CSS Houdiniを味見する
ソフトウェアエンジニアの畠山です。この度 "CSS Houdini" が気になったので調べてみることにしました。
CSS Houdiniとは
CSSは他のWeb技術と同様,標準化が日々進められていますが,標準化にはかなりの時間が掛かります。機能の提案がされてから,仕様をつくり,各ブラウザがそれを実装します。それから,古いバージョンのブラウザの影響を考えて,ようやく開発者は新しいCSSの機能を使用できるようになります。
CSS Houdiniは,CSSの拡張性のために誕生したタスクフォースです。標準化のプロセスを待たずにCSSの機能を拡張したい。開発者コミュニティで新しいCSSのプロパティを作れるようにしたい。そのために必要なAPIを提供すべく仕様を策定しているタスクフォースがCSS Houdiniなのです。
<br>
Houdiniの現状
Houdiniのステータスは"Is Houdini Ready Yet?” というサイトで確認出来ます。本記事執筆時点(2018年06月26日)ではほとんどのAPIがまだドラフトの段階です。例の如くChromeが先行して実装を進めている状況です。
HoudiniのAPIたち
ここで,Houdiniの各種APIについて説明したいと思います。
※ 現在これらは仕様策定の初期段階ですので,将来変更される可能性があります。それを踏まえてご覧下さい。
Properties and Values API
CSSには既にCSS Variablesという機能が存在していますが,"Properties and Values API"はその拡張です。
- プロパティの型
- プロパティの初期値
- 継承の振る舞い
を指定することができます。実際のコードは以下のような見た目になります。--my-color
というプロパティを登録しているサンプルです。
window.CSS.registerProperty({
name: "--my-color", //プロパティ名
syntax: "<color>", //型
inherits: false, //継承
initialValue: "rgba(0,0,0,0)" //初期値
});
CSSからは以下のように使用します。
.button {
--my-color: red;
background: linear-gradient(var(--my-color), black);
transition: --my-color 1s;
}
.button:hover {
--my-color: green;
}
もしも間違った型の値を指定した場合は,初期値にフォールバックしてくれます。
Properties and Values APIは,執筆時点ではChrome Canaryに一部実装されています。"Experimental Web Platform features" フラグを有効にすると使用できます。
Typed OM
JavaScriptからCSSにアクセスしたいとき,従来の方法では window.getComputedStyle
を使用できます。例えば次のようなCSSにJavaScriptからアクセスしたいとき,以下のように書くことができます。
.example {
width: 50%;
height: 100px;
}
let element = document.querySelector('.example');
let style = window.getComputedStyle(element);
let height = getPropertyValue("height");
console.log(height); // 24px
console.log(typeof height); // string
ご覧のように取得できる値は文字列です。プログラムで使うには不便です。更に,CSSの値を読む度に毎回必ず文字列を生成することになり,ガーベジコレクションによって60fpsの達成を妨げる可能性があります。CSS Typed OMはこの問題を解決します。名前の通りCSSに対して型を持ったデータ構造にアクセス可能になります。
下記のようなCSSStyleValue
オブジェクトがいくつか用意されています。
CSSUnitValue
CSSPositionValue
CSSTransformValue
CSSMathValue
…
ex.) CSSUnitValue
let unitValue = new CSSUnitValue(11, 'px');
これらのオブジェクトは,"Style Map"としてアクセスすることができます。先程のCSSの例に対しては以下のようにアクセスできます。
let styleMap = element.computedStyleMap();
let w = styleMap.get("width");
let h = styleMap.get("height");
console.log(w.value, w.unit); // 50 "percent"
console.log(h.value, h.unit); // 100 "px"
前述したCSSStyleValue
オブジェクトを取得出来る (読み取り専用) のでそのままプログラムで使用できます。また,余計な文字列の生成も行わないので,先程述べたガーベジコレクションの心配もありません。
Typed OMはChrome 66に実装されています。
Worklet
"Worklet" は軽量なWeb workerのようなものです。以下のように何種類か定義されています。
PaintWorklet
AnimationWorklet
LayoutWorklet
CSSプロパティを拡張するためにはこれらのWorkletを用います。
Paint API
PaintWorklet
を追加すれば,任意のボックス領域にCanvas API (のサブセット) で自由に描画することができます。
window.CSS.paintWorklet.addModule("my-paint-worklet.js");
// my-paint-worklet.js
registerPaint("my-paint", class MyPaint { ... });
/* style */
.example {
background-image: paint(my-paint);
}
以下のサンプルでは,ボックスの background-image
を水玉模様にするCSSを追加しています。
See the Pen Polka Dots (CSS Houdini Demo) by Sota Hatakeyama @chooblarinon CodePen.
次のサンプルは,ボックス要素を星型にするCSSを追加しています。
See the Pen Star block (CSS Houdini Demo) by Sota Hatakeyama (@chooblarin) on CodePen.
以下のサンプルは,ボタン押下時にRippleエフェクトを追加しています。
See the Pen Ripple Buttons (CSS Houdini Demo) by Sota Hatakeyama (@chooblarin) on CodePen.
Paint APIはChrome 65に実装されています。
Layout API
LayoutWorklet
を追加することで,独自のレイアウトアルゴリズムのCSSを追加することが出来ます。
window.CSS.layoutWorklet.addModule("my-layout-worklet.js");
// my-layout-worklet.js
registerLayout('centering', class extends Layout {
*layout(constraintSpace, children, styleMap) {
...
}
...
});
/* style */
.example {
display: layout(centering);
}
現状のカスタムレイアウト(例えばMasonryのような)はJavaScriptを用いて実現されているものが多いですが,こういったものをCSSプロパティで指定できるようになります。Layout APIではWorkletを使用してレイアウトのコードを並列に実行するため,パフォーマンスの面でも有利です。
Layout APIは執筆時点では,Chrome Canaryで一部実装されています。"Experimental Web Platform features" フラグを有効にすると使用できます。
Font Metrics API
テキストのメトリクスを取得するためのAPIです。以下のようなメトリクスを取得できます。
- width
- height
- ascent
- decent
- baseline
etc…
Font Metrics APIは執筆時点で実装はありません。
Parser API
CSSのパーサーを解放する仕様です。CSSのテキストをTyped OMにパースできるようになります。これによってCSSの構文自体を拡張することが可能になります。
実はParser APIの策定は現在,HoudiniではなくWICG (Web Platform Incubator Community Group) で進行しています。
Animation Worklet
ハイパフォーマンスなアニメーションを実現します。"Sticky Header" や "Parallax Effect" などのリッチなアニメーションを追加することができます。Animation Workletは以下のようにして追加します。(parallax effectの例です。完全なコードはこちらです。)
window.animationWorklet.addModule("animation-worklet.js").then(_ => {
const workletAnim = new WorkletAnimation("parallax",
new KeyframeEffect(parallax, [
{ 'transform': 'translateY(0)' },
{ 'transform': 'translateY(' + -scrollRange + 'px)' }
], scrollRange),
new ScrollTimeline({ scrollSource: scroller, timeRange: 1 })
);
});
// animation-worklet.js
registerAnimator("parallax", class {
animate(currentTime, effect) {
...
}
});
Animation Workletは執筆時点では,Chrome Canaryで一部実装されています。
おわりに
CSS Houdiniの各種APIにより,CSSの機能をブラウザが提供するJavaScriptのAPIで拡張することが可能になります。将来,Webサイトのレイアウトやスタイルに関する大部分を,CSSプロパティを追加するだけで解決できるようになるかもしれません。Webデベロッパーの体験は大きく向上すると思います。
弊社では,一緒にWebの技術を楽しめるフロントエンドのエンジニアを募集しています。こちらまでお願いします。
参考
その他の記事
Other Articles
関連職種
Recruit