CSSは日々進化している!知ったら使いたくなる「モダンCSS」機能紹介

2024年5月13日

執筆

山内 直

有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)に所属するテクニカルライター。出版社を経てフリーランスとして独立。ライター、エディター、デベロッパー、講師業に従事。屋号は「たまデジ。」。著書に『Bootstrap 5 フロントエンド開発の教科書』、『作って学べるHTML+JavaScriptの基本』など。

 

監修

山田 祥寛

静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。
主な著書に「独習」シリーズ「これからはじめるReact実践入門」「改訂3版 JavaScript本格入門」他、著書多数

新発見!フロントエンド技術の今」の連載。第5回のテーマは「モダンCSS」です。

モダンCSSを取り巻く環境

「モダンCSS」とは何でしょうか? 近年、「モダン」を冠した言葉をよく見かけますが、CSSについては「新しいCSSの機能」と捉えておけば良さそうです。「新しい」というのも漠然としていますが、本記事では以下のように定義したいと思います。

この数年で策定された新しい仕様でCSSの使い勝手や効果を大きく変えるもの

モジュールとバージョンで管理される「モダンCSS」

実は、「CSS3」のような仕様は正式には存在しません。現在のCSSは、その機能ごとに分けられた「モジュール」毎に、「レベル」という概念でバージョニングされて管理されています。例えば、CSS Selector Level 3、Media Queries Level 4といった具合です。そして、年に1回、「スナップショット」として標準化の状況が公開されます。

このため、「CSSのバージョン○○に準拠」というように明確な対象を限定できません。常に、新しく策定される仕様に対して対応しているいないか、確認しながら開発を進めていくような状況になります。実際の開発では、ブラウザのサポート状況をまとめているサイト、例えば「Can I use… Support tables for HTML5, CSS3, etc」などに確認したいことを打ち込んで、使用する必要があります。

▲Can I use... Support tables for HTML5, CSS3, etc

皆が知っていて使われている新しいCSS

新しいCSSですが、具体的にどのようなものがあるか、大づかみするために役立つのが「State of CSS」です。開発者向けにCSSの最新トレンドを毎年調査しているサイトで、本稿作成時点の最新は2023年版になります

▲State of CSS 2023: FEATURES OVERVIEW

このサイトの「FEATURES」(機能)には、CSSの新しい機能の「知っている」(Awareness)と「使っている」(Usage)がまとめられているので、「皆が知っていて、しかも使われている機能」「知られてはいるけど、使われていない機能」などが一目瞭然です。

▲「Awareness」✕「Usage」。皆が知っていて、しかも使われている機能

まず、「皆が知っていて、しかも使われている機能」を上記の表にピックアップしてみました。いずれも便利そうな機能です。機能自体は以前から存在していましたが、ブラウザのサポートが進んで一気に使われ出したという位置付けです。

Flexbox
Flexboxは、Flexbox Moduleでサポートされるレイアウトのための機能です。その名(Flexible Box)の通り、非常に柔軟性の高いレイアウトを実現します。従来は、テーブルやCSSのfloatプロパティを駆使していたようなレイアウトを、簡単なプロパティの設定だけで実現できるのが特徴です。

知られてはいるけどあまり使われていないCSS

次に、「知られてはいるけど、使われていない機能」は、興味関心はあるが、ブラウザのサポートが進んでいないので、まだ使えていない、使うには躊躇しているという位置付けです。このような機能も、State of CSSの2024年度版では「皆が知っていて、しかも使われている機能」に仲間入りしていくでしょう。これらを、いくつかピックアップして紹介します。

  • ・CSS Nesting:スタイル設定の入れ子が可能に
  • ・:has() セレクタ:特定の条件を満たすというセレクタが指定可能に
  • ・@container Queries:コンテナに対してのクエリでレスポンシブレイアウトが可能に
  • ・subgrid:サブグリッドを導入してグリッドの親子関係が可能に
  • ・Media Queries Range Contexts:範囲を分かりやすく適切に表現可能に

CSSの根幹にかかわる機能

レイアウトやタイポグラフィといった個別の機能に先立ち、CSSの記述方法そのものを変えるような、インパクトのある機能が「CSS Nesting」と「:has() セレクタ」です。

