プロンプトとコンテキスト
コンポーネントライブラリで --accent、--progress、--card-size などのカスタムプロパティが使用されています。デザイン要件ではスムーズなトランジションが求められていますが、変数は型のない文字列であり、無効な値が暗黙的に伝播し、子コンポーネントが誤ってテーマの値を継承してしまいます。デフォルト値、無効な値、継承、ブラウザ互換性を含め、CSS の @property を使用してこれらを登録すべきタイミングを説明してください。
これはフロントエンド、デザインシステム、Web パフォーマンスの面接に適しています。テストの目的は、すべての変数を登録することではなく、CSS Properties and Values API の境界を理解しているかどうかです。構文、初期値、継承、補間、スコープ、プログレッシブエンハンスメント、テストについて説明してください。
面接官がテストしていること
優れた回答では、通常のカスタムプロパティは文字列として計算されデフォルトで継承されるのに対し、登録されたプロパティは型、初期値、継承動作を宣言し、計算値の算出時(computed-value time)に無効な値がチェックされることを説明します。syntax と inherits が必須の記述子であること、ユニバーサル構文以外では通常、計算上独立した initial-value が必要であること、そしてアニメーション、型の制約、非継承のコンポーネント状態が登録を正当化するタイミングを説明します。@property を JavaScript の状態や自動的なパフォーマンス保証として提示しないでください。
最初に確認すべき質問
- その変数にはどのような型が含まれるか:color、length、angle、number、または自由なトークン文字列か?
- スムーズな補間が必要か、それとも不連続なテーマの切り替えだけでよいか?
- 子要素に継承させるべきか、それともコンポーネント境界で分離すべきか?
- 無効な値が指定された場合、初期値、継承値、または宣言なしのどれになるべきか?
- 対象ブラウザ、サーバーレンダリングのパス、フォールバック、デザイントークンのリリースプロセスはどのようになっているか?
30秒の回答
「通常のカスタムプロパティは継承される文字列であり、オープンなトークンに適しています。型チェック、非継承のデフォルト値、またはスムーズな補間が必要な場合にプロパティを登録します。登録には syntax、inherits、および計算上独立した initial-value を指定する必要があり、これにより無効な代入の挙動が予測可能になります。古いブラウザではフォールバックとして通常の変数が維持され、コンポーネントテストで継承、無効な値、アニメーション、テーマの変更をカバーします。登録すること自体で自動的に高速化されるわけではありません。」
ステップごとの回答
ステップ 1: 通常の変数と登録されたプロパティを区別する
通常の --name はカスケードに参加し、デフォルトで継承されます。ブラウザはその値をトークンの並びとして扱います。これは色、スペーシングトークン、オープンなコンポジションには便利ですが、ブラウザはその値が色であるべきか長さであるべきかを認識しません。@property は、同じ変数に型、継承、デフォルト値のメタデータを追加します。
ステップ 2: 明示的な構文(syntax)を選択する
制約や補間が必要な値のみを登録します。一致する値に対して、CSS の color、number、angle などの構文タイプを使用します。厳格に見せるためだけに、複数トークンの実験的な値を1つの型に無理に押し込めないでください。有効なテーマ値まで破棄されてしまいます。
ステップ 3: inherits と initial-value を設定する
inherits を明示します。テーマカラーは通常継承されますが、コンポーネント内部のサイズやアニメーションの進行状況は継承されない場合があります。ユニバーサル構文以外では、親に依存するパーセンテージではなく固定単位など、計算上独立した initial-value が必要です。必須の記述子が欠落していると、登録が無効になります。
ステップ 4: 無効な値とフォールバックを理解する
登録されたプロパティは計算値の算出時に検証されます。型が誤っている値は適用されず、inherits と宣言の場所に応じて、登録された初期値、継承、またはカスケードの別の有効な結果を通じてプロパティが解決されます。initial、inherit、unset、revert などのグローバルキーワードには引き続き特別なセマンティクスがあるため、個別のテストが必要です。
ステップ 5: 補間可能なアニメーションを使用する
未登録のカスタムプロパティは、ブラウザが任意の文字列を補間できないため、通常は不連続に変化します。color、length、または number として登録されると、ブラウザはグラデーション、進捗、回転を補間する方法を認識します。それでも、継続時間、合成、reduced-motion(視覚効果の抑制)の動作、および多数の要素を更新する実際のコストをテストしてください。
ステップ 6: コンポーネントの境界を制御する
グローバルなテーマのトークンと内部状態は別々に命名します。継承する値はテーマに役立ちます。非継承プロパティを使用すると、コンポーネントが自身の初期値を使用でき、親の同名変数が内部アニメーションを汚染するのを防ぐことができます。プロパティが Shadow DOM やコンテナの境界を越える場合は、登録を決定する前に名前空間と公開 API を定義してください。
ステップ 7: プログレッシブエンハンスメントを提供する
まず通常のカスタムプロパティと静的な最終状態を提供し、@property に対応していないブラウザでも実用的な UI がレンダリングされるようにします。サポートされているブラウザでは、型の制約と補間を追加できます。重要なレイアウトが登録のみに依存しないようにしてください。拡張パスを選択する際は、@supports (property: --x) または機能検出を使用します。
ステップ 8: エラーとブラウザの動作を検証する
有効な値、誤った型、初期値の欠落、継承の切り替え、テーマの上書き、アニメーション中の更新、サーバーレンダリングによる初回描画をテストします。古いブラウザ、開発者ツールの計算値、および視覚的なリグレッションを確認してください。MDN が指摘しているように、登録は計算値の算出時に検証され、不正な形式のルールは完全に無視される可能性があるため、ビルドチェックとランタイムの例の双方が重要です。
トレードオフと限界
登録には宣言やデザイントークンのメンテナンスコストが伴い、この API に不慣れなコントリビューターはすべての値が自由に置き換え可能であると思い込む可能性があります。明確な型、アニメーションの必要性、デフォルト値、または継承境界を持つ値を登録し、自由形式のコンテンツトークンは通常のカスタムプロパティのままにしておきます。
型チェックはセキュリティ境界でも、ブラウザ間の一貫性を保証するものでもありません。サポート状況、解析のタイミング、アニメーション合成については、ターゲットマトリクスでのテストが依然として必要です。重要なアクセシビリティ状態には静的なスタイルと reduced-motion のパスが必要です。
ロールアウト計画と検証
進捗または色のコンポーネント1つでパイロット運用を実施します。各変数の目的、型、継承ポリシー、フォールバックを記録します。有効な例と無効な例を使用して計算結果を検証し、登録前後のアニメーションの滑らかさ、スタイルの再計算、古いブラウザの動作を比較します。パイロットに合格したら、登録、トークンのドキュメント、視覚的リグレッションテストをコンポーネントライブラリのリリースチェックに組み込みます。
syntax または inherits の変更はすべて動作の変更として扱い、子要素の上書き、テーマの切り替え、永続化されたスナップショットを検査します。ユーザーから色のジャンプやサイズのフォールバックが報告された場合は、アニメーションの継続時間を変更する前に計算値と機能パスを検査してください。
よくある間違いとフォローアップ
すべての CSS 変数を登録してしまう
オープンなトークン、複合値、実験的な文字列には、安定した構文がない場合があります。型、デフォルト値、継承制御、または補間が必要な値のみを登録してください。
initial-value の計算上の独立性を忘れる
ユニバーサル構文以外の場合、初期値はコンテキストに依存できません。パーセンテージや em は登録を無効にする可能性があります。計算上独立した単位を使用するか、ユニバーサル構文で緩やかな制約を受け入れます。
無効な値が直前の有効な宣言を保持すると誤認する
登録されたプロパティは計算値の算出時に検証されます。無効な代入は、直前の古い値ではなく、初期値や継承された結果に解決されることがあります。ソースの順序だけでなく、計算されたスタイルをテストしてください。
inherits を完全なカスケード分離として扱う
inherits: false はデフォルトの継承を制御します。作成者は依然として inherit と書くことができ、別のトークンが親の値をコンポーネントに持ち込むことも可能です。命名、ドキュメント、テストを組み合わせて境界を強制する必要があります。
@property をサポートしていないブラウザにはどう対応するか?
静的な最終状態と適切なデフォルト値を持つ通常の変数を維持し、拡張として登録とアニメーションを追加します。クリティカルパスには @supports または機能検出を使用し、対象ブラウザマトリクス全体で初回描画、テーマ、および reduced-motion をテストします。