🔘

<button>とかのスタイルを消して書き直すときに考えることの備忘録

2024/01/01に公開

all: unset; などを使ってUAスタイルシートを消してまっさらな場所からスタイルを当てるのは気持ちがいいですが、アクセシビリティ等の観点から重要な分岐が見落とされる可能性があります。

ここではChromeのUAスタイルシートを参考に、検討しておいたほうがいい状態をいくつかリストします。

(もちろん、既存のUIコンポーネントライブラリの使用が可能であれば、それが最も堅牢な選択肢でしょう。)

参考

UAスタイルの中には、CSSのカスケードルールの範疇で実装されているものもあれば、レンダリングエンジンの特別処理として書かれていて作者スタイルシートでの上書きが不可能なものもあります。これはブラウザ実装により異なります。

スコープ

UIコンポーネントを作るような場面を想定しています。したがって、要素名自体は固定として、その中で見落としがちな分岐をリストアップします。

display: block;box-sizing: border-box; をはじめとして、静的なデザインを適用する時点で必要になることが明らかなものはここには書きません。

<input> は実質的に <input type="..."> の値ごとに別種の要素であるとみなします。

本記事の目標は、見落としを防いでinformed decisionをすることにあります。想定する品質ラインは、Webブラウザのデフォルト挙動と同等程度です。 (それ以上の使いやすさを考えるのは本記事のスコープ外です)

カーソル

  • UAスタイルシートでは、 <label>, <select> およびボタン類のフォームコントロールには cursor: default; がついている。
    • テキストが cursor: text; 相当になるのを抑止して、クリック動作を示すため。
    • テキスト類のフォームコントロールは <label> のcursorを継承してくることがあるため、これを cursor: auto; にリセットしている。
  • UAスタイルシートでは、ボタン類のフォームコントロールには user-select: none; がついている。
  • UAスタイルシートでは、テキスト類のフォームコントロールには user-select: text; がついている。
    • UAスタイルシートの範囲内では、これはデフォルト値である auto と同等の挙動のはずです。祖先コンポーネントで user-select が上書きされている場合にテキスト入力の動作が意図せず変わってしまわないように明示しているのでしょう。
  • UAスタイルシートでは、テキスト類のフォームコントロールには unicode-bidi: plaintext; がついている。

擬似クラス / 属性セレクタ

擬似クラスや属性による条件分岐を見落とすと、UAで当てられていた必要なスタイルが削除されてしまい、アクセシビリティ等の観点から問題が発生する可能性があります。

  • テキスト類のフォームコントロール (<input type="text">, <input type="search"> etc.)
    • :focus または :focus-visible ... キーボード操作時等のフォーカス表示
    • :enabled または :disabled ... フォームコントロールが利用不可能であることを視覚的に表示
    • :autofill ... オートフィルが発生した場合。(ChromeやSafariでは !important がついていてどの道上書きされません)
  • ボタン類のフォームコントロール
    • :focus または :focus-visible ... キーボード操作時等のフォーカス表示
    • :enabled, :disabled, または [disabled] ... フォームコントロールが利用不可能であることを視覚的に表示
    • :active ... ユーザーによるボタン押下に反応
      • テキスト類でも利用可能だが、UAスタイルシートではあまり使われていない
  • リンク
    • :any-link または [href] ... 実際にリンクになっているかどうかを確認してスタイルを当てるのが望ましい
    • :focus または :focus-visible ... キーボード操作時等のフォーカス表示
    • :enabled または :disabled ... フォームコントロールが利用不可能であることを視覚的に表示
    • :active ... ユーザーによるボタン押下に反応
    • :link または :visited
      • WebKit/Blinkではこの擬似クラスを使わず、 color: -webkit-link; を指定することで暗黙的に同じ効果を達成している
  • チェックボックス
    • フォーカス、有効状態、アクティブについては上記を参照
    • :checked ... 状態特有のスタイルを当てる場合は、 :indeterminate 状態も考慮が必要。
  • ダイアログ (<dialog>)
    • :open, :close, または [open] ... 閉じている場合は display: none; にする必要がある
      • <details> でも同様の考慮が必要だが、これはレンダリングエンジンの特殊実装になっていることが多そう
    • :modal ... モーダルかどうかによって表示を変えることが期待されている
  • その他のフォーカス可能な要素 (フォームコントロール内の補助的なウィジェット、<dialog>, <iframe>, スクロール可能な要素、またはtabindexが設定されている場合など)
    • :focus または :focus-visible ... キーボード操作時のフォーカス表示

意外なことに、以下の擬似クラスはUAスタイルシートではあまり使われていません。

  • :hover
    • サイトによっては、マウスポインタが上にあるときにはボタンを強調するなどのスタイルを当てることがあります。
  • [readonly], :read-only または :read-write
    • enabled/disabled とは別の概念です。
    • 入力不可能であることを視覚的に表示することが可能です。

擬似要素

擬似要素のスタイルはオリジナル要素のスタイルとは独立にカスケードするため、必要な処理を怠るとUAのスタイルが残ったままになってしまいます。

Tree-abiding

複雑なフォームコントロールや <video> 要素などは内部にシャドウ要素を含んでおり、これらにはブラウザ固有の擬似要素でアクセスできることがあります。 (例: ::-webkit-clear-button) こういったもののうち、ベンダープレフィックスが必要な擬似要素については扱わないことにします。

  • ::placeholder
    • テキスト系のフォームコントロールなどで発生します。これらのコントロールのスタイルを設定するなら、一緒に設定しておくといいでしょう。
    • color を設定するのが一般的でしょう。
  • ::before, ::after
    • <q> など一部の要素で使われていることがあるので、必要に応じて上書きするといいでしょう。
    • :before, :after と書かれていることもあります。
  • ::marker
    • display: list-item のときだけ発生するので、通常は注意する必要はありません。
  • ::file-selector-button
    • フォームコントロールのシャドウ要素のなかでは珍しく、標準的な擬似要素でアクセスできます。
  • ::backdrop
    • ダイアログで使われます。

ハイライト

これらはページ全体のテーマの一部として設定されることが多いでしょう。

  • ::selection
  • ::target-text
  • ::spelling-error
  • ::grammar-error

強制スタイル

UAスタイルシートには !important がついているものもあります。これらはオリジン優先度の関係で作者スタイルシートからは上書きできません。これらのスタイルが強制されていてもなるべく問題がないようにスタイルを当てるのがよいでしょう。

ここではブラウザやスペックの記述から発見された候補を列挙していますが、これらが常に !important であるとは限りません。ベンダープレフィックスのあるものは原則として除いています。

  • いくつかの display: none; 指定はレンダリングエンジンに組み込みのルールとして実装されていることがあります。
  • フォームコントロールの横書き強制
  • ::placeholderuser-events: none
  • <input type="file">text-align: start
  • :autofillcolor および background
  • <select>overflow: visible
  • <input>overflow: clip, overflow-clip-margin: 0

タグ固有のボックス

<a><button> の両方に使えるスタイルを作る場合などには、特定のタグでのみ発生するボックス構造に注意が必要です。

メディア特性

UIの状態を示すために視覚効果を使うのは重要なことですが、それをなるべく多くの環境で効果的に適用するにはメディア特性も考慮するといいでしょう。

Webブラウザのデフォルトのウィジェットを使う限りにおいてはブラウザがある程度考慮してくれることもありますが、それを上書きする場合は考慮漏れのリスクが多少あります。

Discussion