そのためにJavaScriptは必要ありません
(htmhell.dev)- Web機能を実装する際は、HTML、CSS、JavaScriptの順に、より強力でない技術を先に検討するほうが、読み込み失敗やアクセシビリティの問題を減らすうえで有利
- JavaScriptはブラウザーの動作を直接制御できる一方で、追加リソースやエラーの可能性があるため、キーボード利用者・支援技術利用者を排除しやすい
- 以前はJavaScriptが必要だったチェックボックススイッチ、
datalist、input type="color"、details/summary、dialogのような機能が、今ではHTML/CSSの基本機能でかなり実現できるようになっている - HTMLとCSSの宣言的機能では、ブラウザーがネイティブ動作、ユーザー環境設定、アクセシビリティ対応を担えるため、より良いデフォルトを提供しやすい
- 慣れ親しんだJavaScript実装が動き続けていても、最新のHTML/CSSによる代替手段を定期的に確認し、置き換える際はアクセシビリティテストもあわせて行うべき
最小権限の原則
- 最小権限の原則とは、目的を達成できる中で最も強力でない言語を選ぶべきだというWeb開発の原則
- Webでは通常、HTMLをCSSより先に、CSSをJavaScriptより先に検討する形で適用される
- JavaScriptはこの3つの技術の中で最も多機能だが、そのぶん負担も大きい
- 壊れる可能性がある
- 読み込みに失敗する可能性がある
- ダウンロード、パース、実行に追加リソースが必要
- キーボード利用者や支援技術利用者を排除しやすい
- HTMLとCSSは、命令的なJavaScriptと異なり、宣言的に動作する
- 開発者はブラウザーに何をしたいかを伝え、実装方法はブラウザーが選ぶ
- ブラウザーがより効率的な処理方法を選べる
- ブラウザーがHTML/CSS機能を処理すると、パフォーマンス、ネイティブ動作、ユーザー環境設定への対応、アクセシビリティの面で有利になることがある
- ただし、アクセシビリティが常に自動で保証されるわけではない
以前はJavaScriptが必要だった機能
- ブラウザーメーカーと仕様策定者は、数年前までJavaScriptが必要だった機能をCSSとHTMLへ移してきた
- Webは後方互換性を維持するため、いったん覚えた実装方法がツールボックスに残り、繰り返し使われやすい
- ある機能にJavaScriptが必要だと思っていても、今もそうなのかを時々確認すれば、より良いWebサイトを作れる
チェックボックスで作るカスタムスイッチ
- カスタムスイッチは、
div、onclickハンドラー、内部状態の代わりに、標準のチェックボックスとCSSで実装できる <label>の中に<input type="checkbox">を入れると、ブラウザーが両者を関連付ける- ラベルのどこをクリックしてもチェックボックスが切り替わる
- 別途
onclickハンドラーは不要
appearance: noneは、ブラウザー標準のフォームコントロール描画を止めて、独自にスタイリングできるようにするinput自体をスイッチの背景のように装飾できる::beforeを切り替わる内部の点として使える
:checked疑似クラスは、チェック状態に応じて背景色と::beforeの位置を変えられる- キーボード利用者のために、フォーカス表示が必要
outline: noneでフォーカスを隠す方法は望ましくない:focus-visibleを使えば、キーボード操作時にだけ見やすいフォーカスリングを表示できるoutline-offsetでフォーカスのアウトラインを要素の外側または内側に調整できる
input:focus { outline-color: transparent; }は、通常時はアウトラインを透明にしつつ、高コントラストモードではユーザーが選んだ色で再表示させられる- 強制色モードについては forced colors explained を参照
datalistで作るネイティブ自動補完
datalistは、ユーザーの入力中に候補一覧を表示するブラウザー内蔵の自動提案機能- 構成はシンプル
datalist要素にidと複数のoptionを入れるinputのlist属性でそのdatalistに関連付ける
- ユーザーが入力すると、ブラウザーがドロップダウンを表示し、入力内容に合わせて候補を自動で絞り込む
- 標準の入力フィールドなので、一覧にない値を直接入力することもできる
- 入力フィールドを選択したあと矢印キーで一覧をたどるか、ブラウザーが追加したドロップダウンアイコンをクリックして全候補を表示できる
input type="color" の標準カラーピッカー
<input type="color">の1行だけで、ブラウザーネイティブのカラーピッカーを使える- JavaScript製のキャンバスUIやスライダーを多く置き換えられる
- Chromiumブラウザーのネイティブカラーピッカーでは、サイト内だけでなく画面上のどこからでも色を選べる
- すべてのユーザーがブラウザーのカラーピッカーを使えるわけではないため、通常のテキスト入力のように色を選ぶ別の手段もあわせて提供するのが望ましい
details と summary で作るアコーディオン
details要素とsummary要素は、コンテンツを折りたたんだり展開したりするアコーディオンをブラウザー標準機能として提供する- 標準動作はシンプル
details内の内容はsummaryを除いて隠される- ユーザーが
summaryをクリックすると残りの内容が表示される
open属性は初期の開いた状態を指定する- ユーザー操作後も固定される値ではなく、ユーザーが開閉すると状態は変化する
summary::markerで標準の三角マーカーをスタイリングできる- コンテンツを絵文字などに変えられる
- 背景色、背景画像、フォントサイズなどを調整できる
- 多くのCSSプロパティは動作せず、まったく別の位置に配置するようなスタイリングには制限がある
- Safariでは
::-webkit-details-marker疑似要素が必要 - マーカーの内容変更は、支援技術がアコーディオンを伝える方法に影響する可能性があるため、details/summary inconsistencies を参照できる
summaryはクリック可能だが、標準ではリンクのようなポインターカーソルも出ず、ボタンのようにも見えないため、hoverやfocus状態を追加してクリック可能であることを示す必要がある
dialogで作るモーダル
alert()、prompt()、confirm()はユーザーへの通知や確認に使えるが、メインスレッドをブロックし、デザインに合わせてスタイリングしにくい- 自前でダイアログを作るとアクセシビリティ対応が複雑になる
- フォーカスをダイアログ内に保持する必要がある
- モーダルであることを伝える必要がある
- ユーザーが誤って抜け出さないようにする必要がある
- 非常に高い
z-indexを持つウィジェットと衝突する可能性がある
- ブラウザーの
dialog要素はネイティブダイアログを提供する - 現時点ではダイアログを開くのにJavaScriptが必要
- JavaScriptなしで開けるようにする変更も進行中だが、まだ完全には仕様化・実装されていない
showModal()関数でダイアログを開ける
dialogはtop layerで開かれる- top layerはHTMLとは分離した新しいレイヤー
- このレイヤー上の要素は、
z-indexやスタッキングコンテキストの入れ子に関係なく、常に最前面に表示される - 概念の説明はMDNの Top layer を参照
dialogは標準の閉じるUIを提供しないため、自分でUIを入れる必要があるform method="dialog"が送信されると、ブラウザーがダイアログを閉じる- 2つの送信ボタンに異なる
valueを入れれば、確認ダイアログのように使える closeイベントでdialog.returnValueを読み、ユーザーが押したボタンの値を確認できる- 追加のフォームデータは FormData で読める
dialog::backdropは、ダイアログとそれ以外のページの間にあるレイヤー- 背景を暗くしたりぼかしたりして、ユーザーの注意をダイアログへ向けられる
- ブラウザーが配置するため、スクロール、固定要素、ブラウザーサイズ変更を自前で処理する必要がない
より少ないJavaScriptで実現できる機能
- JavaScriptを減らせる機能はほかにも多い
scroll-behavior: smoothを使ったネイティブのスムーズスクロールprefers-reduced-motion: no preferenceに一致する場合のみ使う条件付き
scroll-snapを使ったネイティブカルーセルposition: stickyを使った「in-view」要素- コンテナクエリ
- 今後追加される機能もある
- スクロール連動アニメーション
masonry.jsなしでgrid-template-rows: masonryにより作るMasonryレイアウト- 新しい
selectlist要素による完全にスタイリング可能なselect - JavaScriptによる選択コードの一部を減らせる
:has()セレクター
- 発表動画 Stop Using JavaScript for That: Moving Features from JS to CSS and HTML. で関連内容をさらに見られる
- 既存の検証済み実装を新しい方法に置き換える際は、とくにアクセシビリティをテストし、誰も排除しないようにする必要がある
1件のコメント
Hacker Newsのコメント
この記事で抜けている点は、このような場面で JavaScript を使う理由が、互換性のほうが優れているからだということ 新しい JavaScript はトランスパイルできますが、欠けている CSS や HTML の機能をポリフィルするのははるかに難しく、場合によっては不可能です。しかもそのポリフィルも結局は JavaScript を使います
appearanceについては、MDN でもappearance: noneですら徹底的にテストするよう注意喚起が多くあります。最新ブラウザだけをサポートするならそれほど重要ではないかもしれませんが、古い Safari のバージョンは思った以上に長く残っていますdatalistは Firefox Android ではまったく機能せず、私には候補すらない入力ボックスにしか見えません カラーピッカーは素晴らしいですが、極めて非標準的なので、ほとんどのビジネスでは致命的です。デザイナーが不満を言うだけでなく、カスタマーサポートがユーザーを支援しにくくなります。Chromium はページ上から拾ったり任意の色を選んだりする機能まで提供しますが、Firefox Android は虹色、グレー、白黒程度しかありません 記事自体もdetailsとdialogの不一致を認めています。いつか、こうした機能をサポートしない、あるいは一貫してサポートしないブラウザがもう使われなくなることを願いますが、当面はこうした要素は、対応ブラウザを完全に制御できるサイドプロジェクトでしか使わないと思いますdialog要素は今では サポート範囲 がかなり広く、2021年台の Firefox や Safari を使っている数パーセントのユーザー向けにポリフィルを用意するのも十分現実的です モーダルを作るなら強くおすすめしますし、アクセシビリティ改善も素晴らしいですdatalistのようなものの代わりに JS 実装 を使うことにしました。特にdatalistは試してみたものの、結果があまりに一貫しないため断念せざるを得ませんでした 結局、ブラウザ間の不一致のせいで Chrome 以外のサポートを打ち切ることさえありましたDatalistを知らなかったのですが、少なくとも Chrome Android ではまともに動いているようには見えません 選択肢は自動補完候補が表示されるキーボード領域に出ているようです: https://imgur.com/a/Ecb4503 モバイル Web UI のフォームコントロールでそういう方式は初めて見ましたし、パスワード自動入力アプリが同じ場所を使う場合を除けば見たことがありません 悪くはありません。雑に作られたカスタム JS のドロップダウンをぎこちなくスクロールするよりはずっとましですが、一般ユーザーがこれの使い方を理解できるという確信がありません。なのでモバイルでは実質的に望みがないと思います Firefox Android ではそもそもサポートされていません: https://caniuse.com/?search=datalistdatalistドロップダウンに スタイル指定 できるようにしてくれないものですか? 参考: https://adrianroselli.com/2023/06/under-engineered-comboboxe...input要素にautocomplete="off"を追加すると動作が変わるのか気になります いずれにせよ、datalistを正常に使うにはそれが必要です。そうしないと、値の選択履歴がドロップダウンの一覧に追加されます。Chromium で確認しました また、デフォルト値が設定されている場合のように、状況によってはdatalistにもなお JS が必要です。回避策やブラウザごとの癖のメモを、新しい LibreOffice Web サイトのコードにまとめてあります: https://git.libreoffice.org/infra/libreofficeorg/+/835a5cc59... 良い知らせとしては、Firefox の開発者がdatalistの動作改善を検討する予定で、一度クリックするだけで一覧を表示できるようになるかもしれませんdatalistの選択肢がキーボード内に表示されるのは、ここ数か月で起きた変化です 以前は「普通」でしたが、誰かが変えるためだけに変えたかったように思えますscroll-behavior: smoothによるネイティブのスムーズスクロールは、本当に限定的にだけ使うべき思っている以上に、ほとんどの用途では良い考えではなく、望ましくない副作用もよくある
scroll-snapでネイティブのカルーセルを作れるとはいえ、カルーセル自体が依然として悪いアイデアなので、scroll-snapの正当な活用範囲はきわめて限られるスクロールベースのアニメーションを使うページは、たいていそれを取り除いたほうが良くなる
スムーズスクロールが良い例。ネイティブ API なら、ユーザーはいつでも中断できる。多くの JS 実装はひどくカクつき、ユーザーを苦しめる
デザインの選択をいくらでも批判することはできるが、「カルーセルは依然として悪い」と実際の理由を示さなければ、耳を傾けてもらえるとは期待しにくい
でも Amazon のホームページではカルーセルが目立って使われていて、Amazon はホームページの変更を容赦なく A/B テストしていることで知られている。だとすれば、カルーセルがテストで良い結果を出した可能性はあり、何か普遍的・客観的な意味で本当に「悪い」と言い切るのは微妙
たいてい、目次スタイルのアンカーを実装した直後には少なくとも追加するほう
2023年になってもまだフォームと、ユーザーがデータを入力する一般的な UX をめぐって争っているのは驚き
datalistやカラーピッカー関連のコメントを見るだけでもそうで、なぜまだ解決済みの領域になっていないのか理解できない昔、XForms でこれを一気に解決しようという試みがあったが、ブラウザーには実装されなかった
その代わり、ほぼすべての CSS/JS コンポーネントフレームワークが、それぞれ異なるセマンティクスを持つ限定的なフォーム要素のセットを独自に提供している
私たちは一生、基本 UI コントロールを自前で実装し続けることになりそう
「解決されていない」と見えるのは、一部の人たちが JavaScript を避けようとする妙な執着のせいで、中途半端な代替案を無理やり押し込もうとしているからにすぎない
退屈で基本的な技術にとどまるなら、すでに解決済み。でも React でまた解決し、React hooks でさらに解決し、際限なく再解決し続けようとこだわるなら、解決されないことになる
意図はプログラムで判定できるものではないので、状況によっては便利な機能を持てない
最後に扱った複雑なフォームでは、ブラウザーが許可するよう、クリックイベントがかなり直接的にフォーム送信を発生させるようにしなければならなかった
Web ページ経由で色を送信する方法を求めたことはない
JavaScript の代わりに
detailsを使えば、Ctrl+F でその中を検索して開けるJavaScript のアコーディオンではそうはできない
hidden="until-found"を使えば、JS ベースのアコーディオンや他の隠しコンテンツでも可能になるが、残念ながら現時点では Chromium ベースのブラウザーでしか使えない: https://developer.chrome.com/articles/hidden-until-found/大半には同意するが、
dialogは十分使い込んでいないので意見がなく、datalistは社内ツールでもない限り有効な選択肢ではないと思う見た目が悪く、できることが限られ、スタイル指定もできない。「組み込み機能を使えばいい」という主張の大半の問題はここにある。
date pickerも同じデフォルトがいまいちなだけでなく、変えたくても変えられない。スタイルや動作を変えようとすると無数の壁のどれかにぶつかり、たとえば週の始まりを月曜日にしたくてもできない。そうなると選択肢はたいてい、JS を使う完全置き換えライブラリーしかなくなる
もっと軽い選択肢を使うことには賛成だし、HTML > CSS > JS という階層にも同意するが、見栄えの良い UI と欲しい機能を両立するには、時にJS が唯一の答えになる
datalistが役立つかもしれないと思った入力内容で厳密に始まらない選択肢も表示したくなった瞬間まではうまく動く。たとえば入力にタイプミスがあると、候補が表示されない
すべての項目を強制表示する方法がないので、結局は順序付きリストを選んだ
Web 開発を始めたころは、変化には最大 10 年かかっていた。IE6 も皆の足を引っ張っていたし、当時の w3c もかなり力がなかった。今は変化が速い
来年には 3 大ブラウザーで
datalistのスタイル指定がプレフィックスなしで可能になっているかもしれないが、カスタム JS の解決策に縛られていると、ビジネスは再構築コストを払ってくれないだろうネイティブ機能を JS で拡張しておけば、十分なサポートが整った時点で低コストで JS を外せる。ネイティブコントロールで許容できる場面では今それを使い、JS はポリフィルのように適用すればいい
input[type=date]についてよく提案されるカスタマイズの多くは、開発者が制御できないほうがむしろ良い表示すべき適切なカレンダーはロケール依存であるべき。ユーザーのプラットフォームは、ユーザーが最も効果的に使えそうな形で設定し表示する機能をすでに持っている
プラットフォームの日付ピッカーのほうが、自作の妙なものより優れている
あのトグルボタンは本当に良い
この記事にフロントエンドのミーム開発者たちが怒っているように見えるが、要点は正しい。なぜこんなに多くの愚かなサイトをJSで作るのか? 人々がHTMLのような単一の標準に従いさえすれば、すべてを一貫させられるし、アクセシビリティや翻訳のようなことも簡単に合わせられる
最近のサイトを見ると、すべてを単一ページ上で動的に読み込もうとするせいで、戻るボタンすら動かない
そして、新機能が導入された後、それが十分広くサポートされて有用になるまで何年もかかるという、「人々が更新するのを待つ」問題も依然としてある
実装がひどいものや複雑なJavaScriptの仕掛けが多いことにはおおむね同意する。動的コンテンツでも戻る機能を維持する標準化された解決策はかなりあり、人気のWebフレームワークはデフォルトで対応しているはずだ
上位コメントを読んでみたが、怒りと呼べるようなものはあまり見当たらず、ブラウザ対応についてもっともな指摘をしている人たちが見えるだけだ
正しい方向への一歩ではあるが、CSSもまた、Philip Greenspunの言う“artistes”が読みにくいページを作るために乱用する別の道具だ
Gemini支持者ではないが、基本的にレイアウトとタイポグラフィのあらゆる側面はブラウザ側に戻し、ユーザーが制御できるべきだ。デザイナーたちは、それを信頼して任せられないことを何度も示してきた
趣旨は気に入っているし、スイッチも格好よく、
summary/detailsも時々役に立つただし、
datalist要素は、おもちゃやプロトタイプを超える用途ではほとんど現実的な選択肢ではない私が気に入っている「JSなしでCSSだけで十分」なものは、サイドバードロワーとカルーセルだ
DaisyUIというTailwindCSSコンポーネントライブラリにも、そのまま使えるコンポーネントがある
https://daisyui.com/components/drawer/
https://daisyui.com/components/carousel/
ドロワーとページ上に現れる他のコンテンツは告知されるべきで、制御対象の横には
aria-expandedの状態があるべきだ依然として本物の質問だ。方法があるのかもしれないし、開発者たちがcollectively重要ではないと考えているのかもしれない。監査担当者は同意しないだろうが
こうしたフレームワークの作者たちは、ブラウザ全体で実際に動くようにするためにどれほど多くのテストが必要かをひどく過小評価しているように見える
コンポーネントがそれだけ多く、しかもテーマ化まで可能になると、既存のテーマやアプリケーションを壊さずに修正できるかどうかも断言しにくい
components/carousel/の“Snap to [start|center|end]”は初めて見たそもそもsnapとは何で、どう動くのか? 私の画面では指のクリックに反応しない
知られていないインタラクション方式は、UI要素ライブラリを勧める良い根拠にはならないと思う