CSSHoudiniの実用的な概要

公開: 2022-03-10
簡単な要約↬ブラウザAPIのコレクションの総称であるHoudiniは、Web開発プロセスと一般的なCSS標準の開発に大幅な改善をもたらすことを目的としています。 フロントエンド開発者は、JavaScriptを使用してCSSを新機能で拡張し、CSSレンダリングエンジンに接続して、レンダリングプロセス中にCSSを適用する方法をブラウザーに指示できます。 Houdiniのブラウザサポートは改善されており、一部のAPIは現在使用可能であるため、それらに精通して実験する良い機会です。 Houdiniの各部分、現在のブラウザーサポートを見て、プログレッシブエンハンスメントを使用してそれらを今日どのように使用できるかを見ていきます。

新しいCSS機能または改善が、最初のドラフトから、開発者が使用できる完全にサポートされた安定したCSS機能に進むまでには長い時間がかかります。 JavaScriptベースのポリフィルは、正式に実装される前に新しいCSS機能を使用するために、ブラウザーサポートの欠如の代わりに使用できます。 しかし、ほとんどの場合、それらには欠陥があります。 たとえば、scrollsnap-polyfillは、CSS ScrollSnap仕様のブラウザーサポートの不整合を修正するために使用できるいくつかのポリフィルの1つです。 しかし、そのソリューションでさえ、いくつかの制限、バグ、および矛盾があります。

ポリフィルを使用することの潜在的な欠点は、パフォーマンスに悪影響を与える可能性があり、適切に実装することが難しいことです。 この欠点は、ブラウザのDOMとCSSOMに関連しています。 ブラウザは、HTMLマークアップからDOM(ドキュメントオブジェクトモデル)を作成し、同様に、CSSマークアップからCSSOM(CSSオブジェクトモデル)を作成しました。 これらの2つのオブジェクトツリーは互いに独立しています。 JavaScriptはDOMで動作し、CSSOMへのアクセスは非常に制限されています。

JavaScript Polyfillソリューションは、最初のレンダリングサイクルが完了した後、つまりDOMとCSSOMの両方が作成され、ドキュメントの読み込みが完了した後にのみ実行されます。 PolyfillがDOMのスタイルに(インライン化によって)変更を加えた後、レンダリングプロセスが再度実行され、ページ全体が再レンダリングされます。 requestAnimationFrameメソッドに依存している場合、またはスクロールイベントなどのユーザー操作に依存している場合、パフォーマンスへの悪影響はさらに明白になります。

Web開発におけるもう1つの障害は、CSS標準によって課せられるさまざまな制約です。 たとえば、ネイティブにアニメーション化できるCSSプロパティの数は限られています。 CSSは、色をネイティブにアニメーション化する方法を知っていますが、グラデーションをアニメーション化する方法を知りません。 技術的な制限にもかかわらず、限界を押し広げて印象的なWebエクスペリエンスを革新し、作成する必要が常にありました。 そのため、開発者は、石積みレイアウト、高度な3D効果、高度なアニメーション、流動的なタイポグラフィ、アニメーション化されたグラデーションなど、現在CSSでサポートされていないより高度なスタイリングや効果を実装するために、理想的とは言えない回避策やJavaScriptを使用する傾向があります。スタイル付きのselect要素など。

CSS仕様では、アニメーションの制御の強化、テキストの切り捨ての改善、 input要素とselect要素のスタイルオプションの改善、 displayオプションの増加、 filterオプションの増加など、業界からのさまざまな機能の要求に対応することは不可能のようです。

考えられる解決策は何でしょうか? 開発者に、さまざまなAPIを使用してCSSを拡張するネイティブな方法を提供します。 この記事では、フロントエンド開発者がHoudini API、JavaScript、CSSを使用してそれを行う方法を見ていきます。 各セクションでは、各APIを個別に調べ、そのブラウザーサポートと現在の仕様ステータスを確認し、プログレッシブエンハンスメントを使用してそれらを今日どのように実装できるかを確認します。

ジャンプした後もっと! 以下を読み続けてください↓

Houdiniとは何ですか?

