機能クエリーの使用
=========

**機能クエリー**は、 CSS の @supports アットルールを使って作成され、ウェブ開発者がある機能に対応しているかどうかを検査し、その検査結果に基づいて実行する CSS を提供する方法として有益です。このガイドでは、機能クエリを使用してプログレッシブエンハンスメントを実装する方法を学びます。

構文
--

CSS の機能クエリーは CSS 条件付きルールモジュールの一部で、ここにはメディアクエリーの @media ルールも含まれてます。機能クエリーを使用すると、メディアクエリーと同様の動作をすることが分かると思います。違いは、メディアクエリーではウェブページが動作している環境について何かを検査するのに対し、機能クエリーでは CSS 機能に対するブラウザーの対応状況を検査する点です。

機能クエリは `@supports` ルールと、それに続く検査したいプロパティ名と値から構成されます。 `display` のようなプロパティ名だけでは検査できません。ルールにはプロパティ名と値が必要です。


```css
@supports (property: value) {
  適用する CSS ルール
}
```


例えば、あるブラウザーが `row-gap` プロパティに対応しているかどうかを確認したい場合、次のような機能クエリーを記述します。多くの場合は、どの値を使用しても問題ありません。ブラウザーがこのプロパティに対応しているかどうかを確認したいだけであれば、有効な値であればどのような値でもかまいません。

特定のプロパティの新しい値を検査する場合は、プロパティと値の組の値の部分がより重要になります。良い例は `display` プロパティでしょう。すべてのブラウザーは `display` に対応しており、`display: block` は CSS1 にまでさかのぼります。しかし、 `display: flex` と `display: grid` はもっと新しい値です。 CSS ではプロパティに追加の値を指定することがよくあるので、プロパティと値を検査するということは、これらの値に対応しているかどうかを検出することができることを意味します。

対応がないかどうかを検査
------------

ブラウザーが機能に対応しているかどうかを尋ねる場合のほか、 `not` キーワードを追加することで逆の検査を行うことができます。


```css
@supports not (property: value) {
  CSS rules to apply
}
```


以下の例の機能クエリー内の CSS は、ブラウザーが `row-gap` に対応していない場合に実行されます。

複数の機能を検査
--------

機能クエリーで、複数のプロパティに対応していることを検査必要がある場合があります。そのような場合は、`and` キーワードで区切って、検査する機能の一覧を記述します。


```css
@supports (property1: value) and (property2: value) {
  CSS rules to apply
}
```


例えば、実行したい CSS が、ブラウザーが CSS シェイプと CSS グリッドに対応していることを必要とする場合、この 2 つを検査するルールを作成することができます。次のルールは、ブラウザーが `shape-outside: circle()` と `display: grid` の両方に対応している場合にのみ true を返します。

`or` を使用することもできます。これは選択したもののうち 1 つが一致した場合に CSS を有効にすることができます。


```css
@supports (property1: value) or (property2: value) {
  CSS rules to apply
}
```


これは、ある機能がベンダー接頭辞付きである場合に特に有用で、標準のプロパティとベンダー接頭辞を加えたものを検査することができます。

機能クエリーの制限
---------

`@support` ルールは、ブラウザーが 1 つ以上のプロパティと値の組を解釈できるかどうか、つまり、その機能に対応していると主張するかどうかを確認するために使用します。もしブラウザーがそのプロパティと値のペアを理解できれば、肯定的な応答を返します。したがって、ブラウザーがある機能に正しく、バグなく対応しているかどうかを確認するために、機能クエリーを使用することはできないのです。

さらに、機能クエリーはは「部分的な実装」を検査することもできません。この良い例が `gap` プロパティです。CSS グリッドに対応しているすべてのブラウザーは、 CSS グリッドの `gap` に対応していますが、フレックスボックスの `gap` に対応しているのは Firefox だけです。フレックスボックスで使いたいからと `gap` プロパティを検査「すると、実装されていないにもかかわらず肯定的な回答を得ることになります。

プログレッシブエンハンスメントのための機能クエリーの使い方
-----------------------------

機能クエリーは、サイトを段階的に拡張していく際に非常に有効なツールです。すべてのブラウザーに対して適切なソリューションを提供し、より新しい機能に対応しているブラウザーにはより高度なソリューションを提供することができます。

しかし、機能クエリーに対応していないブラウザーもあれば、使いたい機能に対応していないブラウザーもあります。例えば、 IE11 で対応していない CSS グリッドを使いたいとします。 IE11 は機能クエリーにも対応していないので、未対応のブラウザーをチェックして代替策を作ることはできません。しかし、実際には、プログレッシブエンハンスメントに機能クエリーを使用する場合、これは重要ではありません。ただし、未対応ブラウザー用の CSS を記述し、それを機能クエリー内の CSS で上書きするようにするなど、一定の方法で CSS を構成する必要があります。

それでは、上記のような方法で機能クエリーを使用する、とても簡単な例を見ていきましょう。

例えば、 3 つのボックスが並んだレイアウトを作りたい場合、理想的にはCSS グリッドレイアウトを使いたいところです。しかし、古いブラウザーのためのレイアウトでは、浮動要素を使ったレイアウトにしたいとします。まずはその浮動レイアウトを以下のコードで作成しすると、 3 列にすることができます。

ブラウザーは CSS のプロパティや値を理解できない場合、それを無視します。そこで、 CSS グリッドを使ってレイアウトを強化することから始めるとよいでしょう。グリッドに対応していないブラウザーは、 `display` プロパティの `grid` の値を無視します。浮動アイテムがグリッドアイテムになると、浮動は取り除かれます。詳細は、古いブラウザーの対応を参照してください。そのため、グリッド版は浮動のものを上書きすればよいのです。

しかし、浮動されたアイテムを 3 列で表示するために使用した `width` プロパティが原因で問題が発生しました。これは、現在、浮動の場合のようにコンテナーの幅ではなく、カラムトラックの幅としてグリッドに解釈されます。

必要なのは、 `display: grid` に対応している場合に、 width を削除する方法です。これはまさに機能クエリーが解決する状況です。グリッドに対応している場合、 `width` を `auto` に戻すことができます。

上記のシナリオでは、 IE11 が機能クエリーや CSS グリッドに対応していなくても問題ありません。浮動版はどの場合でも適用され、グリッドに対応しているブラウザーではそれが上書きされm佐生。

上記のコードを記述する別の方法として、以下のようにグリッドのコードをすべて機能クエリーでラップすることができます。

この場合、コードが少し増えるかもしれませんが、プロパティ名や値名の綴りを故意に間違えることで、代替策をテストできるという利点があります。上記のライブサンプルでは、 `@supports` ルールの `display: grid` を `display: grip` などに変更すると試すことができます。

まとめ
---

機能クエリーは、古いブラウザーで使用されているサイトの表示をよりシンプルに強化することで、新しい機能の利用を開始するのに役立ちます。対応ブラウザー用の CSS をまとめることができるため、上記のグリッドの例のように、代替表示用のスタイルが漏れてしまうリスクもありません。

### 関連情報

* @supports ルール
* レイアウトの学習: 古いブラウザーの対応
* CSS グリッドレイアウトとプログレッシブエンハンスメント
* CSS での機能クエリーの使用