3 ポイント 投稿者 GN⁺ 2023-12-03 | 1件のコメント | WhatsAppで共有
  • Web機能を実装する際は、HTML、CSS、JavaScriptの順に、より強力でない技術を先に検討するほうが、読み込み失敗やアクセシビリティの問題を減らすうえで有利
  • JavaScriptはブラウザーの動作を直接制御できる一方で、追加リソースやエラーの可能性があるため、キーボード利用者・支援技術利用者を排除しやすい
  • 以前はJavaScriptが必要だったチェックボックススイッチ、datalistinput type="color"details/summarydialogのような機能が、今では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サイトを作れる

チェックボックスで作るカスタムスイッチ

  • カスタムスイッチは、divonclickハンドラー、内部状態の代わりに、標準のチェックボックスと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を入れる
    • inputlist属性でそのdatalistに関連付ける
  • ユーザーが入力すると、ブラウザーがドロップダウンを表示し、入力内容に合わせて候補を自動で絞り込む
  • 標準の入力フィールドなので、一覧にない値を直接入力することもできる
  • 入力フィールドを選択したあと矢印キーで一覧をたどるか、ブラウザーが追加したドロップダウンアイコンをクリックして全候補を表示できる

input type="color" の標準カラーピッカー

  • <input type="color"> の1行だけで、ブラウザーネイティブのカラーピッカーを使える
  • JavaScript製のキャンバスUIやスライダーを多く置き換えられる
  • Chromiumブラウザーのネイティブカラーピッカーでは、サイト内だけでなく画面上のどこからでも色を選べる
  • すべてのユーザーがブラウザーのカラーピッカーを使えるわけではないため、通常のテキスト入力のように色を選ぶ別の手段もあわせて提供するのが望ましい

detailssummary で作るアコーディオン

  • 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()関数でダイアログを開ける
  • dialogtop 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件のコメント

 