ブラウザAPIのコレクションの総称であるHoudiniは、Web開発プロセスとCSS標準の開発全般に大幅な改善をもたらすことを目的としています。 開発者は、JavaScriptを使用してCSSを新機能で拡張し、CSSレンダリングエンジンに接続して、レンダリングプロセス中にCSSを適用する方法をブラウザーに指示できます。 これにより、通常のポリフィルを使用するよりもパフォーマンスと安定性が大幅に向上します。

Houdini仕様は、高レベルAPIレベルAPIの2つのAPIグループで構成されています。

高レベルのAPIは、ブラウザのレンダリングプロセス(スタイル→レイアウト→ペイント→コンポジット)と密接に関連しています。 これも:

  • ペイントAPI
    視覚的プロパティ(色、背景、境界線など)が決定されるブラウザのペイントレンダリングステップの拡張ポイント。
  • レイアウトAPI
    要素の寸法、位置、および配置が決定される、ブラウザのレイアウトレンダリングステップの拡張ポイント。
  • アニメーションAPI
    レイヤーが画面に描画されてアニメーション化される、ブラウザーの複合レンダリングステップの拡張ポイント。

低レベルAPIは、高レベルAPIの基盤を形成します。 これも:

  • 型付きオブジェクトモデルAPI
  • カスタムプロパティと値API
  • フォントメトリクスAPI
  • ワークレット

一部のHoudiniAPIは、リリースの準備ができたときに追随するために、他のAPIを備えた一部のブラウザーですでに使用可能です。

CSSの未来

これまでに導入された通常のCSS機能仕様とは異なり、Houdiniは、開発者がよりネイティブな方法でCSSを拡張できることで際立っています。 これは、CSS仕様の進化が止まり、CSS機能の新しい公式実装がリリースされないことを意味しますか? まあ、そうではありません。 Houdiniの目標は、開発者が簡単に標準化できる実用的なプロトタイプを作成できるようにすることで、CSS機能の開発プロセスを支援することです。

さらに、開発者はオープンソースのCSSワークレットをより簡単に共有でき、ブラウザー固有のバグ修正の必要性も少なくなります。

型付きオブジェクトモデルAPI

Houdiniが導入される前は、JavaScriptがCSSと対話する唯一の方法は、文字列値として表されるCSSを解析し、それらを変更することでした。 スタイルを手動で解析およびオーバーライドすることは、値のタイプを前後に変更する必要があり、新しい値を割り当てるときに値の単位を手動で追加する必要があるため、困難でエラーが発生しやすい場合があります。

 selectedElement.style.fontSize = newFontSize + "px"; // newFontSize = 20 console.log(selectedElement.style.fontSize); // "20px"

型付きオブジェクトモデル(型付きOM) APIは、CSS値を型付きJavaScriptオブジェクトとして公開することにより、CSS値に意味的な意味を追加します。 これにより、関連するコードが大幅に改善され、パフォーマンス、安定性、および保守性が向上します。 CSS値は、値とユニットプロパティで構成されるCSSUnitValueインターフェイスによって表されます。

 { value: 20, unit: "px" }

この新しいインターフェイスは、次の新しいプロパティで使用できます。

  • computedStyleMap() :計算された(非インライン)スタイルを解析するため。 これは、他のメソッドを解析または使用する前に呼び出す必要がある、選択された要素のメソッドです。
  • attributeStyleMap :インラインスタイルを解析および変更するため。 これは、選択した要素で使用できるプロパティです。
 // Get computed styles from stylesheet (initial value) selectedElement.computedStyleMap().get("font-size"); // { value: 20, unit: "px"} // Set inline styles selectedElement.attributeStyleMap.set("font-size", CSS.em(2)); // Sets inline style selectedElement.attributeStyleMap.set("color", "blue"); // Sets inline style // Computed style remains the same (initial value) selectedElement.computedStyleMap().get("font-size"); // { value: 20, unit: "px"} // Get new inline style selectedElement.attributeStyleMap.get("font-size"); // { value: 2, unit: "em"}

新しい数値を設定するときに、特定のCSSタイプがどのように使用されているかに注意してください。 この構文を使用することにより、多くの潜在的な型関連の問題を回避でき、結果のコードはより信頼性が高く、バグがありません。

