labelでinput[type="file"]を装飾する話の記事
label で input[type="file"] を装飾するな
読んだ。
ひとまずlabelで装飾しているところがないか手元のコードを確認したけど、コンポーネントライブラリを使っていたりしてひとまず大丈夫そうだった。
問題は
- フォーカスが当たらない
- tabIndexを設定してもlabelはclickableではないのでSpace/Enterでclickイベントを発火させられない
のふたつ。
解決策は、
- button要素を用意する
- そのbuttonのclickイベントに、input要素のclickイベントを発火させる関数を定義する
- button要素が適切でない場合にはアクセシビリティに配慮したボタンを用意する
<div role="button" tabindex="0">ファイルを選択</div>
<input type="file" />
↑記事内のコードを引用
miyaokaさんのやり方↓
これウチだとinputはdisplay:noneではなくopacity:0;pointer-evnets:noneにしてfocusできるようにして、focus時のlabelハイライトをfocus-withinで対処したな / label で input[type="file"] を装飾するな|dqn https://t.co/vahf4K7wHx #zenn
— miyaoka (@miyaoka) March 1, 2022
labelを使うやり方で、input要素をdisplay: none;
にするのではなく
.input {
opacity: 0; /* 要素は完全に透明で不可視 */
pointer-events: none; /* 要素がポインターのイベント対象にならない */
}
のようにして、clickイベントは発生しないがtabでのフォーカスをできるようにし、:focus-within
でフォーカス時のスタイルを調整しているという感じらしい。
こうすることで、button要素の追加やclickイベントを発火する関数の定義をしないでCSSだけでいけるのか、なるほど。
ウェブアプリケーションからのファイルの使用 - Web API | MDN
opacity - CSS: カスケーディングスタイルシート | MDN