[CSS]これは知らなかった!セレクタを使った条件分岐のテクニック

古いブラウザ用のスタイルシートとモダンブラウザ用のスタイルシートは、どのように分けて記述していますか?

CSSのセレクタだけを使用して、古いブラウザ用とモダンブラウザ用にスタイルシートを条件分岐させるテクニックを紹介します。

サイトのキャプチャ

Using Feature Detection, Conditionals, and Groups with Selectors


下記は各ポイントを意訳したものです。
※当ブログでの翻訳記事は、元サイト様にライセンスを得て翻訳しています。

CSSの新しい機能を使用する時

CSSは、新しい機能をスムーズに追加できるよう設計されています。ブラウザがサポートしていないプロパティ、値、セレクタなどは、無視されるように仕様で設計されており、そのため新しい機能が登場しても古いブラウザで問題を起こさずに使用できます。

例えば、caret-colorという比較的新しいプロパティがあります。機能はinput要素でカーソルのカラーを変えるもので、サポートはまだ少ないです。しかし、サポートが少ないことだけで、そのプロパティを使うべきではないということを意味しません。

ほとんどのブラウザをサポートしているcolorのすぐ後に記述していることに注目してください。この記述方法は、モダンブラウザと古いブラウザを明示的に区別していません。単にサポートされていない機能が無視され、古い機能が適用されるだけです。

このように記述するのは、非常に有用なテクニックです。

新しい機能の検出が必要な時

上記の記述は有用ですが、場合によってはそのフォールバックが新しい機能と大きく異なる場合があります。そんな時には、@supportsが便利です。

@supportsは、特定のプロパティとその値をサポートするブラウザで任意のスタイルを条件付きで適用できます。

@mediaと同じように動作し、条件が満たされた時にのみスタイルを適用します。

@supportsの使い方を説明するために、もう一つ例を見てましょう。
ユーザーがアップロードしたアバターの画像を円状のサークルで表示したいのですが、アップロードされた画像の大きさがサークルに適するか保証はありません。この場合、object-fitプロパティが非常に役に立ちます。ただし、object-fitはIEではサポートされていません。どうしますか?

マークアップから始めます。

まずはフォールバックとして画像の幅を調整し、より広い画像がアバター領域を完全にカバーしないようにします。その代わりに、背景のカラーが表示されます。

実際の動作を見てましょう。
サークルに適していない画像があるのが分かると思います。

See the Pen Demo fallback for object-fit by Jirka Vebr (@JirkaVebr) on CodePen.

これは期待通りではないので、手を加えます。
object-fitを使用すると、画像の最適な位置をブラウザが自動で決めてくれます。つまり、幅・高さを自動的に調整してくれます。

実際の動作を見てましょう。
これで、期待通りに機能します。

See the Pen @supports object-fit demo by Jirka Vebr (@JirkaVebr) on CodePen.

条件セレクタのサポート

Selectors Level 4の仕様はまだワーキングドラフトですが、:placeholder-shownのようにいくつかのセレクタはすでに多くのブラウザでサポートされています。Selectors Level 4では、以前のものよりも多くの新しいセレクタが導入されます。
そのため、CSSのデベロッパーはIEが現役の間、これらのセレクタのサポートで、より多様で揮発性のあるブラウザをターゲットにしなければなりません。

セレクタで、検出を行うことは非常に有用です。
残念なことに、@supportsはプロパティとその値のサポートをテストするためにのみ設計されています。仕様の最新のドラフトでもそれを変更するようには見えません。ただし、将来のバージョンでサポートされる可能性は否定できません。

@supportsに対応するセレクタ

まず、前述のcaret-colorのように、@supportsが必要ないセレクタもあることを強調しておきます。多くのセレクタを明示的にテストする必要はありません。例えば、::selectionにマッチさせるだけで、サポートされていないブラウザについて心配する必要はありません。selectionの外観がブラウザのデフォルトのままであれば、問題ないからです。

そして、セレクタに対する明示的な機能検出が必要な場合もあります。
この記事の残りの部分では、このようなニーズに対処するために、:placeholder-shownを使用して、フローティングラベル付きの入力フィールドをCSSのみで構築します。

フローティングラベル付きの入力フィールド

フローティングラベル付きの入力フィールド

セレクタの基本的なプロパティのグループ

セレクタは重複を避けるために、いくつかの同じ宣言をコンマで区切られたセレクタのリストに集約することができます。これはセレクタのグループと呼ばれています。

2つの同じ宣言をされたセレクタ。

同じ宣言をまとめたセレクタのグループ。

