ベンダープレフィックスの順序

CSS3を扱う上でベンダープレフィックスの話題は外せません。
そのベンダープレフィックスの順序について書いてみます。

ベンダープレフィックスとは

ベンダープレフィックス(vendor prefix)は、ブラウザが独自の拡張機能を実装、勧告候補前の仕様を先行実装する場合に、 将来的に仕様が変更されるリスクに備えて、プロパティや値につけられる識別子のことです。
その識別子は、ベンダー識別子(vendor identifier)によってブラウザの種類が付けられています。

主要なブラウザのベンダープレフィックス

-webkit-
Google Chrome、Safari、(Opera)
-moz-
Firefox
-ms-
Internet Explorer
-o-
Opera

ただしCSS3などの仕様が勧告候補になった場合には、ブラウザベンダー側がベンダープレフィックスを外すことが推奨されています。
Firefoxなどに関しては、ベンダープレフィックスが外されてプロパティがサポートされると、今までベンダープレフィックス付きで動いていたものが、逆に動かなくなる可能性もあります。
そのためサポートされたプロパティを指定する必要があります。
以後、「ベンダープレフィックスなしのプロパティ」を「サポートされたプロパティ」と明記します。

以下は、ボックスの角を丸くするプロパティの border-radius を使用した時のFirefoxの例です。

.foo {
  -moz-border-radius: 2px;
  /* Firefox 3.6 までは動くが、Firefox 4以降は動かない */
}
.foo {
  border-radius: 2px;
  /* Firefox 4以降は動く */
}

多くの人がベンダープレフィックスの付いたCSS3を利用していると思いますが、それはあくまで独自の拡張機能や、仕様を先行実装した機能であり、仕様が確定していないCSS3を使用する場合は、必ずサポートされたプロパティをセットしておいた方が良いでしょう。

ベンダープレフィックスが先か、サポートされたプロパティが先か。

「サポートされたプロパティをセットしておいた方が良い」といわれても、ベンダープレフィックスと、サポートされたプロパティのどちらを先に書けば良いのか。

どちらを先に書いてもほとんどが正常に動きます。
もっというなら、ベンダープレフィックスの中に、サポートされたプロパティが紛れていてもほとんどが動きます。

例えば、以下のプロパティをFirefox 3.6で見たとします。
先ほど紹介したようにFirefox 3.6の border-radius は、-moz- のプレフィックス付きのプロパティしか認識しません。
この時ブラウザの動きは、-moz- 以外のベンダープレフィックスを不明なプロパティとして無視されるようになっています。

.foo {
  width: 100px; /* 認識 */
  -o-border-radius: 2px; /* 無視する */
  border-radius: 2px; /* 無視する */
  -moz-border-radius: 2px; /* 認識 */
  -webkit-border-radius: 2px; /* 無視する */
  -ms-border-radius: 2px; /* 無視する */
}

結果、上記のコードはFirefox 3.6の場合において下記のプロパティしか読まれていないことになります。

.foo {
  width: 100px;
  -moz-border-radius: 2px;
}

もしFirefox 3.6がサポートされたプロパティも認識できると仮定した場合は、どうなるでしょうか。

.foo {
  width: 100px;
  border-radius: 2px;
  -moz-border-radius: 2px;
}

読めるプロパティが増えただけで、プレフィックスがあってもなくても、「角を2pxだけ丸くしろ」と指示しているだけなので、表示の結果は変わりません。

どちらを先に書いても結果は変わりませんが、私はサポートされたプロパティを、最後に書いてほしいと思います。

サポートされたプロパティを最後に書く理由

CSSの基本をおさらいします。
以下のCSSで、最終的に反映される値は、blue と red のどちらでしょうか。

.foo {
  color: blue;
}
.foo {
  color: red;
}

答えは、red です。
CSSは上から読まれていき、詳細度が同じなら、下にあるプロパティが優先されます。
そして下記のコードも、上記のコードと同様の結果が得られます。

.foo {
  color: blue;
  color: red;
}

CSSは上から読まれていき、同列の詳細度の場合は、最後に書かれたプロパティがその結果となります。
これはベンダープレフィックスにも当てはまります。
ベンダープレフィックスは、独自の拡張機能や仕様を先行実装した機能であり、勧告候補になればベンダープレフィックスを外すことが推奨されています。