getメソッドとsetメソッドは、Typed OMAPIによって定義された使用可能なすべてのメソッドのほんの一部です。 それらのいくつかは次のとおりです。

  • clear :すべてのインラインスタイルを削除します
  • delete :指定されたCSSプロパティとその値をインラインスタイルから削除します
  • has :指定されたCSSプロパティが設定されている場合、ブール値を返します
  • append :複数の値をサポートするプロパティに追加の値を追加します

特徴の検出

var selectedElement = document.getElementById("example"); if(selectedElement.attributeStyleMap) { /* ... */ } if(selectedElement.computedStyleMap) { /* ... */ }

W3C仕様ステータス

  • ワーキングドラフト:コミュニティによるレビューのために公開

ブラウザのサポート

グーグルクロームマイクロソフトエッジOperaブラウザFirefox サファリ
サポートされていますサポートされていますサポートされていますサポートされていません部分サポート(*)

* 「実験的なWebプラットフォーム機能」またはその他の機能フラグを有効にしてサポートされます。

データソース:Houdiniはまだ準備ができていますか?

カスタムプロパティと値API

CSS Properties And Values APIを使用すると、開発者は型、初期値を追加し、継承を定義することでCSS変数を拡張できます。 開発者は、 registerPropertyメソッドを使用してCSSカスタムプロパティを登録することで、CSSカスタムプロパティを定義できます。このメソッドは、ブラウザにCSSを移行し、エラーが発生した場合のフォールバックを処理する方法を指示します。

 CSS.registerProperty({ name: "--colorPrimary", syntax: "<color>", inherits: false, initialValue: "blue", });

このメソッドは、次のプロパティを持つオブジェクトである入力引数を受け入れます。

  • name :カスタムプロパティの名前
  • syntax :カスタムプロパティの解析方法をブラウザに指示します。 これらは、 <color><integer><number><length><percentage>などの事前定義された値です。
  • inherits :カスタムプロパティが親の値を継承するかどうかをブラウザに通知します。
  • initialValue :オーバーライドされるまで使用される初期値を示します。これはエラーの場合のフォールバックとして使用されます。

次の例では、 <color>タイプのカスタムプロパティが設定されています。 このカスタムプロパティは、グラデーション遷移で使用されます。 現在のCSSは背景グラデーションのトランジションをサポートしていないとお考えかもしれませんが、それは正しいことです。 通常background-color遷移に使用されるbackgroundプロパティではなく、カスタムプロパティ自体がtransitionでどのように使用されているかに注目してください。

 .gradientBox { background: linear-gradient(45deg, rgba(255,255,255,1) 0%, var(--colorPrimary) 60%); transition: --colorPrimary 0.5s ease; /* ... */ } .gradientBox:hover { --colorPrimary: red /* ... */ }

ブラウザはグラデーション遷移の処理方法を認識していませんが、カスタムプロパティが<color>タイプとして指定されているため、色遷移の処理方法を認識しています。 Houdiniをサポートするブラウザーでは、要素にカーソルを合わせるとグラデーション遷移が発生します。 グラデーション位置のパーセンテージは、CSSカスタムプロパティ( <percentage>タイプとして登録)に置き換えて、例と同じ方法でトランジションに追加することもできます。

registerPropertyが削除され、通常のCSSカスタムプロパティが:rootセレクターに登録されている場合、グラデーション遷移は機能しません。 ブラウザーがそれを色として扱う必要があることを認識できるように、 registerPropertyを使用する必要があります。

このAPIの将来の実装では、カスタムプロパティをCSSに直接登録することが可能になるでしょう。

 @property --colorPrimary { syntax: "<color>"; inherits: false; initial-value: blue; }

この簡単な例は、色と位置にそれぞれ登録されたCSSカスタムプロパティを使用して、ホバーイベントでのグラデーションの色と位置の遷移を示しています。 完全なソースコードは、サンプルリポジトリで入手できます。

Custom Properties&ValuesAPIを使用してアニメーション化されたグラデーションの色と位置。 CSS遷移プロパティで有効にするために追加された各プロパティの遅延。 (大プレビュー)

特徴の検出

if (CSS.registerProperty) { /* ... */ }

W3C仕様ステータス

  • ワーキングドラフト:コミュニティによるレビューのために公開

ブラウザのサポート