スタイル定義の入れ子を可能にする「CSS Nesting」

スタイル定義の入れ子(Nest/ネスト)は、CSS Nestingモジュールでサポートされました。スタイル定義の入れ子により、書きやすく読みやすい、メンテナンス性にも優れたスタイルシートの作成が可能になります。

▲CSS Nesting

スタイル定義の入れ子は、長年の課題だったといって良いでしょう。フロントエンドにおけるコンポーネント指向の開発が普通になったことで、コンポーネントの親子関係や階層をスタイル定義に持ち込めないのは、スタイルの定義や管理を難しいものにしていました。そこで、スタイル定義の入れ子をサポートしたCSSソース(SCSS)が考案されました。これをSaasやPostCSSといったツールを使ってネイティブなCSSにコンパイルすることで、間接的にスタイル定義の入れ子を可能にしてきました。この方法は、ビルド環境を用意する必要がある、CSSソースを変更するたびにビルドが必要になるといった欠点があります。

CSS Nestingでサポートされたスタイル定義の入れ子を使うと、スタイル定義を階層化できます。コンテナのセレクタに対するスタイルを記述し、その内部に各項目のセレクタに対するスタイルを記述することで、コンポーネントにおける階層をそのままスタイル定義に持ち込めます。これは、スタイルの可読性やメンテナンス性を大きく向上させます。

なお、入れ子のスタイルとしては、メディアクエリによるスタイル、後述するコンテナクエリによるスタイルも記述できます。条件に応じたスタイル定義が、より分かりやすい形で行えるわけです。

スタイル定義の入れ子は、スタイル定義の記述量そのものを減らせることから、CSSファイルの軽量化にも一役買います。

条件に合う子要素があるか調べる「:has() セレクタ」

:has() は、Selectors Level 4モジュールでサポートされる疑似クラス関数の一つです。:has() セレクタを使うと、子要素の状態に応じた親要素へのスタイル適用をコントロールできます。

▲:has() セレクタ

親要素の状態に応じた子要素へのスタイル適用は、従来のセレクタで可能でした。例えば、「.parent:hover .child」といったセレクタで、「ホバー状態にある.parentクラスの親要素の配下にある.childクラスの要素」といった記述が可能です。しかしながら、「ホバー状態にある.childクラスの要素を配下に持つ.parentクラスの親要素」といった指定はできません。別の例として、以下のようなケースがあると思います。

複数のチェックボックスのどれかがチェックされたら、
それを囲んだボックスの背景の色を変えたい。

このケースでは、:has() セレクタを使って「.parent:has(.child:checked)」と記述すれば、「.child:checkedを配下に持つ.parent」というセレクタが実現できます。:has() セレクタによるサポートがなければ、クリックイベントを捕捉し、親要素のスタイルを書き換えるJavaScriptコードが必要でしょう。これがスタイル定義だけで実現できるというのは非常に便利です。

:has() セレクタは、CSSにおける表現の手法をさらに広げるのではないでしょうか。

レスポンシブデザインに関連した機能

レスポンシブデザインというとメディアクエリが定番ですが、コンテナクエリとスタイルクエリがそこに加わりました。また、クエリ対象の大きさの指定する構文が分かりやすくなりました。

メディアクエリ
メディアクエリは、Webページを閲覧する媒体(メディア)によって、CSSの適用をコントロールする仕組みです。媒体の種類(画面、印刷など)やそのサイズを判定し、その結果によって、どのCSSを適用するかを切り替えられるようになります。

コンテナのサイズでクエリする「@container Queries」

@container Queriesは、CSS Containment Module Level 3モジュールでサポートされている、@ルール(CSSの動作を制御する命令文)の一つです。@containerを使うと、コンテナとなる要素に対してスタイルが適用となる条件を指定できるので、レスポンシブレイアウトをより柔軟に設定できます。

▲@container Queries

メディアクエリは、主にビューポートに対して作用するものでした。閲覧媒体(メディア)の種類や大きさに対して適用されるのがメディアクエリです。メディアクエリでは、例えばブラウザ画面が狭くなったといったイベントに反応して、スタイルの適用を決定します。このため、レスポンシブにスタイルを変更したい要素には、それぞれのスタイル定義を@mediaルール内に記述する必要があり、煩雑になりがちでした。

