全モダンブラウザ対応のCSS機能が爆増。Chromium版Edgeのもたらす次世代CSS表現

362
445
285

2020年初め、Chromium版のMicrosoft Edge(以下新Edge)がリリースされました。新Edgeは「Microsoft Edge Legacy」(以下Edge Legacy)と比べて多くの機能が使えるようになっており、Chrome・Firefox・Safariのモダンブラウザと遜色ないレベルになっています。

先日5月29日にリリースされた「Windows 10 May 2020 Update」では、Edge Legacyの開発が終了することもアナウンスされており(参考記事「Windows 10 features we’re no longer developing - Windows Deployment」)、今後のWindows標準ブラウザは新Edgeとなっていくでしょう。

ウェブ制作の面で嬉しいことは、多くのCSSやJavaScriptの機能が使えるようになったことです。

新Edgeで多くの機能が使えるようになったことで、全モダンブラウザで使える機能もぐっと増えました。本記事では、その中でもとくに便利なCSSの機能についてピックアップして紹介します。いずれも新Edge、Google Chrome、Firefox、Safariの全モダンブラウザで使える機能です。

記事末尾では、ピックアップしたもの以外で全モダンブラウザで使えるようになったCSSの新機能についても紹介しています。

clearfixによる回り込み解除がいらなくなるdisplay: flow-root

displayプロパティのflow-root値とは、要素のブロック整形コンテキスト(block formatting context、BFC)を作成するための値です。clearfixを使うことなくフロートの回り込み解除ができます。

次のようにして使います。

.container {
  display: flow-root;
}

次のようなレイアウトを実装するケースで考えてみましょう。画像が2つ横並びになっていて、その後にテキストが続いています。

HTMLコードは次のような形です。

<div class="container">
  <div class="box1"><img src="images/photo_1.jpg" alt="" /></div>
  <div class="box2"><img src="images/photo_2.jpg" alt="" /></div>
</div>

<p>吾輩は猫である。名前はまだ無い。(中略)</p>

画像の横並び部分はfloatプロパティを使ってレイアウトします。

.box1 {
  float: left;
}

.box2 {
  float: right;
}

floatプロパティにより要素をフロート(左寄せ・右寄せ)にする場合は、後続の要素がフロートされた要素が重なってしまいます。従来は、この問題を解決するためにはclearfixなどが使われてきました(参考記事「floatを解除する手法のclearfix と 次世代のレイアウトの話 | Web Design KOJIKA17」)。

▼ clearfixの例

.container:after {
  content: "";
  clear: both;
  display: block;
}

display: flow-rootを使えば、clearfixを使うことなくフロートの回り込み解除ができます。

.container {
  display: flow-root;
}

実行結果は次のとおりです。

display: flow-rootの対応ブラウザは次のとおりです(「Can I use…」より)。

子孫要素にフォーカスがあたっているときのスタイル設定に便利な:focus-within疑似クラス

:focus-withinとは、自分自身または子孫要素にフォーカスがあたっている要素を示すための擬似クラスです。入力フォームで、子孫要素にフォーカスがあたっときに自分自身のスタイルを変えたいときに便利です。

次のようにして使います。

:focus-within擬似クラスの使い方

.container:focus-within {
  background-color: red;
}

:focus-within擬似クラスは、フォーム要素のフォーカス時のスタイル設定に便利です。次のような入力フォームで、テキスト入力要素にフォーカスをあてたときに背景のスタイルを変えるUIを考えてみましょう。

HTMLコードは次のようにしました。

▼ HTMLコード

<label>名前<input type="text"/></label>
<label>住所<input  type="text"/></label>
<label>メールアドレス<input  type="text"/></label>

input要素にフォーカスがあたった時にlabel要素全体にスタイルをあてたいのですが、ラジオボタンの:focus擬似クラスはinput要素そのものしかスタイルをあてることはできません。

▼ フォーカスがあたったときのスタイルは、input要素にしか設定不可能

input:focus {
 /* フォーカスがあたったときのスタイル */
}

よって、目的のレイアウトを実現したければ、JavaScriptを用いてinput要素のフォーカスイベントをキャッチしてlabel要素のスタイルを変更するという冗長な手段が取られてきました。

:focus-within擬似クラスを使えば、input要素にフォーカスがあたった状態を、その親要素であるlabel要素で検知ができるので、JavaScriptを使わず目的のスタイル設定が可能です。

input要素にフォーカスがあたったとき、label要素全体にスタイルを付与するCSSコード

label:focus-within {
  background-color: rgb(221, 255, 69);
}