グーグルクロームマイクロソフトエッジOperaブラウザFirefox サファリ
サポートされていますサポートされていますサポートされていますサポートされていませんサポートされていません

データソース:Houdiniはまだ準備ができていますか?

フォントメトリクスAPI

Font Metrics APIはまだ開発の非常に初期の段階であるため、その仕様は将来変更される可能性があります。 現在のドラフトでは、 Font Metrics APIは、開発者が画面上でのテキスト要素のレンダリング方法に影響を与えることができるように、画面上にレンダリングされているテキスト要素の寸法を測定するためのメソッドを提供します。 これらの値は、現在の機能では測定が困難または不可能であるため、このAPIを使用すると、開発者はテキストおよびフォント関連のCSS機能をより簡単に作成できます。 複数行の動的テキスト切り捨ては、これらの機能の1つの例です。

W3C仕様ステータス

  • アイデアのコレクション:現時点では仕様ドラフトは提出されていません

ブラウザのサポート

グーグルクロームマイクロソフトエッジOperaブラウザFirefox サファリ
サポートされていませんサポートされていませんサポートされていませんサポートされていませんサポートされていません

データソース:Houdiniはまだ準備ができていますか?

ワークレット

他のAPIに移る前に、ワークレットの概念を説明することが重要です。 ワークレットは、レンダリング中に実行されるスクリプトであり、メインのJavaScript環境から独立しています。 これらは、レンダリングエンジンの拡張ポイントです。 これらは、並列処理(2つ以上のインスタンス)およびスレッドに依存しないように設計されており、グローバルスコープへのアクセスが制限されており、必要に応じてレンダリングエンジンによって呼び出されます。 ワークレットは、HTTPS(実稼働環境)またはローカルホスト(開発目的)でのみ実行できます。

Houdiniは、ブラウザレンダリングエンジンを拡張するために次のワークレットを導入しています。

  • ペイントワークレット-ペイントAPI
  • アニメーションワークレット-アニメーションAPI
  • レイアウトワークレット-レイアウトAPI

ペイントAPI

Paint APIを使用すると、開発者はJavaScript関数を使用して、HTML5 Canvas APIのサブセットである2Dレンダリングコンテキストを使用して、要素の背景、境界線、またはコンテンツに直接描画できます。 Paint APIは、Paint Workletを使用して、CSSの変更(CSS変数の変更など)に動的に応答する画像を描画します。 Canvas APIに精通している人なら誰でも、HoudiniのPaintAPIに慣れることができます。

ペイントワークレットの定義には、いくつかの手順が必要です。

  1. registerPaint関数を使用してペイントワークレットを作成および登録します
  2. CSS.paintWorklet.addModule関数を使用してHTMLファイルまたはメインJavaScriptファイルでワークレットを呼び出します
  3. ワークレット名とオプションの入力引数を使用して、CSSでpaint()関数を使用します。

ペイントワークレットを登録し、その機能を定義するために使用されるregisterPaint関数を見てみましょう。

 registerPaint("paintWorketExample", class { static get inputProperties() { return ["--myVariable"]; } static get inputArguments() { return ["<color>"]; } static get contextOptions() { return {alpha: true}; } paint(ctx, size, properties, args) { /* ... */ } });

registerPaint関数は、いくつかの部分で構成されています。

  • inputProperties
    Workletが追跡するCSSカスタムプロパティの配列。 この配列は、ペイントワークレットの依存関係を表します。
  • inputArguments
    CSS内からpaint関数から渡すことができる入力引数の配列。
  • contextOptions :色の不透明度を許可または禁止します。 falseに設定すると、すべての色が完全に不透明に表示されます。
  • paint :次の引数を提供するメイン関数:
    • ctx :2D描画コンテキスト。CanvasAPIの2D描画コンテキストとほぼ同じです。
    • size :要素の幅と高さを含むオブジェクト。 値は、レイアウトレンダリングプロセスによって決定されます。 キャンバスのサイズは、要素の実際のサイズと同じです。
    • propertiesinputPropertiesで定義された入力変数
    • args :CSSのpaint関数で渡される入力引数の配列

