logo
コーディング

更新日

CSSの@supportsを使ってCSSのみでスタイルの条件分岐をする方法

Webブラウザーによって表示可能なCSSが異なるのは、よく知られていることです。例えばChromeやSafariでは問題なく表示される filter は、Internet Explorerではうまく表示されず、別のスタイルを用意しなければいけません。今回は @supports を使って対応しているプロパティー別にスタイルを変更してみましょう。

@supports とは?

指定した (プロパティー:値) の条件に対応しているブラウザーには {} 内に書かれたスタイルを適用するよ、というもの。新しいスタイルの書き方に対応しているブラウザーにはそれを、対応していないブラウザーには従来の書き方で、かつ見栄えの崩れないようにコンテンツを提供できるよう、CSS を記述していけます。「プログレッシブエンハンスメント」というやつですね。

有名な JavaScript ライブラリー「Modernizr」の役割を、CSS でやってのける、というわけです!

@supports に対応しているブラウザー

Can I use…を見ると、IE 以外のモダンブラウザーに対応しています。そのため、基本的に IE 用に CSS を書き、ブラウザーごとに対応状況の異なるスタイルに @supports を使って対応させるとよいでしょう。

@supports の記述方法

まずは簡単な例を。以下のコードを CSS ファイルに記述すると、Flexbox に対応しているブラウザーには Flexbox を適用させます。Flexbox って何?という人は、過去記事「これからの CSS レイアウトは Flexbox で決まり!」を読んでみてくださいね!

@supports (display: flex) {
  .flexbox {
    display: flex;
  }
}

not、and、or も使える

not (プロパティー:値) を使うと、それに対応していないブラウザーに向けてスタイルを指定できます。以下の例では、Flexbox に対応していないブラウザーには従来どおり float を使ってコンテンツを横並びにしています。

@supports not (display: flex) {
  .flexbox {
    overflow: hidden;
  }
  .flexbox div {
    float: left;
  }
}

and は「指定した複数のスタイルの、どちらにも対応している場合のみ」を条件に指定できます。

@supports (animation: example 2s infinite) and (transform: rotate(-45deg)) {
  /* ここにCSSが入ります */
}

or は「指定した複数のスタイルの、どちらかに対応している場合」を条件に指定できます。同じスタイルに対して複数のベンダープレフィックスを指定する場合等に使えます。

@supports (display: flex) or (display: -webkit-flex) {
  /* ここにCSSが入ります */
}

注意点 1:スペースが必要

notandor を使う場合は、その前後にスペースが必要です。 (display: flex)or(display: -webkit-flex) ではうまく動作しません。

/* 良い例 */
@supports (display: flex) or (display: -webkit-flex) {
  /* ここにCSSが入ります */
}

注意点 2:カッコが必要

条件にする プロパティー:値 は必ずカッコ () で囲みます。

/* 悪い例 */
@supports display: flex {
  /* ここにCSSが入ります */
}

/* 良い例 */
@supports (display: flex) {
  /* ここにCSSが入ります */
}

@supports を使った実例

実際にどんな場面で使えるのか、実例を紹介します。

1. iOS 風に下に重なったコンテンツをぼかす

下のレイヤーにある画像やテキストなどのコンテンツをぼかして、上のレイヤーを目立たせるという、iPhone ユーザーにはお馴染みのエフェクト。JavaScript 等を使って様々なスニペットが公開されていますが、現在 Safari にのみ対応している backdrop-filter が一番簡単です。

ただし、Safari 以外のブラウザーだと適用されないので、この例では Safari 以外のブラウザーはぼかしなしで、背景色である白の不透明度を高くしています。

header {
  padding: 5px 0;
  position: fixed;
  top: 0;
  width: 100%;
  background: rgba(255, 255, 255, 0.9);
}

@supports (-webkit-backdrop-filter: blur(5px)) {
  header {
    -webkit-backdrop-filter: blur(5px);
    background: rgba(255, 255, 255, 0.5);
  }
}

サンプルをスクロールしてみてください。Safari で見ると後ろの画像やテキストがぼかされてますね!早くすべてのブラウザーに対応してくれますように!

2. グラデーションのテキスト

テキストの色をグラデーションにするには、テキスト要素の背景をグラデーションカラーにし、テキストでマスクをかける方法を使います。しかし、マスクをかけるには Safari と Chrome で使える background-clip を利用するので、対応していないブラウザーには普通の塗りつぶし色を適用させましょう。

.gradient-text {
  color: #e55d87;
}

@supports (-webkit-background-clip: text) or (background-clip: text) {
  .gradient-text {
    background: linear-gradient(90deg, #e55d87 10%, #5fc3e4 90%);
    color: transparent;
    -webkit-background-clip: text;
    background-clip: text;
  }
}

同じプロパティーと値を繰り返し記述するのはなんだかスマートではないのですが、JavaScript に頼らず実装できるのは利点かなーと思います。もちろんサイトによってはこれがベストな書き方とは言えないかもしれません。「こんな書き方もあるよー」ということで、ぜひ試してみてください!