実行結果は次のとおりです。各フォーム要素に使えるので、フォーカス時のスタイル設定がラクになる機能です。

:focus-within擬似クラスの挙動については、新EdgeやGoogle ChromeのDevToolで確認できます。CSSを記述する際の参考にするとよいでしょう。

▼ 新EdgeのDevToolで:focus-within擬似クラスをチェックしている様子

:focus-within擬似クラスの対応ブラウザは次のとおりです(「Can I use…」より)。

2つの値のどちらか小さい値を使いたいときのmin()関数

min()関数は、2つの値のどちらか小さい方を使いたいときのための関数です。最大値または最小値を一括で指定したいときに役立ちます

次のようにして使います。「画像のwidth(横幅)について、700px100%のうちどちらかを使ってください」という意味になります。

min()関数の使い方

img {
  width: min(700px, 100%)
}

次のようなレイアウトを実装するケースで考えてみましょう。画像の横幅はウインドウサイズに応じて伸び縮みしますが、最大で700pxまでしか伸びないレイアウトです。

HTMLコードは次のようにしました。

<img
  src="images/piyopiyo.svg"
  alt=""
/>

従来のコードでは、次のようにmax-widthwidthを別々に指定する必要がありました。

▼ 従来のコード

img {
  width: 100%;
  max-width: 700px;
}

min()関数を使うと、次のように一行で済みます。

img {
  width: min(700px, 100%);
}

次のような仕組みにより、前述のmax-widthwidthを組み合わせたときと同じ挙動となっているのです。

  • 画面サイズが700px以下のとき、100%のほうが小さいので、100%の値が採用され、画像横幅は100%になる
  • 画面サイズが700px以上のとき、700pxのほうが小さいので、700pxの値が採用され、画像横幅は700pxになる

実行結果は次のリンクより確認できます。ウインドウサイズを拡縮すると、挙動がわかりやすいでしょう。

類似の関数として、max()関数やclamp()関数も使えるようになりました。

  • max(A, B):A, Bの値のうち、どちらか大きい方を採用する
  • clamp(A, B, C):A以上C以下のB。max(A, min(B, C))と同じ意味

min()関数の対応ブラウザは次のとおりです(「Can I use…」より)。

CSS Gridでのレイアウトがラクになるdisplay: contents

displayプロパティのcontents値とは、自分自身がボックスを生成せず、その子要素(と疑似要素)はボックスを生成するものです。CSS Gridでのレイアウト時、セマンティックなタグ付けを行いつつもCSS Gridのレイアウトを適用したいときに便利です

次のようにして使います。

display: contentsの使い方

.box {
  display: contents;
}

display: contentsはCSS Gridと組み合わせると便利です。次のようなレイアウトを実装するケースで考えてみましょう。各テキストと画像はリンク要素の想定です。

HTMLコードは次のようにしました。

▼ HTMLコード

<div class="container">
  <a href="#">
    <h2>雪三桜</h2>
    <img src="images/photo_1.jpg" alt="" />
  </a>
  <a href="#">
    <h2>ゴードンの歩道橋</h2>
    <img src="images/photo_2.jpg" alt="" />
  </a>
  <a href="#">
    <h2>セントラルガーデン<br />※ 品川駅</h2>
    <img src="images/photo_3.jpg" alt="" />
  </a>
</div>

各要素は横並びなので、CSS Gridを使って次のような2行3列のCSSコードにしたいところです。

▼ CSSコード

.container {
  display: grid;
  justify-content: center;
  grid-template:
    repeat(2, auto) /
    repeat(3, 1fr);
  gap: 10px 20px;
  grid-auto-flow: column;
}

しかし、CSS Gridによるレイアウトは子要素にのみ適用されるので、a要素が邪魔で意図どおりにレイアウトされません。

▼ 意図どおりにレイアウトされないCSS Grid

この問題を解決するため、h2タグとimgタグをaタグで囲む冗長なコードもしばしば見受けられます。

▼ CSS Gridのレイアウトを適用するために作り出した冗長なHTMLコード

<div class="container">
  <a href="#">
    <h2>雪三桜</h2>
  </a>
  <a href="#">
    <img src="images/photo_1.jpg" alt="" />
  </a>
  <a href="#">
    <h2>ゴードンの歩道橋</h2>
  </a>
  <a href="#">
    <img src="images/photo_2.jpg" alt="" />
  </a>
  <a href="#">
    <h2>セントラルガーデン<br />※ 品川駅</h2>
  </a>
  <a href="#">
    <img src="images/photo_3.jpg" alt="" />
  </a>