ワークレットを登録したら、ファイルへのパスを指定するだけでHTMLファイルで呼び出す必要があります。

 CSS.paintWorklet.addModule("path/to/worklet/file.js");

ワークレットは、外部URL(たとえば、コンテンツ配信ネットワークから)から追加することもできます。これにより、ワークレットはモジュール化され、再利用可能になります。

 CSS.paintWorklet.addModule("https://url/to/worklet/file.js");

Workletが呼び出された後、 paint関数を使用してCSS内で使用できます。 この関数は、ワークレットの登録名を最初の入力引数として受け入れ、それに続く各入力引数は、ワークレットに渡すことができるカスタム引数です(ワークレットのinputArguments内で定義されます)。 その時点から、ブラウザーは、いつWorkletを呼び出すか、およびどのユーザーアクションとCSSカスタムプロパティ値が変更されて応答するかを決定します。

 .exampleElement { /* paintWorkletExample - name of the worklet blue - argument passed to a Worklet */ background-image: paint(paintWorketExample, blue); }

次の例は、PaintAPIと一般的なWorkletの再利用性およびモジュール性を示しています。 Google Chrome Labsリポジトリから直接リップルワークレットを使用しており、さまざまなスタイルのさまざまな要素で実行されます。 完全なソースコードは、サンプルリポジトリで入手できます。

リップル効果の例(Google Chrome Labsのリップルワークレットを使用)(大プレビュー)

特徴の検出

if ("paintWorklet" in CSS) { /* ... */ } @supports(background:paint(paintWorketExample)){ /* ... */ }

W3C仕様ステータス

  • 推奨候補:実装の準備ができている安定した作業ドラフト

ブラウザのサポート

グーグルクロームマイクロソフトエッジOperaブラウザFirefox サファリ
サポートされていますサポートされていますサポートされていますサポートされていませんサポートされていません

データソース:Houdiniはまだ準備ができていますか?

アニメーションAPI

Animation APIは、さまざまなイベント(スクロール、ホバー、クリックなど)をリッスンするオプションを備えたWebアニメーションを拡張し、アニメーションワークレットを使用して専用のスレッドでアニメーションを実行することでパフォーマンスを向上させます。 これにより、ユーザーアクションにより、パフォーマンスの高い、ブロックされない方法で実行されるアニメーションのフローを制御できます。

他のワークレットと同様に、アニメーションワークレットを最初に登録する必要があります。

 registerAnimator("animationWorkletExample", class { constructor(options) { /* ... */ } animate(currentTime, effect) { /* ... */ } });

このクラスは、次の2つの関数で構成されています。

  • constructor :新しいインスタンスが作成されたときに呼び出されます。 一般的なセットアップに使用されます。
  • animate :アニメーションロジックを含むメイン関数。 次の入力引数を提供します。
    • currentTime :定義されたタイムラインからの現在の時刻値
    • effect :このアニメーションが使用する一連の効果

アニメーションワークレットを登録したら、メインのJavaScriptファイルに含める必要があります。アニメーション(要素、キーフレーム、オプション)を定義し、選択したタイムラインでアニメーションをインスタンス化する必要があります。 タイムラインの概念とWebアニメーションの基本については、次のセクションで説明します。

 /* Include Animation Worklet */ await CSS.animationWorklet.addModule("path/to/worklet/file.js");; /* Select element that's going to be animated */ const elementExample = document.getElementById("elementExample"); /* Define animation (effect) */ const effectExample = new KeyframeEffect( elementExample, /* Selected element that's going to be animated */ [ /* ... */ ], /* Animation keyframes */ { /* ... */ }, /* Animation options - duration, delay, iterations, etc. */ ); /* Create new WorkletAnimation instance and run it */ new WorkletAnimation( "animationWorkletExample" /* Worklet name */ effectExample, /* Animation (effect) timeline */ document.timeline, /* Input timeline */ {}, /* Options passed to constructor */ ).play(); /* Play animation */

タイムラインマッピング

Webアニメーションは、タイムラインと、現在の時刻のエフェクトの現地時間のタイムラインへのマッピングに基づいています。 たとえば、ページが読み込まれてから1秒後(遅延)に4秒間実行される、3つのキーフレーム(開始、中間、最後)を持つ繰り返し線形アニメーションを見てみましょう。

