🌸

2021年から開発の現場で使える3つの便利CSS - aspect-ratio, gap, is()

commits7 min read

この記事はマネーフォワードアドベントカレンダー2021の13日目の記事です。

ブラウザは日々進化しています。2021年もブラウザには多くの新機能が追加されました。

私はCSSの新機能を1年かけてチェックしてきましたが、その中でもとりわけ便利だと思った3つの機能を紹介します。いずれも、2021年に全モダンブラウザ(Chrome、Firefox、Microsoft Edge、Safari)で使えるようになったもので、日々の開発をラクにしてくれることでしょう。

動画や画像のアスペクト比を指定できるaspect-ratioプロパティ

aspect-ratioプロパティとは、ボックスのアスペクト比(幅と高さの比率)を指定するプロパティです。

構文
aspect-ratio: アスペクト比率

▼ 簡単な例

/* .box要素のアスペクト比を4:3にする */
.box {
  aspect-ratio: 4 / 3;
}

説明

次のように、YouTube動画のアスペクト比率を16:9に固定する例を考えます。

動画部分は、iframeで表示されています。

<iframe src="動画URL"></iframe>

昔の方法: padding-topと絶対配置

昔は、iframeのラッパー要素を作り、padding-top: 56.25%;(もしくはpadding-top: calc(100% * 16 / 9); を指定し、iframeabsoluteで絶対配置する必要がありました。

<div class="wrapper">
  <iframe
    class="video"
    src="動画URL"
  ></iframe>
</div>
.wrapper {
  position: relative;
  padding-top: 56.25%;
}

iframe {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
}

2021年の方法: aspect-ratioを使う

aspect-ratioプロパティを使うと、ラッパー要素や絶対配置は不要で、iframeaspect-ratioプロパティを指定するだけで、アスペクト比が固定されます。

iframe {
  aspect-ratio: 16/9;
  width: 100%;
  height: 100%;
}

私はウェブ業界に入った頃から前述のpadding-topによるハックを使っていましたが、なんでこんな面倒くさいことをしなければならないんだろう?🤔とずっと疑問に思っていました。aspect-ratioの登場で、直感的にアスペクト比を指定できるようになり助かっています。

デモはつぎのとおりです。新しいタブでデモを開くとわかりやすいのですが、YouTubeの動画が画面サイズがウインドウいっぱいに広がりつつ、アスペクト比が16:9に保たれています。

aspect-ratioの対応ブラウザ

aspect-ratioプロパティは、2021年9月に登場したSafari 15が対応したことで、全モダンブラウザで使えるようになりました。

https://twitter.com/tonkotsuboy_com/status/1440137120186699780

Flexboxでgapプロパティを使う

gapプロパティとは、行や列の隙間を指定するためのプロパティです。昔はCSS Gridのアイテムに対してのみ有効でしたが、2021年からはFlexboxのアイテムに対しても使えるようになりました。

構文
gap: 間隔

▼ 簡単な例

/* .container要素内のアイテムの隙間を10pxにする */
.container {
  display: flex;
  gap: 10px;
}

説明

次のように、Flexboxで配置したボックスに対して、16pxの隙間を空けることを考えましょう。

HTMLは次のようになっています。

<div class="container">
  <div class="box"></div>
  <div class="box"></div>
  <div class="box"></div>
  <div class="box"></div>
  <div class="box"></div>
  <!-- 中略 -->
</div>

昔の方法: marginを使う

昔は、marginを使って次のように指定していました。最初や最後のアイテムのmargin0にする、コンテナにネガティブマージンを使うなど、調整する必要があります。また、複数行になった場合には、最初の行や最後の行でのmarginの調整も必要で、煩雑でした。

.container {
  display: flex;
  margin-left: -8px;
  margin-right: -8px;
}

.box {
  margin-left: 8px;
  margin-right: 8px;
}

.box:first-child {
  margin-left: 0;
}

2021年の方法: gapプロパティを使う

Flexboxのgapプロパティを使えば、次のように記述できます。スタイルの指定はコンテナーに対してだけであり、marginのときのようにアイテムに個別のスタイルを指定する必要はありません。複数行のときも然りです。

.container {
  display: flex;
  gap: 16px;
}

私は単一行レイアウトではFlexbox、複数行レイアウトではCSS Gridという使い分けをしているのです。しかし、昔はアイテムの隙間を空けたいケースにおいてはFlexboxではなくCSS Gridを使っていました。前述のように、marginpaddingで隙間を空けようとすると、最初の要素や最後の要素の調整が煩雑だったためです。Flexbox用のgapプロパティが登場したことにより、単一行レイアウトでも気兼ねなくFlexboxが使えるようになり、助かっています。

デモはこちら。ボックス間の隙間が16pxになっています。

Flexbox用gapの対応ブラウザ

Flexbox用gapプロパティは、2021年4月に登場したSafari 14が対応したことで、全モダンブラウザで使えるようになりました。

https://twitter.com/tonkotsuboy_com/status/1386886571710816256

セレクターリストをまとめてスタイルをあてる :is()擬似クラス

is擬似クラスとは、引数のセレクタリストに合致する要素を選択できる擬似クラスです。

構文
.foo:is(.bar, .baz) {}

▼ 簡単な例

/* section要素、nav要素、main要素内のh1のテキスト色を赤色にする */
:is(section, nav, main) h1 {
  color: red;
}

説明

次のように、ホバー時とカレント時に、文字色をwhite、背景色を#333333にすることを考えてみましょう。

https://www.youtube.com/watch?v=j5VG43nNq_k

リンク部分のHTMLは次のようになっています。

<ul class="link-list">
  <li>
    <a class="link current" href="#">
     ホーム
   </a>
  </li>
  <li>
    <a class="link" href="#">探索</a>
  </li>
  <!-- 中略 -->
</ul>  

JavaScriptでは、カレント状態のa.link要素に対して、.current クラスが付与されるようになっています。

昔の方法: 別々に書く

.link-list内のaの、:hover.currentに対して同じスタイルを指定したい場合、従来は次のように指定していました。

.link-list .link:hover,
.link-list .link.current {
  color: white;
  background-color: #333333;
}

2021年の方法: :is()を使ってセレクタリストをまとめる

:is()を使うと、次のようにセレクタリストをまとめられます。

.link-list .link:is(:hover, .current) {
  color: white;
  background-color: #333333;
}

デモはこちら。リンクを押すと.linkのカレント状態が変わり、カレント状態のスタイルはホバー時のスタイルと同じになります。

詳細度が常に0:where()

:is()と似た疑似クラスで、:where()があります。:is()()内の詳細度になるのに対し、:where()の詳細度はつねに0です。

次の:is()の例では、div aredになります。

:is(div.foo a) {
  color: red;
}

div a {
  color: blue;
}

次の:where()の例では、div ablueになります。

:where(div.foo a) {
  color: red;
}

div a {
  color: blue;
}

:not()でもセレクタリストが指定できるように

:not()でもセレクタリストが指定できるようになりました。

個人的にはこの機能がありがたいです。.foo.barではない要素に対してスタイルを設定するというケースは多かったものの、昔は:not()の引数としてセレクタリストを取れずに不便に感じていました。現在はラクです。

/* ホバーされておらず、.currentも付与されていないa要素に対してスタイルを指定 */
a:not(:hover, .current) {
  color: red;
}

:is():where()・セレクタリストをとる:not()の対応ブラウザ

:is():where()・セレクタリストをとる:not()は、2021年1月に登場したChrome 88が対応したことで、全モダンブラウザで使えるようになりました。

細かいことを言うと、:is():where()はSafari 15以前から対応していましたが、Forgiving Selectorに対応したのは15からです。

新しいCSSで便利に開発しよう

aspect-ratioプロパティ、Flexbox用gapプロパティ、:is()擬似クラスは、いずれも昔の煩雑なCSSの記述をラクにしてくれるものです。シンプルなコードになれば、バグの発見がしやすくなり、他の開発者も読みやすくなることでしょう。

今回紹介したCSSの機能以外にも、便利なCSSはどんどん追加されていきます。当たり前だと思っていたCSSの知識を見直し、新しくて便利なCSSをキャッチアップしていきましょう。

GitHubで編集を提案

この記事に贈られたバッジ

Discussion

ログインするとコメントできます