GN⁺ 2023-12-03
Hacker Newsのコメント
  • この記事で抜けている点は、このような場面で JavaScript を使う理由が、互換性のほうが優れているからだということ 新しい JavaScript はトランスパイルできますが、欠けている CSS や HTML の機能をポリフィルするのははるかに難しく、場合によっては不可能です。しかもそのポリフィルも結局は JavaScript を使います appearance については、MDN でも appearance: none ですら徹底的にテストするよう注意喚起が多くあります。最新ブラウザだけをサポートするならそれほど重要ではないかもしれませんが、古い Safari のバージョンは思った以上に長く残っています datalist は Firefox Android ではまったく機能せず、私には候補すらない入力ボックスにしか見えません カラーピッカーは素晴らしいですが、極めて非標準的なので、ほとんどのビジネスでは致命的です。デザイナーが不満を言うだけでなく、カスタマーサポートがユーザーを支援しにくくなります。Chromium はページ上から拾ったり任意の色を選んだりする機能まで提供しますが、Firefox Android は虹色、グレー、白黒程度しかありません 記事自体も detailsdialog の不一致を認めています。いつか、こうした機能をサポートしない、あるいは一貫してサポートしないブラウザがもう使われなくなることを願いますが、当面はこうした要素は、対応ブラウザを完全に制御できるサイドプロジェクトでしか使わないと思います

    • カラーピッカー が非標準的だという話には同意しにくいです iPhone でボタンを押すと、本物のシステムネイティブのカラーピッカーが表示されます。OS が提供していて複数のアプリで見かける、まさにあのコントロールであり、作り込みのカスタム実装よりずっと好ましいです
    • 互換性のほうが優れているというのは、すべてのユーザーが JavaScript を使うことを前提にした場合にしか成り立ちません 私は JavaScript のない Web をずっと好みますし、ノートPCのバッテリー駆動時間にも数時間単位で影響します。あるサイトはこれと互換性がなく、空白ページしか描画されなかったり、テキストを表示するにも JavaScript が必要だと文句を言ったりします 一方で Amazon は JavaScript なしの EC サイトの複製版も持っていて、あれほど大規模なことでも JavaScript なしで可能だと示しています
    • dialog 要素は今では サポート範囲 がかなり広く、2021年台の Firefox や Safari を使っている数パーセントのユーザー向けにポリフィルを用意するのも十分現実的です モーダルを作るなら強くおすすめしますし、アクセシビリティ改善も素晴らしいです
    • カスタマーサポートがユーザーを支援しにくくなる、というのは大きいです 以前の職場でこの問題を真剣に議論し、datalist のようなものの代わりに JS 実装 を使うことにしました。特に datalist は試してみたものの、結果があまりに一貫しないため断念せざるを得ませんでした 結局、ブラウザ間の不一致のせいで Chrome 以外のサポートを打ち切ることさえありました
    • いいえ。JavaScript は失敗すると完全に失敗し、コンテンツ自体が消えます HTML の例は古いブラウザでは見た目が崩れることはあっても、実際のコンテンツは残ります。JS は単に何もありません。アクセシビリティを完全に壊します HTML ならスクリーンリーダーが少なくとも読めますが、JS で生成されたコンテンツはそれを妨げます。JS が JS を実行できないとき、どんなポリフィルや別の JS でも JS を救えません。最初から「動作」していなければアクセシビリティ上問題がなくならず、その場合は元の論点自体が無意味になります
  • Datalist を知らなかったのですが、少なくとも Chrome Android ではまともに動いているようには見えません 選択肢は自動補完候補が表示されるキーボード領域に出ているようです: https://imgur.com/a/Ecb4503 モバイル Web UI のフォームコントロールでそういう方式は初めて見ましたし、パスワード自動入力アプリが同じ場所を使う場合を除けば見たことがありません 悪くはありません。雑に作られたカスタム JS のドロップダウンをぎこちなくスクロールするよりはずっとましですが、一般ユーザーがこれの使い方を理解できるという確信がありません。なのでモバイルでは実質的に望みがないと思います Firefox Android ではそもそもサポートされていません: https://caniuse.com/?search=datalist

    • ブラウザベンダーは datalist ドロップダウンに スタイル指定 できるようにしてくれないものですか? 参考: https://adrianroselli.com/2023/06/under-engineered-comboboxe...
    • こうした解決策が広く定着するのに時間がかかる理由はこれです JavaScript はかなりよく標準化されていますが、HTML と CSS は相対的にそうではありません
    • 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 テストしていることで知られている。だとすれば、カルーセルがテストで良い結果を出した可能性はあり、何か普遍的・客観的な意味で本当に「悪い」と言い切るのは微妙
    • ネイティブのスムーズスクロールが、なぜ大半の場合で良いアイデアではないのか?
      たいてい、目次スタイルのアンカーを実装した直後には少なくとも追加するほう
    • とにかく、そういうものに JavaScript は不要ではある
  • 2023年になってもまだフォームと、ユーザーがデータを入力する一般的な UX をめぐって争っているのは驚き
    datalist やカラーピッカー関連のコメントを見るだけでもそうで、なぜまだ解決済みの領域になっていないのか理解できない
    昔、XForms でこれを一気に解決しようという試みがあったが、ブラウザーには実装されなかった
    その代わり、ほぼすべての CSS/JS コンポーネントフレームワークが、それぞれ異なるセマンティクスを持つ限定的なフォーム要素のセットを独自に提供している

    • XML 技術を拒んだ結果、Web は XML が提供していたものの出来の悪い版を延々と再実装し続ける運命を背負った
      私たちは一生、基本 UI コントロールを自前で実装し続けることになりそう
    • もう解決済み。React に入れて人生を続ければいい
      「解決されていない」と見えるのは、一部の人たちが JavaScript を避けようとする妙な執着のせいで、中途半端な代替案を無理やり押し込もうとしているからにすぎない
    • フォームが「解決された」とは、どういう意味だろう?
      退屈で基本的な技術にとどまるなら、すでに解決済み。でも React でまた解決し、React hooks でさらに解決し、際限なく再解決し続けようとこだわるなら、解決されないことになる
    • CSRF のせいで、人間にはできても私たちにはできないことがいくつかある
      意図はプログラムで判定できるものではないので、状況によっては便利な機能を持てない
      最後に扱った複雑なフォームでは、ブラウザーが許可するよう、クリックイベントがかなり直接的にフォーム送信を発生させるようにしなければならなかった
    • 誰かがどこかで、フォームで違うものを送信したがるからこそ、フォームは解決されない
      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 が役立つかもしれないと思った
      入力内容で厳密に始まらない選択肢も表示したくなった瞬間まではうまく動く。たとえば入力にタイプミスがあると、候補が表示されない
      すべての項目を強制表示する方法がないので、結局は順序付きリストを選んだ
    • 組み込みのセマンティックマークアップを JS で拡張するやり方は、将来を見据えたアプローチだということを常に覚えておく価値がある
      Web 開発を始めたころは、変化には最大 10 年かかっていた。IE6 も皆の足を引っ張っていたし、当時の w3c もかなり力がなかった。今は変化が速い
      来年には 3 大ブラウザーで datalist のスタイル指定がプレフィックスなしで可能になっているかもしれないが、カスタム JS の解決策に縛られていると、ビジネスは再構築コストを払ってくれないだろう
      ネイティブ機能を JS で拡張しておけば、十分なサポートが整った時点で低コストで JS を外せる。ネイティブコントロールで許容できる場面では今それを使い、JS はポリフィルのように適用すればいい
    • 週の開始日や input[type=date] についてよく提案されるカスタマイズの多くは、開発者が制御できないほうがむしろ良い
      表示すべき適切なカレンダーはロケール依存であるべき。ユーザーのプラットフォームは、ユーザーが最も効果的に使えそうな形で設定し表示する機能をすでに持っている
      プラットフォームの日付ピッカーのほうが、自作の妙なものより優れている
  • あのトグルボタンは本当に良い
    この記事にフロントエンドのミーム開発者たちが怒っているように見えるが、要点は正しい。なぜこんなに多くの愚かなサイトをJSで作るのか? 人々がHTMLのような単一の標準に従いさえすれば、すべてを一貫させられるし、アクセシビリティや翻訳のようなことも簡単に合わせられる
    最近のサイトを見ると、すべてを単一ページ上で動的に読み込もうとするせいで、戻るボタンすら動かない

    • 人々が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重要ではないと考えているのかもしれない。監査担当者は同意しないだろうが
    • こういうフレームワークを見ると最初はいつも期待するが、試してきた他のすべてのフレームワークと同じく、DaisyUIにもiOS Safariや他のブラウザでいくつもの問題がある
      こうしたフレームワークの作者たちは、ブラウザ全体で実際に動くようにするためにどれほど多くのテストが必要かをひどく過小評価しているように見える
      コンポーネントがそれだけ多く、しかもテーマ化まで可能になると、既存のテーマやアプリケーションを壊さずに修正できるかどうかも断言しにくい
    • components/carousel/の“Snap to [start|center|end]”は初めて見た
      そもそもsnapとは何で、どう動くのか? 私の画面では指のクリックに反応しない
      知られていないインタラクション方式は、UI要素ライブラリを勧める良い根拠にはならないと思う