</div>

a要素に対してdisplay: contentsを指定すると、あたかもa要素の見た目が消えたかのようにふるまいます。CSS Gridのアイテムはh2要素とimg要素となり、正しくレイアウトされます。

a要素にdisplay: contentsを指定

a {
  display: contents;
}

実行結果は次のとおりです。a要素についても見栄え上消えただけなので、正しくリンクとして機能します。このように、display: contentsはHTMLの文書構造を保ちつつ、CSS Gridによるレイアウトを行うのに強力な機能です

display: contentsの対応ブラウザは次のとおりです(「Can I use…」より)。

ダークモードの判別に便利なprefers-color-scheme

prefers-color-schemeとは、ユーザーが明るいカラースキームを好むか、暗いカラースキームを好むかを検知できるメディアクエリです。明るいカラースキームとは明るい背景と暗いテキスト、暗いカラースキームとは暗い背景と明るいテキストを指します。ユーザーのOSがダークモードかライトモードかでCSSのスタイルを変えたいときに便利です。

次のようにして使います。

prefers-color-schemeの使い方

@media (prefers-color-scheme: dark) {
  /* ダークモードの場合のみ適用されるスタイル設定 */
}

次に示すのは、OSがダークモード(※ Androidではダークテーマ)か否かで背景色とテキストの色が変わるサンプルです。OSの設定が非ダークモードの場合は背景が#f9f9f9・文字色が#000000、OSの設定がダークモードの場合は背景が#333333・文字色が#ffffffとなります。

▼ ダークモードでスタイルが変わるサンプル

body {
  background-color: #f9f9f9;
}

h1, 
body {
  color: #000000;
}

@media (prefers-color-scheme: dark) {
  body {
    background-color: #333333;
  }

  h1, p {
    color: #ffffff;
  }
}

OSの設定に応じて、背景色とテキストの色が変わっていることがわかります。

▼ ダークモードでスタイルが変わるサンプル

prefers-color-schemeでのダークモード切り替えをチェックする場合は、新EdgeやGoogle ChromeのDevToolを使うと便利です。

prefers-color-schemeの対応ブラウザは次のとおりです(「Can I use…」より)。

ピックアップしたもの以外で全モダンブラウザで使えるようになったCSSの新機能

本記事で解説したCSSの新機能以外に、全モダンブラウザで使えるようになったCSSの新機能について紹介します。

  • text-orientationプロパティ:縦書きのテキストで、文字の向きを指定するためのプロパティ
  • will-changeプロパティ:変更するスタイルをあらかじめブラウザに伝えるためのプロパティ
  • font-variant-numericプロパティ:数字、分数、序数の表記を指定するためのプロパティ
  • CSS論理プロパティ(CSS Logical Properties):論理的方向と次元を通じて、レイアウトを制御するためのプロパティ
  • font-displayプロパティ:@font-faceの中で指定し、ダウンロード可能なフォントがダウンロードされる前にどのように表示されるのかを指定するプロパティ
  • image-renderingプロパティ:画像を拡大縮小する場合のアルゴリズム
  • caret-colorプロパティ:テキスト入力エリアでのカレットの色を指定するプロパティ
  • mix-blend-modeプロパティ:要素をかさねたときの見え方を指定するプロパティ(記事「新プロパティmix-blend-modeを使いこなそう」で詳しく解説しています)
  • background-blend-modeプロパティ:要素の背景をどのようにブレンドするかを指定するプロパティ
  • allプロパティ:要素のプロパティをリセットするためのプロパティ
  • CSS scrollbar styling:スクロールバーのスタイルを指定するための機能
  • env()変数:safe-area-inset-top()のような環境変数を取り扱う
  • :placeholder-shown疑似クラス:プレイスホルダーが表示されている場合の要素を示す
  • :default疑似クラス:デフォルトでチェックされている要素を示す(例:ラジオボタン、チェックボックス)

現場で使えるようになったCSSの新機能を使いこなそう

モダンブラウザは日々進化を続けています。便利なCSSもどんどん使えるようになっているので、これまで当たり前だと思っていた機能を見直すことで、より効率的に開発が可能になります。

「どうせIE11で使えないから…」と思う方もいるかもしれません。しかし、IE11で使えないからと言って新しい技術を学ばないのはもったいないです。開発の現場ではIE11をサポート対象外とするプロジェクトも増えてきており、IE11を言い訳に新しい技術を学ばないのは大きな機会損失と言えるでしょう

新Edgeで使えるようになったCSSの新機能を使いこなしつつ、楽しく制作をしましょう。