最新の CSS の魅力的な機能について学びましょう。
現在、CSS では数多くの新しい機能が開発されており、その多くはすでに最新のブラウザでサポートされています。CDS 2019 での Google の講演(下記を参照)では、注目に値する新機能や今後の機能について説明しています。
この記事では、現在使用できる機能に焦点を当てています。Houdini などの今後の機能について詳しくは、ぜひ講演をご覧ください。ここで説明するすべての機能のデモは、CSS@CDS ページでもご覧いただけます。
目次
- スクロール スナップ
:focus-within
- メディアクエリ レベル 5
- 論理プロパティ
position: sticky
backdrop-filter
:is()
gap
- CSS Houdini
- オーバーフロー
スクロール スナップ
スクロール スナップを使用すると、ユーザーがコンテンツを縦方向、横方向、またはその両方でスクロールするときにスナップ ポイントを定義できます。スクロールの慣性と減速が組み込まれており、タップが有効になっています。
このサンプルコードでは、子 <picture>
要素の左側にスナップポイントを配置して、<section>
要素に水平スクロールを設定します。
section {
overflow-x: auto;
overscroll-behavior-x: contain;
scroll-snap-type: x mandatory;
}
section > picture {
scroll-snap-align: start;
}
仕組みは次のとおりです。
- 親の
<section>
要素で、overflow-x
はauto
に設定され、横方向のスクロールが許可されています。overscroll-behavior-x
をcontain
に設定して、ユーザーが<section>
要素のスクロール領域の境界に達したときに親要素がスクロールしないようにします。(これは、スナップでは厳密には必要ありませんが、使用するのが一般的です)。scroll-snap-type
は、水平方向のスナップの場合はx
、ビューポートが常に最も近いスナップポイントにスナップされるようにするにはmandatory
に設定します。
- 子
<picture>
要素では、scroll-snap-align
が start に設定されています。これにより、各画像の左側にスナップポイントが設定されます(direction
がltr
に設定されていることを前提としています)。
ライブデモは次のとおりです。
縦方向のスクロール スナップと行列スクロール スナップのデモもご覧ください。
:focus-within
:focus-within
は、長年の問題であるユーザー補助機能の対応に取り組んでいます。子要素にフォーカスを当てると親要素の表示に影響し、ユーザー補助技術のユーザーが UI にアクセスできるようにする必要があるケースは数多くあります。
たとえば、複数のアイテムを含むプルダウン メニューがある場合は、いずれかのアイテムがフォーカスされている間、メニューを表示したままにします。そうでない場合、キーボード ユーザーにはメニューが表示されなくなります。
:focus-within
は、指定した要素の子要素にフォーカスがあるときにスタイルを適用するようブラウザに指示します。メニューの例に戻りましょう。メニュー要素に :focus-within
を設定すると、メニュー項目にフォーカスが当たっているときにメニューが常に表示されるようになります。
.menu:focus-within {
display: block;
opacity: 1;
visibility: visible;
}
以下のデモで、フォーカス可能な要素をタブで移動してみてください。メニュー項目にフォーカスを当てると、メニューは引き続き表示されます。
メディアクエリ レベル 5
新しいメディアクエリを使用すると、ユーザーのデバイスの設定に基づいてアプリのユーザー エクスペリエンスを調整できます。基本的に、ブラウザはシステムレベルの設定のプロキシとして機能します。この設定には、メディアクエリの prefers-*
グループを使用して CSS で対応できます。
ここでは、デベロッパーの皆様が最も興味を持つと思われる新しいクエリをご紹介します。
- prefers-reduced-motion
- prefers-color-scheme
- prefers-contrast
- prefers-reduced-transparency
- forced-colors
- inverted-colors
このようなクエリは、ユーザー補助機能において大きなメリットがあります。以前は、ユーザーが OS をハイ コントラスト モードに設定しているかどうかを把握する方法がありませんでした。ブランドイメージを損なうことなくウェブアプリにハイコントラスト モードを提供するには、アプリ内の UI から選択するようユーザーに依頼する必要がありました。prefers-contrast
を使用すると、OS からハイコントラスト設定を検出できるようになりました。
これらのメディアクエリの魅力的な点の 1 つは、システムレベルのユーザー設定を複数組み合わせて設計し、幅広いユーザー設定とユーザー補助のニーズに対応できることです。ユーザーが薄暗い環境で高コントラストのダークモードを希望している場合は、そのように設定できます。
アダムにとって重要なのは、「動きを抑えたい」が「動きなし」として実装されないことである。お客様はアニメーションをまったく望まないのではなく、動きを抑えたいと言っているようです。彼は、縮小運動は運動ではないと主張しています。次に、ユーザーが動きの軽減を望んでいる場合にクロスフェード アニメーションを使用する例を示します。
論理プロパティ
論理的特性は、国際化に取り組むデベロッパーが増えるにつれ、注目を集めてきた問題を解決します。margin
や padding
などの多くのレイアウト プロパティは、上から下、左から右に読む言語を前提としています。
さまざまな入力モードを持つ複数の言語のページを設計する場合、デベロッパーは複数の要素にわたってこれらのプロパティを個別に調整する必要があり、メンテナンスが非常に困難になっていました。
論理プロパティを使用すると、翻訳と入力モード間でレイアウトの完全性を維持できます。空間配置ではなく、コンテンツのセマンティックな順序に基づいて動的に更新されます。論理プロパティでは、各要素に次の 2 つのディメンションがあります。
- ブロック ディメンションは、行内のテキストの流れに対して垂直です。(英語では、
block-size
はheight
と同じです)。 - インライン ディメンションは、1 行内のテキストの流れに平行しています。(英語では、
inline-size
はwidth
と同じです)。
これらのディメンション名は、すべての論理レイアウト プロパティに適用されます。たとえば、英語では block-start
は top
と同じで、inline-end
は right
と同じです。
論理プロパティを使用すると、個々の要素の多数のレイアウト プロパティを更新するのではなく、ページの writing-mode
プロパティと direction
プロパティを変更するだけで、他の言語用にレイアウトを自動的に更新できます。
論理プロパティの動作は、次のデモで確認できます。<body>
要素の writing-mode
プロパティを異なる値に設定します。
position: sticky
position: sticky
を持つ要素は、画面外に移動し始めるまでブロックフロー内に留まります。この時点で、ページの他の部分と一緒にスクロールを停止し、要素の top
値で指定された位置に固定されます。その要素に割り当てられたスペースはフロー内に残り、ユーザーがスクロールして戻ると要素がそのスペースに戻ります。
スティッキー ポジショニングを使用すると、これまで JavaScript が必要だった多くの便利な効果を作成できます。可能性の一部を示すために、いくつかのデモを作成しました。各デモでは、ほぼ同じ CSS を使用し、HTML マークアップをわずかに調整して各効果を作成しています。
Sticky Stack
このデモでは、すべてのスティッキー要素が同じコンテナを共有しています。つまり、ユーザーが下にスクロールすると、それぞれの固定要素が前の要素の上へとスライドします。スティッキー要素は同じ固定位置を共有します。
スティッキー スライド
ここで、スティッキー要素はいとこです。(つまり、両親が兄弟姉妹である)。スティッキー要素がコンテナの下限に達すると、コンテナとともに上に移動します。これは、スティッキー要素がコンテナの下側に来ると、それよりも上のスティッキー要素が押し上げられているような印象を与えます。つまり、停止した位置を競合しているように見えるということです。
Sticky Desperado
このデモのスティッキー要素は、スティッキー スライドと同様に、親戚関係にあります。ただし、2 列のグリッド レイアウトに設定されたコンテナに配置されています。
backdrop-filter
backdrop-filter
プロパティを使用すると、要素自体ではなく、要素の背後の領域にグラフィック効果を適用できます。これにより、これまでは複雑な CSS や JavaScript のハッキングでしか実現できなかった多くの優れた効果を、1 行の CSS で実現できました。
たとえば、このデモでは backdrop-filter
を使用して OS スタイルのぼかしを実現しています。
すでに backdrop-filter
に関する投稿がありますので、そちらをご確認ください。
:is()
:is()
疑似クラスは実際には 10 年以上前のものですが、Google が考えるほどには使用されていません。セレクタのカンマ区切りリストを引数として受け取り、そのリスト内のすべてのセレクタに一致します。この柔軟性は非常に便利で、配布する CSS の数を大幅に削減できます。
簡単な例:
button.focus,
button:focus {
…
}
article > h1,
article > h2,
article > h3,
article > h4,
article > h5,
article > h6 {
…
}
/* selects the same elements as the code above */
button:is(.focus, :focus) {
…
}
article > :is(h1,h2,h3,h4,h5,h6) {
…
}
gap
CSS グリッド レイアウトでは、以前から gap
(以前の grid-gap
)が使用されていました。gap
を使用すると、子要素の周囲の間隔ではなく、親要素の内部の間隔を指定できるため、多くの一般的なレイアウトの問題を解決できます。たとえば、gap を使用すると、子要素のマージンが原因で、包含要素の端に不要な空白が挿入される心配はありません。
さらに良いニュース: gap
が flexbox に導入され、グリッドと同じスペースのメリットがすべて利用できるようになります。
- 複数ではなく 1 つのスペース宣言がある。
- どの子要素がスペースを所有するかについて、プロジェクトに規則を定める必要はありません。代わりに、スペースは親要素が所有します。
- コードは、ロボトミーを受けたフクロウなどの古い戦略よりも理解しやすいです。
次の動画は、グリッド レイアウトと Flex レイアウトの 2 つの要素に単一の gap
プロパティを使用するメリットを示しています。
現在、Firefox のみが flex レイアウトで gap
をサポートしていますが、このデモで動作を確認できます。
CSS Houdini
Houdini は、ブラウザのレンダリング エンジン用の低レベル API のセットです。これにより、カスタム CSS の解釈方法をブラウザに指示できます。つまり、このモデルを使用すると CSS オブジェクト モデルにアクセスし、JavaScript で CSS をextendできます。これには、さまざまなメリットがあります。
- これにより、カスタム CSS 機能を作成する際の自由度が大幅に高まります。
- レンダリングに関する懸念事項をアプリケーション ロジックから分離しやすくなります。
- ブラウザがスクリプトを解析して 2 回目のレンダリング サイクルを行う必要がないため、現在 JavaScript で行っている CSS ポリフィルリングよりもパフォーマンスが向上します。Houdini コードは最初のレンダリング サイクルで解析されます。
Houdini は、複数の API の総称です。これらの機能と現在のステータスについて詳しくは、Houdini は準備ができていますか?をご覧ください。この講演では、現在最もサポートされている Properties and Values API、Paint API、Animation Worklet について説明しました。魅力的な各 API について、簡単に完全な投稿を投稿できますが、ここでは、API で何ができるかを理解するための概要と魅力的なデモをいくつかご覧ください。
オーバーフロー
今後予定されている機能について、もう少し詳しくお話ししたかったのですが、時間の都合上、ハイライトだけご紹介しました。⚡ これらの機能の一部をまだご存じでない場合は、トークの後半をご覧ください。
size
: 高さと幅を同時に設定できるプロパティaspect-ratio
: 固有のアスペクト比を持たない要素のアスペクト比を設定するプロパティmin()
、max()
、clamp()
: 幅と高さだけでなく、任意の CSS プロパティに数値の制約を設定できる関数list-style-type
は既存のプロパティですが、まもなく絵文字や SVG など、より幅広い値がサポートされる予定ですdisplay: outer inner
:display
プロパティはまもなく 2 つのパラメータを受け入れるようになります。これにより、inline-flex
などの複合キーワードを使用するのではなく、外部レイアウトと内部レイアウトを明示的に指定できます。- CSS 領域: コンテンツの流入と流出が可能な指定された長方形以外の領域を塗りつぶすことができます。
- CSS モジュール: JavaScript は CSS モジュールをリクエストし、操作が簡単なリッチ オブジェクトを取得できるようになります。