コンテナクエリは、その名のとおりコンテナ(親要素)のサイズやスタイルによって子要素のスタイルをコントロールする仕組みです。コンテナクエリにより、例えばサイドバーを持つコンテンツに対して、サイドバーのサイズにのみ着目して内部の要素のスタイルをコントロールすることが可能になります。

コンテナクエリは、既述のスタイル定義の入れ子の機能を使い、コンテナのスタイル定義内で@containerルールを指定するのが基本形です。container-nameプロパティでコンテナに名前を付けて、@containerルールでグローバルにそれを参照することも可能です。

スタイルクエリ(CSS Container Style Queries)
コンテナクエリはメディアクエリの延長のようなもので、@containerルールは基本的にコンテナサイズに適用されるものです。スタイルクエリは、この@containerルールにstyleルールを含めようというものです。スタイルには、HTMLのstyle属性で指定するカスタムプロパティも含めることができるので、コンテナのスタイルをHTMLからコントロールするといった柔軟な記法が可能になります。スタイルクエリは、本稿作成時点においてChrome 126などで部分的に実装されるのみという状況なので、今後が期待される機能です。

範囲を分かりやすく指定できる「Media Queries Range Contexts」

Media Queries Range Contextsは、Media Queries Level 4モジュールでサポートされる範囲構文です。ビューポートの幅の指定を、より直感的、柔軟に記述できます。

▲Media Queries Range Contexts

従来のメディアクエリでは、max-widthやmin-widthを使ってビューポートの幅を指定していました。これにより、「max-width以下」「min-width以上」といった条件を記述できました。しかしながら、あまり直感的ではなかったようで、いざ書く段になって「どっちだっけ?」というように一瞬迷うということがあったと思います。また、「max-width未満」「min-widthより大きい」といった指定ができないという問題もありました(この場合は指定する数値の方で調整していたように思えます)。

そこで、Media Queries Range Contextsとして、メディアクエリでより分かりやすく柔軟な範囲構文を使えるようになりました。これにより、一般的な「<」「>」「<=」「>=」などの比較演算子を使った指定が可能になりました。しかも多くのプログラミング言語では許されていない「30em <= width <= 50em」(30em以上50em以下)といった指定も可能になりました。なお、not、and、orを用いた複数の範囲の論理演算も可能になっています。

範囲指定のわかりにくさでメディアクエリが苦手だったという人には朗報でしょう。

レイアウトに関する機能

最後は、レイアウトに関する機能として「subgrid」を紹介します。

グリッドの入れ子を可能にする「subgrid」

subgrid(サブグリッド)は、CSS Grid Layout Level 2モジュールでサポートされる、グリッド内に副グリッドを作成する機能です。

▲subgrid

CSS Grid Layout Level 1でサポートされる従来のグリッドレイアウトは、コンテンツを格子状にレイアウトするといったときに便利です。グリッドの入れ子も可能なので、同一のレイアウトを持ったカードを格子状にレイアウトするといったことも容易です。

このグリッドレイアウトの入れ子、非常に便利なものですが、親グリッドのサイズ変更を子グリッドに反映できないという問題があります。これは、それぞれのグリッドが独立したものであるからです。

CSS Grid Layout Level 2でサポートされたsubgridを使うと、親グリッドのセルをまとめて子グリッドとすることができます。親グリッドのセルの中に新たに子グリッドを作るわけではありません。あくまでも親グリッドのセルをまとめて子グリッドにするという機能なので、各セルの大きさは親グリッドから完全にコントロールできます。普通にグリッドを入れ子にしたときのように、各セル内のグリッドのレイアウトがバラバラになるということもありません。

おわりに

今回は、CSSの使い勝手や表現を大きく向上させる「モダンCSS」を紹介しました。ブラウザのサポート状況を確認しながら導入する必要はありますが、いずれも使いたくなる機能と思います。本記事をきっかけに興味を持たれたならば、ぜひCSSの仕様書やブラウザの対応状況を眺めてみてください。

関連記事

人気記事

  • コピーしました

RSS
RSS