サポートされたプロパティの方が優位に立つべきプロパティであり、最終的に認識されるプロパティに相応しいと思います。
そのためにプロパティの最後の結果となりやすいよう、最後に書くことが望ましいといえるでしょう。

.foo {
  -moz-border-radius: 4px;
  -webkit-border-radius: 4px;
  border-radius: 4px; /* 最終的にはこのプロパティを優先したい */
}

ベンダー識別子の順序

ベンダープレフィックスとサポートされたプロパティの順序は決まりました。
次は、-webkit- や -moz- などのベンダー識別子の順序です。
並べる順序は、いくつか提案できるでしょう。

  1. ベンダー識別子の文字数の小さい順
    .foo {
      -o-border-radius: 4px;
      -ms-border-radius: 4px;
      -moz-border-radius: 4px;
      -webkit-border-radius: 4px;
      border-radius: 4px;
    }
  2. よく使用しているブラウザ順
    .foo {
      -o-border-radius: 4px; /* Opera最強伝説 */
      -webkit-border-radius: 4px;
      -moz-border-radius: 4px;
      -ms-border-radius: 4px;
      border-radius: 4px;
    }
  3. ジェネレーターで吐き出された順

正直、私自身はこの順序に関しては、環境や好みに合せて、好きな順序にすれば良いと思います。

ただプレフィックスを扱う上で、「CSS3だからプレフィックスを全部付けとけ」。 こういった流れは歓迎しません。

以下の表を見てください。
ブラウザのバージョンと border-radius の対応表を抜粋したものです。

引用元: caniuse / features-json / border-radius.json - Github

IE Firefox Chrome Safari Opera iOS
Safari
Android
Browser
8:
未対応
3.6:
-moz-
4:
-webkit-
3.2:
-webkit-
10.0-10.1:
未対応
3.2:
-webkit-
2.1:
-webkit-
9:
対応
4:
対応
5:
対応
4:
-webkit-
10.5:
対応
4.0-4.1:
対応
2.2:
対応
10:
対応
5:
対応
6:
対応
5:
対応
10.6:
対応
4.2-4.3:
対応
2.3:
対応

数字がブラウザのバージョンです。
その下に、対応、未対応、ベンダー識別子(サポートしていないが、プレフィックスを付ければ使用できる)の3つで分けています。

上の表から読み取れることがいくつかあります。
IEとOperaに関して、先行実装を行わずに border-radius がサポートされている点。
これは、border-radius の場合は -ms- と -o- を付けても意味が無いことを示します。

さらにFirefox 4から、 border-radius がサポートされている点。
この記事を書いている現時点のFirefoxのバージョンは19です。
記事を読まれている方の判断にも任せますが、最新のFirefoxをターゲットにするのであれば、-moz- は外してしまっても良いと思います。

-webkit- も同様です。
PCのChromeとSafari。そしてモバイルに関しても、iOS 3.2、初代Xperiaなどに代表されるAndroid 2.1を使用している人も稀でしょう。

先ほど書いていた border-radius をおさらいしましょう。

.foo {
  -o-border-radius: 4px;
  -ms-border-radius: 4px;
  -moz-border-radius: 4px;
  -webkit-border-radius: 4px;
  border-radius: 4px;
}

ある程度アップデートされたブラウザから見ることを想定した場合は、先ほどの点を踏まえると、そもそもベンダープレフィックスが必要ないといえます。

.foo {
  border-radius: 4px;
}

まとめ

冒頭にもいいましたが、ベンダープレフィックスは独自の拡張機能や仕様の先行実装であり、仕様の変更やマイナーなプロパティであれば削除される可能性も少なからずあります。

その教訓となるのが仕様変更によってカオスになってるといわれる、グラデーションの構文やFlexible Boxなどではないでしょうか。

特にCSS3のグラデーションはジェネレーターが多く出ていますが、幾度かの仕様が加わっているので、最新のグラデーションの構文に対応したジェネレーターを使用すべきです。
そうでないと、最新のブラウザではグラデーションの方向が意図とは異なる方向になることもありえます。

クロスブラウザな css3 linear-gradient が面倒になりそうな件について - ほむらちゃほむほむ

定期的に Can I use... などで、プロパティのサポート状況や仕様などを確認することをおすすめます。
そうすることで CSS3 や CSS4 と、さらにうまく付き合っていくことができるのではないでしょうか。