ここ数か月は、ウェブ UI の黄金時代でした。新しいプラットフォーム機能は、クロスブラウザで緊密に採用されており、これまで以上に多くのウェブ機能とカスタマイズ機能をサポートしています。
以下に、最近リリースされた、または近日提供予定の、最もエキサイティングで影響力のある 20 の機能をご紹介します。
- コンテナクエリ
- スタイルクエリ
:has()
セレクタ- マイクロ構文の第 n 番目
text-wrap: balance
initial-letter
- 動的ビューポート単位
- 広色域色空間
color-mix()
- ネスト
- レイヤをカスケードする
- スコープ スタイル
- 三角関数
- 個々の変換プロパティ
- ポップオーバー
- アンカーの配置
- selectmenu
- 離散的なプロパティ遷移
- スクロール ドリブンのアニメーション
- ビュー遷移
新しいレスポンシブ
それでは、レスポンシブ デザインの新機能を使ってみましょう。新しいプラットフォーム機能により、レスポンシブなスタイル設定情報を所有するコンポーネントを使用して論理インターフェースを構築したり、システム機能を活用してよりネイティブな UI を提供するインターフェースを構築したり、ユーザー設定クエリを使用してユーザーがデザイン プロセスに参加できるようにしたりして、完全なカスタマイズを実現できます。
コンテナクエリ
コンテナクエリは最近、すべての最新ブラウザで安定するようになりました。親要素のサイズとスタイルをクエリして、その子に適用するスタイルを決定できます。メディアクエリはビューポートの情報にのみアクセスして利用できるため、ページ レイアウトのマクロビューでのみ機能します。一方、コンテナクエリはより正確なツールで、任意の数のレイアウトやレイアウト内のレイアウトをサポートできます。
次の受信トレイの例では、[メインの受信トレイ] サイドバーと [お気に入り] サイドバーの両方がコンテナになっています。メール内のメールは、利用可能なスペースに基づいてグリッド レイアウトを調整し、メールのタイムスタンプを表示または非表示にします。これはページ内のまったく同じコンポーネントで、異なるビューに表示されるだけです。
コンテナクエリを使用しているため、これらのコンポーネントのスタイルは動的です。ページサイズとレイアウトを調整すると、コンポーネントは個別に割り当てられたスペースに反応します。サイドバーがスペースの広いトップバーになり、レイアウトがメインの受信トレイに近づきます。スペースが少ない場合は、両方とも圧縮形式で表示されます。
コンテナクエリと論理コンポーネントの構築について詳しくは、こちらの投稿をご覧ください。
スタイルクエリ
コンテナのクエリ仕様では、親コンテナのスタイル値をクエリすることもできます。現在、これは Chrome 111 で部分的に実装されており、CSS カスタム プロパティを使用してコンテナ スタイルを適用できます。
次の例では、カスタム プロパティ値に保存されている天気特性(雨、晴れ、曇りなど)を使用して、カードの背景とインジケーター アイコンのスタイルを設定します。
@container style(--sunny: true) {
.weather-card {
background: linear-gradient(-30deg, yellow, orange);
}
.weather-card:after {
content: url(<data-uri-for-demo-brevity>);
background: gold;
}
}
スタイルクエリは、これからさらに進化していきます。今後は、カスタム プロパティ値が存在するかどうかを判断し、コードの重複を減らすブール値クエリが導入される予定です。また、値の範囲に基づいてスタイルを適用する範囲クエリも現在検討中です。これにより、雨や雲量の確率にパーセンテージ値を使用して、ここで示したスタイルを適用できるようになります。
詳細とその他のデモについては、スタイルクエリに関するブログ投稿をご覧ください。
:has()
強力な動的機能といえば、:has() セレクタは、最新のブラウザに導入された最も強力な新しい CSS 機能の 1 つです。:has()
を使用すると、親要素に特定の子要素が含まれているかどうか、またはそれらの子要素が特定の状態にあるかどうかを確認して、スタイルを適用できます。つまり、基本的に親セレクタが作成されたことになります。
コンテナクエリの例を基に、:has()
を使用してコンポーネントをさらに動的にすることができます。「星」要素を含むアイテムにはグレーの背景が適用され、チェックボックスがオンになっているアイテムには青い背景が適用されます。
この API は親の選択に限定されません。親内の子要素にスタイルを適用することもできます。たとえば、アイテムにスター要素がある場合、タイトルが太字になります。これは .item:has(.star) .title
で行います。:has()
セレクタを使用すると、親要素、子要素、さらには兄弟要素にもアクセスできるため、非常に柔軟な API となり、新しいユースケースが日々生まれています。
詳細とデモについては、:has()
に関するこちらのブログ投稿をご覧ください。
nth-of 構文
対応ブラウザ
ウェブ プラットフォームに、より高度な nth-child 選択機能が追加されました。高度な nth-child 構文では、新しいキーワード(of)が使用できます。これにより、An+B の既存のマイクロ構文を使用して、検索対象のより具体的なサブセットを指定できます。
特別なクラスに通常の nth-child(:nth-child(2)
など)を使用すると、ブラウザは、クラス special が適用され、2 番目の子である要素を選択します。これは、最初にすべての .special
要素を事前にフィルタし、そのリストから 2 番目の要素を選択する :nth-child(2 of .special)
とは対照的です。
この機能について詳しくは、n 番目の構文に関する記事をご覧ください。
text-wrap: balance
スタイル内にロジックを埋め込むことができる場所は、セレクタとスタイルクエリだけではありません。タイポグラフィもその一つです。Chrome 114 以降では、text-wrap
プロパティに値 balance
を指定して、見出しにテキストの折り返しのバランス調整を使用できます。
ブラウザはテキストのバランスを取るために、実質的に最小幅のバイナリ検索を実行し、追加の行を生じさせません。その際、(ディスプレイ ピクセルではない)1 CSS ピクセルで停止します。二分探索のステップをさらに最小限に抑えるために、ブラウザは平均行幅の 80% から開始します。
詳しくは、こちらの記事をご覧ください。
initial-letter
ウェブ タイポグラフィの改善点として、initial-letter
もあります。この CSS プロパティを使用すると、インセット ドロップキャップのスタイルをより細かく制御できます。
:first-letter
疑似要素で initial-letter
を使用して、占有する行数に基づく文字のサイズを指定します。文字のブロック オフセット(文字の配置場所の「シンク」)。
intial-letter
の使用方法について詳しくは、こちらをご覧ください。
動的なビューポートの単位
対応ブラウザ
ウェブ デベロッパーが今日直面している共通の問題の一つに、特にモバイル デバイスで、全ビューポートのサイズを正確かつ一貫していることが挙げられます。デベロッパーは、100vh
(ビューポートの高さの 100%)を「ビューポートと同じ高さ」にすることが適切ですが、vh
ユニットはモバイルのナビゲーション バーを撤回するなどは考慮しないため、長くなりすぎてスクロールしてしまうことがあります。
この問題を解決するために、ウェブ プラットフォームに次のような新しい単位値を追加しました。
- 小さいビューポートの高さと幅(または svh
と svw
)は、アクティブなビューポートの最小サイズを表します。
- 大きなビューポートの高さと幅(lvh
と lvw
)。最大サイズを表します。- 動的ビューポートの高さと幅(dvh
と dvw
)。
動的ビューポート ユニットの値は、上部のアドレスバーや下部のタブバーなど、追加の動的ブラウザ ツールバーが表示されている場合と表示されていない場合で異なります。
これらの新しい単位について詳しくは、大、小、動的ビューポート単位をご覧ください。
広色域の色空間
ウェブ プラットフォームに新たに加わったもう 1 つの重要な機能は、広色域色空間です。ウェブ プラットフォームで広色域が利用可能になる前は、最新のデバイスで表示可能な鮮やかな色彩で写真を撮影できましたが、その鮮やかな値にマッチするボタン、テキストの色、背景を用意できませんでした。
しかし、現在、ウェブ プラットフォームには REC2020、P3、XYZ、LAB、OKLAB、LCH、OKLCH など、さまざまな新しい色空間が用意されています。新しいウェブカラー空間などについては、HD カラーガイドをご覧ください。
DevTools では、色域がどのように拡大されたかを確認できます。白い線は、sRGB の範囲の終了点と、より広い色域の範囲の開始点を示しています。
カラーには、他にも多くのツールが用意されています。グラデーションの大幅な改善も見逃さないでください。また、Adam Argyle が開発したまったく新しいツールも用意されています。このツールを使用すると、新しいウェブカラー選択ツールやグラデーション ビルダーを gradient.style で確認できます。
color-mix()
拡張色空間を拡張する機能は、color-mix()
関数です。この関数は、2 つの色値を混合して、混合される色のチャネルに基づいて新しい値を作成できます。混合する色空間が結果に影響します。oklch などの知覚色空間で作業すると、srgb とは異なる色域が使用されます。
color-mix(in srgb, blue, white);
color-mix(in srgb-linear, blue, white);
color-mix(in lch, blue, white);
color-mix(in oklch, blue, white);
color-mix(in lab, blue, white);
color-mix(in oklab, blue, white);
color-mix(in xyz, blue, white);
color-mix()
関数は、以前からのご要望の多かった機能を提供します。不透明な色の値を保持しながら、ある程度の透明度を追加できます。ブランドの色変数を使用して、さまざまな不透明度で色のバリエーションを作成できるようになりました。これを行うには、色を透明なものに混ぜます。ブランドカラーを青に混ぜて透明度を 10% にすると、ブランドカラーは不透明度が 90% になります。これにより、カラーシステムをすばやく構築できます。
この機能は、Chrome DevTools のスタイルペインで、プレビュー用ベン図アイコンとして確認できます。
その他の例と詳細については、color-mix に関するブログ投稿をご覧ください。また、color-mix() のプレイグラウンドをお試しください。
CSS の基礎
ユーザーにとって明確なメリットがある新しい機能を構築することも重要ですが、Chrome に導入される機能の多くは、デベロッパー エクスペリエンスの向上と、より信頼性が高く整理された CSS アーキテクチャの構築を目的としています。これらの機能には、CSS のネスト、カスケード レイヤ、スコープ設定されたスタイル、三角関数、個々の変換プロパティが含まれます。
ネスト
CSS ネスト機能は、Sass で人気があり、CSS デベロッパーからのリクエストが長年寄せられていた機能です。この機能が、ついにウェブ プラットフォームに導入されます。ネスト構造を使用することで、簡潔でグループ化された形式で記述できるようになり、冗長さが軽減されます。
.card {}
.card:hover {}
/* can be done with nesting like */
.card {
&:hover {
}
}
メディアクエリをネストすることもできます。つまり、コンテナクエリもネストできます。次の例では、カードのコンテナに十分な幅がある場合、カードを縦向きレイアウトから横向きレイアウトに変更します。
.card {
display: grid;
gap: 1rem;
@container (width >= 480px) {
display: flex;
}
}
コンテナのインライン スペースが 480px
以上の場合、flex
のレイアウト調整が行われます。ブラウザは、条件が満たされると、その新しい表示スタイルのみを適用します。
詳細と例については、CSS のネストに関する投稿をご覧ください。
レイヤをカスケードする
デベロッパーの懸念事項として、どのスタイルが優先されるかを一貫して確保することが挙げられます。この問題を解決する方法の一つとして、CSS カスケードをより適切に制御することが考えられます。
カスケード レイヤは、この問題を解決するために、どのレイヤを優先するかをユーザーが制御できるようにすることで、スタイルを適用するタイミングをより細かく制御できるようにします。
カスケード レイヤの使用方法について詳しくは、こちらの記事をご覧ください。
スコープ CSS
CSS スコープ スタイルを使用すると、特定のスタイルが適用される境界を指定できます。これは、基本的に CSS でネイティブな名前空間を作成することです。これまで、デベロッパーはサードパーティ スクリプトを使用してクラス名を変更したり、特定の命名規則を使用してスタイルの競合を回避したりしていましたが、まもなく @scope
を使用できるようになります。
ここでは、.title
要素を .card
にスコープしています。これにより、そのタイトル要素が、ページ上の他の .title
要素(ブログ投稿のタイトルやその他の見出しなど)と競合することがなくなります。
@scope (.card) {
.title {
font-weight: bold;
}
}
このライブデモでは、スコープ制限のある @scope
と @layer
を確認できます。
@scope
の詳細については、css-cascade-6 仕様をご覧ください。
三角関数
新しい CSS プラミングのもう一つの機能が、既存の CSS 数学関数に追加されている三角関数です。これらの機能は、すべての最新ブラウザで安定しており、ウェブ プラットフォームでより自然なレイアウトを作成できるようになりました。その好例が放射型メニュー レイアウトです。sin()
関数と cos()
関数を使用してデザインとアニメーション化を行えるようになりました。
以下のデモでは、中心点を中心として点が回転しています。各ドットは、それぞれの中心を中心に回転してから外側に移動する代わりに、X 軸と Y 軸に沿って並進します。X 軸と Y 軸上の距離は、それぞれ --angle
の cos()
と sin()
を考慮して決定されます。
このトピックの詳細については、三角関数に関する記事をご覧ください。
個々の変換プロパティ
デベロッパーのエルゴノミクスは、個々の変換関数によって向上し続けています。前回の I/O 以降、個々の変換がすべての最新ブラウザで安定しました。
以前は、transform 関数を使用してサブ関数を適用し、UI 要素のスケーリング、回転、移動を行っていました。これは多くの繰り返しを伴うため、アニメーションの異なるタイミングで複数の変換を適用する場合は特に不満を感じていました。
.target {
transform: translateX(50%) rotate(30deg) scale(1.2);
}
.target:hover {
transform: translateX(50%) rotate(30deg) scale(2); /* Only scale changed here, yet you have to repeat all other parts */
}
変換の種類を分離して個別に適用することで、これらの詳細をすべて CSS アニメーションに含めることができます。
.target {
translate: 50% 0;
rotate: 30deg;
scale: 1.2;
}
.target:hover {
scale: 2;
}
これにより、アニメーションの進行中に、移動、回転、スケールの変化を異なる変化率で同時に行うことができます。
詳細については、個々の変換関数に関する投稿をご覧ください。
カスタマイズ可能なコンポーネント
デベロッパーの主なニーズをウェブ プラットフォームを通じて確実に解決するために、Google は OpenUI コミュニティ グループと連携し、手始めに次の 3 つのソリューションを特定しています。
- イベント ハンドラ、宣言型 DOM 構造、アクセス可能なデフォルトを含む組み込みのポップアップ機能。
- 2 つの要素を相互に結び付けてアンカー ポジショニングを有効にする CSS API。
- カスタマイズ可能なプルダウン メニュー コンポーネント。セレクト内のコンテンツにスタイルを適用する場合に使用します。
ポップオーバー
popover API を使用すると、要素にブラウザでサポートされている次のような機能を組み込むことができます。
- 最上位レイヤをサポートしているため、
z-index
を管理する必要はありません。ポップオーバーやダイアログを開くと、その要素はページ上部の特別なレイヤに昇格します。 auto
ポップオーバーでは、軽量の閉じる動作を無料で実行できます。これにより、要素の外側をクリックすると、ポップオーバーが閉じられ、ユーザー補助ツリーから削除され、フォーカスが適切に管理されます。- ポップオーバーのターゲットとポップオーバー自体の連結組織のデフォルトのユーザー補助。
つまり、これらの機能をすべて作成し、これらの状態をすべて追跡するために記述する JavaScript の量を減らすことができます。
ポップオーバーの DOM 構造は宣言型であるため、ポップオーバー要素に id
属性と popover
属性を指定するのと同じくらい明確に記述できます。次に、その ID を、ポップオーバーを開く要素(popovertarget
属性を持つボタンなど)と同期します。
<div id="event-popup" popover>
<!-- Popover content goes in here -–>
</div>
<button popovertarget="event-popup">Create New Event</button>
popover
は popover=auto
の省略形です。popover=auto
を含む要素は、開いたときに他のポップオーバーを強制的に閉じ、開いたときにフォーカスを受け取ります。また、ライト ディミッシブに閉じることができます。逆に、popover=manual
要素は他の要素タイプを強制的に閉じず、すぐにフォーカスを受け取ることも、ライトで閉じることもしません。切り替えなどの閉じる操作で閉じる。
ポップオーバーに関する最新のドキュメントは、現在 MDN で確認できます。
アンカーの配置
また、ポップオーバーはダイアログやツールチップなどの要素でも頻繁に使用されます。通常は特定の要素に固定する必要があります。このイベントの例で考えてみましょう。カレンダーの予定をクリックすると、クリックした予定の近くにダイアログが表示されます。カレンダー アイテムがアンカーで、ポップオーバーがイベントの詳細を表示するダイアログです。
anchor()
関数で中央揃えのツールチップを作成できます。アンカーからの幅を使用して、ツールチップをアンカーの x 位置の 50% に配置します。次に、既存のプレースメント値を使用して、残りのプレースメント スタイルを適用します。
ポップオーバーを配置した方法によっては、ビューポートに収まらない場合があります。
この問題を解決するため、アンカー ポジショニング API には、カスタマイズ可能なフォールバック ポジションが含まれています。次の例では、「top-then-bottom」という代替のプレースメントを作成します。ブラウザはまずツールチップを上部に配置しようとしますが、それがビューポートに収まらない場合は、下部のアンカー要素の下にツールチップを配置します。
.center-tooltip {
position-fallback: --top-then-bottom;
translate: -50% 0;
}
@position-fallback --top-then-bottom {
@try {
bottom: calc(anchor(top) + 0.5rem);
left: anchor(center);
}
@try {
top: calc(anchor(bottom) + 0.5rem);
left: anchor(center);
}
}
アンカーの配置について詳しくは、こちらのブログ投稿をご覧ください。
<selectmenu>
ポップオーバーとアンカーの両方を配置して、完全にカスタマイズ可能な選択メニューを構築できます。OpenUI コミュニティ グループは、これらのメニューの基本構造を調査し、その中のコンテンツをカスタマイズできるようにする方法を模索してきました。次の視覚的な例を見てみましょう。
左端の selectmenu
の例を、カレンダーの予定に表示される色に対応する色付きの点で作成するには、次のように記述します。
<selectmenu>
<button slot="button" behavior="button">
<span>Select event type</span>
<span behavior="selected-value" slot="selected-value"></span>
<span><img src="icon.svg"/></span>
</button>
<option value="meeting">
<figure class="royalblue"></figure>
<p>Meeting</p>
</option>
<option value="break">
<figure class="gold"></figure>
<p>Lunch/Break</p>
</option>
...
</selectmenu>
離散的なプロパティ遷移
これらすべての処理でポップオーバーをスムーズに切り替えるには、ウェブで個別のプロパティをアニメーション化するなんらかの方法が必要です。これらは通常、これまでアニメーション化できなかったプロパティです。最上位レイヤとの間でアニメーション化したり、display: none
との間でアニメーション化したりできます。
ポップオーバー、選択メニュー、さらにはダイアログやカスタム コンポーネントなどの既存の要素でも適切に遷移できるようにする取り組みの一環として、ブラウザでこれらのアニメーションをサポートする新しいプラミングが可能になっています。
次のポップオーバーのデモでは、開いた状態には :popover-open
、開前の状態には @starting-style
を使用してポップオーバーをアニメーション化し、開閉状態には変換値を直接要素に適用します。これをディスプレイで機能させるには、次のように transition
プロパティに追加する必要があります。
.settings-popover {
&:popover-open {
/* 0. before-change */
@starting-style {
transform: translateY(20px);
opacity: 0;
}
/* 1. open (changed) state */
transform: translateY(0);
opacity: 1;
}
/* 2. After-change state */
transform: translateY(-50px);
opacity: 0;
/* enumarate transitioning properties, including display */
transition: transform 0.5s, opacity 0.5s, display 0.5s allow-discrete;
}
インタラクション数
ウェブ UI 機能ガイドの最後のページであるインタラクションの説明に移ります。
個別のプロパティのアニメーション化についてはすでに説明しましたが、スクロールドリブン アニメーションとビュー遷移に関連する魅力的な API が Chrome に実装されています。
スクロールドリブン アニメーション
スクロールドリブン アニメーションを使用すると、スクロール コンテナのスクロール位置に基づいてアニメーションの再生を制御することができます。つまり、上下にスクロールすると、アニメーションが前方または後方にスクラブされます。また、スクロールドリブン アニメーションを使用すると、スクロール コンテナ内の要素の位置に基づいてアニメーションを制御することもできます。これにより、視差効果のある背景画像、スクロールの進行状況バー、ビューに入ったときに出現する画像など、面白い視覚効果を作成することができます。
この API は一連の JavaScript クラスと CSS プロパティをサポートしており、宣言型のスクロールドリブン アニメーションを簡単に作成できます。
スクロールによって CSS アニメーションを駆動するには、新しい scroll-timeline
、view-timeline
、animation-timeline
プロパティを使用します。JavaScript Web Animations API を駆動するには、ScrollTimeline
インスタンスまたは ViewTimeline
インスタンスを timeline
オプションとして Element.animate()
に渡します。
これらの新しい API は、既存の Web Animations API や CSS Animations API と連携して動作するため、これらの API の利点を活用できます。これには、これらのアニメーションをメインスレッド以外で実行する機能も含まれます。はい、お読みの通りです。数行のコードを追加するだけで、スクロールによって駆動され、メインスレッドで実行される、滑らかなアニメーションを実現できます。気に入らない理由はありません。
スクロール ドリブンのアニメーションを作成する方法について詳しくは、スクロール ドリブンのアニメーションに関するこちらの記事をご覧ください。
遷移を表示する
View Transition API を使用すると、2 つの状態間のアニメーション遷移を作成する際に、DOM を 1 つのステップで簡単に変更できます。ビュー間の単純なフェードでもかまいませんが、ページの個々の部分の遷移方法を制御することもできます。
ビュー遷移は、プログレッシブ エンハンスメントとして使用できます。任意の方法で DOM を更新するコードを、ビュー遷移 API でラップし、この機能をサポートしていないブラウザ向けにフォールバックを提供します。
function spaNavigate(data) {
// Fallback for browsers that don't support this API:
if (!document.startViewTransition) {
updateTheDOMSomehow(data);
return;
}
// With a transition:
document.startViewTransition(() => updateTheDOMSomehow(data));
}
遷移の外観は CSS で制御します。
@keyframes slide-from-right {
from { opacity: 0; transform: translateX(75px); }
}
@keyframes slide-to-left {
to { opacity: 0; transform: translateX(-75px); }
}
::view-transition-old(root) {
animation: 350ms both slide-to-left ease;
}
::view-transition-new(root) {
animation: 350ms both slide-from-right ease;
}
Maxi Ferreira によるこちらの素晴らしいデモで示したように、再生中の動画など、他のページ操作はビュー遷移の発生中も動作し続けます。
ビュー遷移は現在、Chrome 111 のシングルページ アプリ(SPA)で動作します。複数ページのアプリのサポートは現在開発中です。詳しくは、ビューの切り替えガイドをご覧ください。
まとめ
CSS と HTML の最新情報については、developer.chrome.com でご確認ください。また、I/O の動画で、ウェブに関する最新情報もご確認ください。