例のエフェクトタイムラインは次のようになります(遅延のない4秒間の持続時間):

効果のタイムライン(4秒の持続時間) キーフレーム
0ms 最初のキーフレーム-アニメーションが始まります
2000ms 中央のキーフレーム-アニメーションが進行中
4000ms 最後のキーフレーム-アニメーションが終了するか、最初のキーフレームにリセットされます

effect.localTimeをよりよく理解するために、その値を3000msに設定することにより(1000msの遅延を考慮に入れる)、結果のアニメーションはエフェクトタイムラインの中央のキーフレームにロックされます(1000msの遅延+中央のキーフレームの場合は2000ms)。 アニメーションは4000ms間隔(アニメーション期間)で繰り返されるため、値を7000msと11000msに設定しても、同じ効果が発生します。

 animate(currentTime, effect) { effect.localTime = 3000; // 1000ms delay + 2000ms middle keyframe }

アニメーションは特定のキーフレームでロックされているため、 effect.localTime値が一定の場合、アニメーションは発生しません。 要素を適切にアニメーション化するには、そのeffect.localTimeが動的である必要があります。 値は、 currentTime入力引数またはその他の変数に依存する関数である必要があります。

次のコードは、現地時間を有効にするタイムラインの1:1(線形関数)マッピングの機能表現を示しています。

 animate(currentTime, effect) { effect.localTime = currentTime; // y = x linear function }
タイムライン( document.timeline マップされた効果現地時間キーフレーム
startTime + 0ms(経過時間) startTime + 0ms 初め
startTime + 1000ms(経過時間) startTime + 1000ms(遅延)+ 0ms 初め
startTime + 3000ms(経過時間) startTime + 1000ms(遅延)+ 2000ms 真ん中
startTime + 5000ms(経過時間) startTime + 1000ms(遅延)+ 4000ms 最初の最後
startTime + 7000ms(経過時間) startTime + 1000ms(遅延)+ 6000ms 真ん中
startTime + 9000ms(経過時間) startTime + 1000ms(遅延)+ 8000ms 最初の最後

タイムラインは、エフェクトの現地時間への1:1マッピングに制限されていません。 Animation APIを使用すると、開発者は標準のJavaScript関数を使用して複雑なタイムラインを作成することにより、 animate関数のタイムラインマッピングを操作できます。 アニメーションも、各反復で同じように動作する必要はありません(アニメーションが繰り返される場合)。

アニメーションは、ドキュメントが読み込まれた瞬間からミリ秒単位でカウントを開始するドキュメントのタイムラインに依存する必要はありません。 スクロールイベントなどのユーザーアクションは、 ScrollTimelineオブジェクトを使用してアニメーションのタイムラインとして使用できます。 たとえば、アニメーションは、ユーザーが画面上で200ピクセルまでスクロールしたときに開始し、ユーザーが800ピクセルまでスクロールしたときに終了することができます。

 const scrollTimelineExample = new ScrollTimeline({ scrollSource: scrollElement, /* DOM element whose scrolling action is being tracked */ orientation: "vertical", /* Scroll direction */ startScrollOffset: "200px", /* Beginning of the scroll timeline */ endScrollOffset: "800px", /* Ending of the scroll timeline */ timeRange: 1200, /* Time duration to be mapped to scroll values*/ fill: "forwards" /* Animation fill mode */ }); ...

アニメーションは自動的にユーザーのスクロール速度に適応し、スムーズで応答性を維持します。 アニメーションワークレットはメインスレッドから実行され、ブラウザのレンダリングエンジンに接続されているため、ユーザーのスクロールに依存するアニメーションはスムーズに実行され、非常にパフォーマンスが高くなります。

次の例は、非線形タイムラインの実装方法を示しています。 修正されたガウス関数を使用し、同じタイムラインで平行移動と回転のアニメーションを適用します。 完全なソースコードは、サンプルリポジトリで入手できます。

修正されたガウス関数の時間マッピングを使用するアニメーションAPIで作成されたアニメーション(大プレビュー)

特徴の検出

if (CSS.animationWorklet) { /* ... */ }

W3C仕様ステータス

  • 最初の公開草案:コミュニティレビューの準備ができており、仕様が変更される傾向があります

ブラウザのサポート

グーグルクロームマイクロソフトエッジOperaブラウザFirefox サファリ
部分サポート(*) 部分サポート(*) 部分サポート(*) サポートされていませんサポートされていません

* 「実験的なWebプラットフォーム機能」フラグを有効にしてサポートされます。

データソース:Houdiniはまだ準備ができていますか?

レイアウトAPI

Layout APIを使用すると、開発者は、CSSプロパティのdisplayで使用できる新しいレイアウトモードを定義することにより、ブラウザーのレイアウトレンダリングプロセスを拡張できます。 Layout APIは新しい概念を導入し、非常に複雑で、カスタムレイアウトアルゴリズムを開発するための多くのオプションを提供します。

他のワークレットと同様に、レイアウトワークレットを最初に登録して定義する必要があります。

 registerLayout('exampleLayout', class { static get inputProperties() { return ['--exampleVariable']; } static get childrenInputProperties() { return ['--exampleChildVariable']; } static get layoutOptions() { return { childDisplay: 'normal', sizing: 'block-like' }; } intrinsicSizes(children, edges, styleMap) { /* ... */ } layout(children, edges, constraints, styleMap, breakToken) { /* ... */ } });

ワークレットレジスタには、次のメソッドが含まれています。

  • inputProperties
    Workletが追跡するCSSカスタムプロパティの配列は、親レイアウト要素、つまりこのレイアウトを呼び出す要素に属します。 この配列は、レイアウトワークレットの依存関係を表します。
  • childrenInputProperties
    親レイアウト要素の子要素、つまりこのレイアウトを設定する要素の子に属する、ワークレットが追跡するCSSカスタムプロパティの配列。
  • layoutOptions :次のレイアウトプロパティを定義します。
    • childDisplayblockまたはnormalの事前定義された値を持つことができます。 ボックスをブロックとして表示するかインラインで表示するかを決定します。
    • sizingblock-likeまたはmanualの事前定義された値を持つことができます。 サイズを事前に計算するか、事前に計算しないか(サイズが明示的に設定されていない場合)をブラウザに指示します。
  • intrinsicSizes :ボックスまたはそのコンテンツがレイアウトコンテキストにどのように適合するかを定義します。
    • children :親レイアウト要素の子要素、つまりこのレイアウトを呼び出す要素の子。
    • edges :ボックスのレイアウトエッジ
    • styleMap :ボックスの入力されたOMスタイル
  • layout :レイアウトを実行する主な機能。
    • children :親レイアウト要素の子要素、つまりこのレイアウトを呼び出す要素の子。
    • edges :ボックスのレイアウトエッジ
    • constraints :親レイアウトの制約
    • styleMap :ボックスの入力されたOMスタイル
    • breakToken :ページ付けまたは印刷の場合にレイアウトを再開するために使用されるブレークトークン。

Paint APIの場合と同様に、ブラウザのレンダリングエンジンは、ペイントWorkletがいつ呼び出されるかを決定します。 HTMLまたはメインのJavaScriptファイルに追加するだけで済みます。

 CSS.layoutWorklet.addModule('path/to/worklet/file.js');

そして最後に、CSSファイルで参照する必要があります

.exampleElement { display: layout(exampleLayout); }

LayoutAPIがレイアウトを実行する方法

前の例では、 exampleLayoutはLayoutAPIを使用して定義されています。

 .exampleElement { display: layout(exampleLayout); }

この要素は親レイアウトと呼ばれ、パディング、境界線、スクロールバーで構成されるレイアウトエッジで囲まれています。 親レイアウトは、現在のレイアウトと呼ばれる子要素で構成されます。 現在のレイアウトは、レイアウトAPIを使用してレイアウトをカスタマイズできる実際のターゲット要素です。 たとえば、 display: flex; 要素では、その子が再配置されてフレックスレイアウトが形成されます。 これは、LayoutAPIで行われていることと似ています。

現在の各レイアウトは、LayoutChild(要素、 ::beforeおよび::after疑似要素)のレイアウトアルゴリズムである子レイアウトで構成され、 LayoutChildはスタイルデータのみを含む(レイアウトデータを含まない)CSS生成ボックスです。 LayoutChild要素は、スタイルステップでブラウザレンダリングエンジンによって自動的に作成されます。 Layout Childは、実際にレイアウトレンダリングアクションを実行するフラグメントを生成できます。

Paint APIの例と同様に、この例では、石積みレイアウトのワークレットをGoogle Chrome Labsリポジトリから直接インポートしていますが、この例では、テキストではなく画像コンテンツで使用されています。 完全なソースコードは、サンプルリポジトリで入手できます。

組積造のレイアウト例(Google Chrome Labsの組積造ワークレットを使用(大プレビュー)

特徴の検出

if (CSS.layoutWorklet) { /* ... */ }

W3C仕様ステータス

  • 最初の公開草案:コミュニティレビューの準備ができており、仕様が変更される傾向があります

ブラウザのサポート

グーグルクロームマイクロソフトエッジOperaブラウザFirefox サファリ
部分サポート(*) 部分サポート(*) 部分サポート(*) サポートされていませんサポートされていません

* 「実験的なWebプラットフォーム機能」フラグを有効にしてサポートされます。

データソース:Houdiniはまだ準備ができていますか?

フーディーニとプログレッシブエンハンスメント

CSS Houdiniはまだ最適なブラウザーサポートを備えていませんが、プログレッシブエンハンスメントを念頭に置いて今日使用できます。 プログレッシブエンハンスメントに慣れていない場合は、それを非常によく説明しているこの便利な記事をチェックする価値があります。 今日、プロジェクトにHoudiniを実装することにした場合、覚えておくべきことがいくつかあります。

  • エラーを防ぐために機能検出を使用してください。
    各HoudiniAPIとワークレットは、ブラウザーで利用可能かどうかを確認する簡単な方法を提供します。 機能検出を使用して、Houdiniの拡張機能を、それをサポートし、エラーを回避するブラウザーにのみ適用します。
  • プレゼンテーションと視覚的な強化にのみ使用してください。
    HoudiniをまだサポートしていないブラウザでWebサイトを閲覧しているユーザーは、Webサイトのコンテンツとコア機能にアクセスできる必要があります。 ユーザーエクスペリエンスとコンテンツの表示は、Houdiniの機能に依存するべきではなく、信頼できるフォールバックを備えている必要があります。
  • 標準のCSSフォールバックを利用します。
    たとえば、通常のCSSカスタムプロパティは、カスタムプロパティと値APIを使用して定義されたスタイルのフォールバックとして使用できます。

最初にパフォーマンスが高く信頼性の高いWebサイトのユーザーエクスペリエンスを開発することに重点を置き、次にプログレッシブエンハンスメントとして装飾目的でHoudini機能を使用します。

結論

Houdini APIにより、開発者はスタイルの操作と装飾に使用されるJavaScriptコードをブラウザーのレンダリングパイプラインに近づけることができるようになり、パフォーマンスと安定性が向上します。 開発者がブラウザのレンダリングプロセスに接続できるようにすることで、CSS仕様自体に簡単に共有、実装、および追加できるさまざまなCSSポリフィルを開発できるようになります。 Houdiniはまた、開発者やデザイナーがスタイリング、レイアウト、アニメーションで作業する際のCSSの制限による制約を緩和し、新しい楽しいWebエクスペリエンスを実現します。

CSS Houdiniの機能は、今日のプロジェクトに追加できますが、厳密にはプログレッシブエンハンスメントを念頭に置いています。 これにより、Houdini機能をサポートしていないブラウザーが、エラーなしでWebサイトをレンダリングし、最適なユーザーエクスペリエンスを提供できるようになります。

Houdiniが牽引力を獲得し、ブラウザーのサポートが向上するにつれて、開発者コミュニティが何を思いつくかを見るのはワクワクするでしょう。 コミュニティからのHoudiniAPI実験のいくつかの素晴らしい例を次に示します。

  • CSSHoudini実験
  • CSSHoudiniのインタラクティブな紹介
  • Google ChromeLabsによるHoudiniサンプル

参考文献

  • W3CHoudini仕様ドラフト
  • Houdini州(Chrome Dev Summit 2018)
  • Houdiniのアニメーションワークレット-GoogleDevelopers
  • CSSHoudiniのインタラクティブな紹介