ただし、Selectors Level 3の仕様(Groups of selectors)では、関連するセレクタがすべて有効であるため、これらは同等に扱われます。どいうことかと言うと、グループ内のセレクタのいずれかが無効な場合、グループ全体が無視されるということです。

従って、前のセレクタが無効の場合、セレクタを安全にグループ化することはできませんでした。これらをグループ化すると、ブラウザは後の宣言も無視します。

ブラウザに関する限り、無効なセレクタと新しいバージョンの仕様でのみ有効なセレクタとの間に違いはないことを明示しておくことは重要です。古いブラウザから見ると、それらは両方ともただの無効です。

この仕様を利用して、特定のセレクタのサポートをテストすることができます。必要なのは、一致するセレクタだけです。
例えば、:not(*)を使用してみます。

このスタイルシートで何が起きているのか解説します。
古いブラウザでは最初のルールが正常に適用されますが、残りの部ルールを処理するためには:placeholder-shownを知らないため、グループの最初のセレクタが無効になり、セレクタのグループ全体が無視されます。従って、.fooに一致する要素は「color: red」が適用されます。

新しいブラウザでは、:not(*)(何にもマッチしない)を理解するので、セレクタのグループ全体を無視することはありません。.fooの前のルールを上書きし、「color: green」が適用されます。

これがどのように使用されているか、@supports(または@medi)との類似点に注目してください。最初にフォールバックを記述してから、条件を満たすブラウザに対してのみ上書きします。この場合、特定のセレクタをサポートしていますが、やや複雑な形で記述されます。

See the Pen @supports for selectors by Jirka Vebr (@JirkaVebr) on CodePen.

ラベルは、プレースホルダーが表示されているときはレッド、それ以外のときはグリーン、古いブラウザではブルーになります。

セレクタによる条件分岐の効果的な使い方

:placeholder-shownをサポートしていないブラウザとは別のブラウザをフローティングラベルで入力して使用することができます。これは、非常に重要な疑似クラスを使ったテクニックです。

ここでは簡単にするため、フォールバックは実際のプレースホルダーだけにします。
マークアップから始めます。

これまでのように、ポイントは古いブラウザのスタイルを最初に記述することです。ラベルを隠し、プレースホルダーのカラーを設定します。

モダンブラウザでは、カラーを透明に設定することでプレースホルダーを効果的に無効にできます。プレースホルダーが表示されているときの入力とラベルの相対的な位置合わせも可能です。入力のステータスに合わせてラベルをスタイルするために、兄弟セレクタを利用することもできます。

最後にこのテクニックを使用して、モダンブラウザ用のスタイルを記述します。labelとinputのスタイルと、プレースホルダーが表示されていない状態を上書きします。labelは少し縮小させ、上に移動させます。

実際の動作は、下記で確認できます。

See the Pen CSS-only @supports for selectors demo by Jirka Vebr (@JirkaVebr) on CodePen.

このテクニックを使用するポイントと注意点

このテクニックでは基本的に、何にも一致しないセレクタが必要です。そのため:not(*);を使用しましたが、そのサポートも限られています。ユニバーサルセレクタ(*)はIE7でもサポートされていますが、:not疑似クラスはIE9以降に実装されています。これは、このアプローチが動作する最も古いブラウザです。古いブラウザではセレクタのグループが間違った理由で拒否されます。:notをサポートしていないからです。その代わりに、 .fooなどのclassセレクタやfooなどのtypeセレクタを使用することで、古いブラウザでもサポートできます。しかし、これらのセレクタはコードが読みにくくなるため、現代のほとんどのサイトでは:not(*);が最良の選択肢になります。

わたし達が利用しているセレクタのグループのプロパティが古いブラウザでもサポートされているかどうかについては、その動作がCascading Style Sheets, level 1に例として示されています。さらに、Cascading Style Sheets Level 2では、この動作が明示的に指定されています。この仕様はちょうど、:hoverが導入された時代です。つまり、このテクニックは古いブラウザや不明瞭なブラウザでは広範にテストされていませんが、そのサポートは非​​常に幅広くなければなりません。

最後に、Sassユーザー(SCSSではなく)に注意点があります。
:not(*):placeholder-shownセレクタを使用すると、コンパイラは先頭のコロン(:)を誤認して、プロパティとして解析しようとします。そのためエラーが発生しないように、「\:not(*):placeholder-shown」のようにエスケープして利用してください。
エスケープを使用したくない場合は、「*:not(*):placeholder-shown」のようにセレクタに置き換えてください。Selectors Level 3の仕様にある通り、この場合は暗示されます。

sponsors

top of page

©2018 coliss