innerHTMLに代わるHTMLの差し込み方がそろってきた

つくば市のホームページ制作会社

JavaScriptで画面の一部を書き換えるとき、多くの現場ではいまも innerHTML に文字列を代入する書き方が使われています。手軽で、どのブラウザでも動き、昔のサンプルコードもほとんどがこの形です。ところがこの秋、この「HTMLの文字列を差し込む」という基本動作のまわりで、ブラウザ側の整備が一段進みました。

9月16日にベータ版となったChrome 155では、HTMLを差し込む新しいメソッド群と、差し込みながら少しずつ流し込むストリーミング用のメソッドが入っています。Firefoxは今年2月の148で、差し込むときに危険な部分を取り除く setHTML() を先に出荷しました。安全性と速さという別々の課題に、同じ入り口から手が入りつつある、というのが今回の見立てです。

innerHTMLが抱えてきた二つの弱点

innerHTML の弱点は、大きく分けて二つあります。一つ目は安全性です。ユーザーが入力した文字列や外部から取ってきたデータをそのまま代入すると、紛れ込んだイベント属性などから任意のスクリプトが動く、いわゆるクロスサイトスクリプティング(XSS)の入り口になります。Mozillaの解説では、XSSは10年近くにわたってウェブの脆弱性の上位三つに入り続けているとされています。

二つ目は、同じような目的のメソッドが乱立していることです。Chromeのドキュメントでは、innerHTML、outerHTML、insertAdjacentHTML、createContextualFragment、setHTMLUnsafe などを並べたうえで、上書きなのか追記なのか、危険なタグを取り除くのか、スクリプトは実行されるのか、といった違いを即答できる開発者は少ないだろうと率直に書いています。確かに、制作の現場でもこの違いを意識して使い分けている例はあまり見かけません。

さらにもう一点、これらはすべて「差し込むHTMLが最初から全部そろっている」ことが前提です。サーバーから届く途中のHTMLを順に表示していく、というHTML本来の強みを、JavaScriptからの差し込みでは活かせませんでした。

危険な部分を取り除いてから入れるsetHTML

安全性の側の答えが、HTML Sanitizer APIと、その中心にある setHTML() です。使い方は innerHTML への代入をメソッド呼び出しに置き換えるだけで、差し込む前にブラウザが危険な要素と属性を取り除きます。MDNによると、既定の設定では script、iframe、embed、object などの要素や、onclick のようなイベント属性がすべて落とされ、さらにクリックジャッキングやなりすましに使われうる要素、コメント、data- 属性まで取り除かれます。

許可する要素を自分で指定することもできます。たとえば段落と太字だけを通す、といった「許可リスト型」の設定を作れば、想定外のタグは一切入りません。MDNは、危険なものを列挙して外す方式より、必要なものだけを列挙して通す方式のほうが安全だと説明しています。将来新しい危険な要素が見つかっても、許可リストに入っていなければ最初から通らないためです。

これまでこの役割は、DOMPurifyのような外部ライブラリが担ってきました。MDNは、ブラウザに組み込まれた方式のほうが、解析の文脈や実行されうるコードをより正確に把握できるため、安全な方のメソッドを使うなら外部ライブラリは不要になるという立場です。ただし、この機能はまだ主要ブラウザすべてでは使えない段階にあり、特にSafariが未対応である点は押さえておく必要があります。

名前をそろえた差し込み用メソッド群

Chrome 155で入るのは、差し込む位置ごとに名前をそろえたメソッド群です。要素の中身を置き換える setHTML() を軸に、要素ごと置き換える replaceWithHTML()、前後に足す beforeHTML() と afterHTML()、子要素の先頭と末尾に足す prependHTML() と appendHTML() が用意されています。ベータ版の告知では、これらが insertAdjacentHTML() の実質的な置き換えになると位置づけられています。

それぞれには、危険な部分の除去をしない「Unsafe」付きの版もあります。名前だけ見ると使ってはいけないもののようですが、Chromeのドキュメントは、これは入力の信頼度に応じてリスクを意識してほしいという注意書きであり、使うなという意味ではないと説明しています。Unsafe版では、オプションを指定すれば差し込んだHTML内のスクリプトを実行させることもでき、初期値は実行しない設定です。

地味な変更に見えますが、名前の規則が一つにまとまることの効果は小さくありません。コードを読んだ人が「このメソッドは安全側か」「どこに入るか」を名前だけで判断できるようになれば、レビューや引き継ぎのときの見落としが減ります。複数の人が触るサイトほど、こうした読みやすさは効いてきます。

届いた分から順に流し込むストリーミング

もう一つの柱が、ストリーミング用のメソッドです。上の各メソッドには streamHTML() や streamAppendHTML() のような対応版があり、Streams APIの書き込み口を返します。fetch() で取ってきた応答をそのままつなげば、サーバーから届いた分から順に画面へ反映できます。Chrome 151からは、応答を文字列の流れとして取り出す textStream() という便利なメソッドも加わり、中間の変換処理を書かずに済むようになりました。

これまで、ページの一部をJavaScriptで差し替える作りでは、応答をすべて受け取ってから一気に入れるのが普通でした。Chromeのドキュメントは、単一ページアプリケーションが最初の読み込み以外ではHTMLの逐次表示の恩恵を受けられないことを大きな弱点として挙げ、この新しいメソッドでそこを埋められるとしています。共通のフッターのような部品を別ファイルから取り込み、キャッシュを効かせる使い方も例に挙がっています。ただし、JavaScriptが動かないと表示されない以上、最初の画面で見える部分に使うのは避けるべきだという注意も添えられています。

同じ取り組みの一部として、HTMLの中で後から中身を差し替える仕組みも進んでいます。場所の目印を置いておき、ページの後半で template 要素に for 属性を付けて中身を送ると、目印の位置にはめ込まれる、という方式です。重い処理を待つ部分だけを後回しにして、先に骨組みを表示できます。こちらはChrome 150から使えるとされています。

ブラウザごとの足並みと当面の付き合い方

ここまでの話を整理すると、各ブラウザの足並みはまだそろっていません。setHTML() による安全な差し込みはFirefoxが先行し、Chromeは差し込み位置ごとのメソッドとストリーミングを前に進めています。一方でSafariはSanitizer APIに対応しておらず、MDNでも主要ブラウザで広く使える段階にはないと表示されています。

Chromeのチームは、新しいメソッドの形をそのまま使えるようにする補助ライブラリをnpmで公開しています。ただしドキュメント自身が、この補助ライブラリは実際には流し込まず、全部受け取ってからまとめて差し込むと明記しています。安全な差し込みの部分も、ブラウザ側のSanitizer APIがなければ成り立ちません。つまり補助ライブラリは、書き方を先取りするためのもので、機能そのものを全ブラウザで再現するものではない、と理解しておくのがよさそうです。

もう一つの論点は、Trusted Typesとの関係です。これは危険になりうる差し込み口に、決められた変換処理を必ず通させる仕組みです。Mozillaは、setHTML() を採用したあとなら、setHTML() だけを許して他の危険な差し込み方を禁じる厳しい設定にしやすくなり、今後の書き間違いによるXSSの再発を防げると説明しています。Content Security Policyが大がかりな改修を必要としたため広く普及しきらなかった、という反省も同じ記事で触れられており、今回の仕組みは「コードの置き換えを小さく済ませる」ことに重きが置かれています。

中小企業のサイト運用で見ておきたいところ

では、日々のサイト制作や保守で何をすればよいか。すぐに全面的な書き換えが必要な話ではありません。ただ、お知らせの一覧をJavaScriptで読み込んで表示する部分や、問い合わせフォームの入力内容を確認画面に出す部分など、外から来た文字列を innerHTML で差し込んでいる箇所は、どのサイトにも意外と残っています。まずはそうした箇所を把握しておき、Safariを含む主要ブラウザで使えるようになった段階で、setHTML() への置き換えを検討する、という順番が現実的です。

WordPressのサイトでも、テーマやプラグインのJavaScriptに同じような書き方が含まれていることがあります。自社で書いた追加のスクリプトであれば、置き換えの候補として一覧にしておくだけでも、将来の改修の見積もりがしやすくなります。外部のプラグインについては、作者側の対応を待つことになりますが、どの部分が外から来たHTMLを扱っているかを知っておくことには意味があります。

ストリーミングのほうは、表示速度を気にする規模の大きなサイトや、画面の一部を頻繁に差し替える管理画面のような作りで先に効いてくるはずです。普通のコーポレートサイトでは急いで取り入れる理由は少ないものの、HTMLを後から流し込めるようになると、ページの組み立て方の選択肢が確実に増えます。長く制作を続けてきた立場から見ても、innerHTML ひとつで何でも済ませていた時代から、目的に応じて安全な道具を選べる時代へと、基本の部分が静かに入れ替わり始めているように感じます。

モーダルを閉じたときに出る警告は消すより順番を直す

つくば市のホームページ制作会社

モーダルウィンドウを閉じた瞬間、Chromeの開発者ツールのコンソールに黄色い警告が出る。Bootstrapでも、Angularでも、Ionicでも、同じ文面が出てくるおなじみのものです。検索すると一行で黙らせる方法がすぐ見つかるので、深く考えずに入れてしまった経験がある方も多いのではないでしょうか。

CSS-Tricksに、この警告は正しく、よく出回っている直し方のほとんどは使う人を困らせる方向に働いている、と正面から論じた記事が掲載されました。表示の崩れとして目に見えない不具合だけに、制作の現場では見落としやすい話です。

警告が伝えているのはフォーカスの置き去り

問題の中心は、aria-hidden という属性の性質にあります。この属性は要素をスクリーンリーダーなどの支援技術から見えなくしますが、キーボードでのフォーカス移動からは外しません。つまり、読み上げの対象からは消えているのに、Tabキーでは到達できる、という食い違いが起こり得ます。

モーダルを閉じる処理でよくあるのが、先に外側の枠へ aria-hidden を付けてフェードアウトを始め、アニメーションが終わってから元のボタンにフォーカスを戻す、という順番です。この間、閉じるボタンにはまだフォーカスが残っています。記事によると、Chromeはこの状態を見つけると指定された非表示を実際には適用せず、読み上げ側に中身を見せたままにしたうえで警告を出しているとのことです。コンソールの表示はお知らせではなく、書いたマークアップをブラウザが上書きしたという報告だと捉えたほうが実態に近いようです。

よく見かける直し方が使う人を置き去りにする

検索上位によく出てくるのが、閉じる処理の中で document.activeElement.blur() を呼ぶ一行です。確かに警告は消えます。ただ、フォーカスはどこにも移らず、ブラウザはページ全体の body に落とします。マウスで操作している人には何も起きていないように見えますが、キーボードやスクリーンリーダーで操作している人は、読み上げが途切れたうえに、次のTabでページの先頭からやり直すことになります。記事では、フォーカスの順序に関するWCAGの達成基準2.4.3に反する状態だと指摘しています。

ほかにも、setTimeout などで処理を少し遅らせる方法、aria-hidden 自体を取り除く方法、Radixやshadcnでモーダル扱いそのものを外してしまう設定などが紹介されていますが、いずれも警告を静かにする代わりに別の不都合を生むとされています。遅らせる方法は処理の重い端末で失敗が不定期に出るようになり、属性を外す方法はモーダルを開いている最中に背後のページを操作できてしまいます。

筆者自身もこの一行を入れて出荷し、後日の利用者テストでスクリーンリーダー利用者がページの先頭から延々とTabを押して元の場所へ戻る様子を見て、ようやく意味に気付いたと書いています。自動のアクセシビリティ検査も静止した状態のマークアップを見るため、この種の順番の不具合は通ってしまう、という指摘は制作側として耳が痛いところです。

閉じるときの手順を並べ替える

記事が示す正しい直し方は、新しい部品を足すことではなく、閉じる処理の順番を入れ替えることです。要点は、隠す領域からフォーカスを先に出してから隠す、の一点に集約されます。手順としては次の流れになります。

  • 開いている間に背後のページへ付けていた inert を先に外す
  • モーダルを開いたボタンへ、その場でフォーカスを戻す
  • 閉じかけているモーダル自体には aria-hidden ではなく inert を付け、クリックも受け付けないようにしてからフェードアウトさせる
  • アニメーションが終わった時点で要素を取り除く

inert は読み上げの対象からも、フォーカス移動からも、クリックからも要素を外す属性なので、フェード中の抜け殻を安全に扱えます。また、開いたボタンそのものは開く処理の時点で記録しておく必要があります。フォーカスをモーダルの中へ移したあとでは、どこから来たのかが分からなくなるためです。

加えて、動きを減らす設定の利用者のようにアニメーション自体が走らない場合、終了を知らせるイベントが来ないまま要素が残り続けるという落とし穴も挙げられています。削除した行のメニューから開いたモーダルのように、戻り先のボタンがもう無い場合に備えて、代わりの戻り先を用意しておくことも勧められています。

新しく作るなら標準のdialog要素が近道

記事の冒頭で真っ先に勧められているのが、HTML標準の dialog 要素を showModal() で開く方法です。この場合、フォーカスの受け渡しや背後の操作不能化はブラウザが引き受けてくれるため、今回のような不具合はほぼ起きなくなるとされています。Bootstrapも次の大きな版で自前の処理をやめ、この標準の仕組みに寄せたと紹介されています。

中小企業のサイトでも、お問い合わせの確認画面や画像の拡大表示など、モーダルは意外と多く使われています。既存のライブラリをすぐに入れ替えられない場合でも、閉じる処理でフォーカスがどこへ戻るかをキーボードだけで一度確かめてみる価値はありそうです。コンソールをきれいにすることが目的になっていないか、改めて見直すきっかけになる記事でした。

npmの公開に人の承認を挟む流れが強まっている

つくば市のホームページ制作会社

WordPressのブロックテーマやプラグインを作っていると、npmを使わない日はほとんどありません。ビルド用のツール一式も、CSSの処理も、小さな便利ライブラリも、たいていnpm経由で入ってきます。そのnpmで、9月に入ってから公開の手順まわりの変更が立て続けに発表されました。一つひとつは地味な更新ですが、並べてみると「パッケージを公開する最後の一押しは人間がやる」という方向がはっきり見えてきます。

今回は、GitHubの変更履歴(Changelog)に9月に載った三つの更新と、6月に予告されたnpm v12の既定値の変更、そしてその背景にある8月のワーム被害をつなげて、制作の現場から見た意味を考えてみます。

8月に起きたことを振り返る

話の出発点は、8月4日に起きたnpmパッケージの大規模な乗っ取りです。Datadog Security Labsの分析によると、キャッシュ用ライブラリとして広く使われているkeyvのGitHubリポジトリに不正なコミットが入り、そこから公開された版に悪意あるコードが仕込まれました。同じ手口はcacheable系のパッケージ群やectoにも広がり、flat-cacheやfile-entry-cacheといった、名前を見れば依存関係の奥で見覚えのあるパッケージも含まれていました。コミュニティではChainDropと呼ばれています。

仕組みとしては、パッケージのインストール時に自動で走るpreinstallスクリプトから読み込み役のファイルを起動し、そこから本体を動かすというものです。本体は開発者の端末やCIの環境から、GitHubやnpmのトークン、クラウドの認証情報、環境変数などを集めて外部へ送り出します。さらに、盗んだnpmトークンのうち二要素認証を迂回できる設定のものを見つけると、そのトークンで書き込める別のパッケージにも同じ仕掛けを入れて勝手に新しい版を公開する、という自己増殖の機能まで備えていました。

見落とせないのは、keyvの問題の版が、GitHub Actionsのワークフローから正規の手順で公開され、正しい来歴証明(provenance)まで付いていたという点です。Datadogは、来歴証明は「どこでどう作られたか」を示す証拠であって、安全かどうかの判定ではないと指摘しています。ワークフローそのものが乗っ取られていれば、証明は悪意あるコードの出どころを忠実に記録してしまうわけです。

ステージ公開という考え方

こうした流れを受けて、npmが力を入れているのがステージ公開(staged publishing)です。これは、新しい版をいきなりレジストリに出すのではなく、いったん「公開待ち」の状態に置き、メンテナーが二要素認証を通したうえで承認して初めて公開される、という手順です。

9月3日の更新では、この仕組みまわりに三つの変更が一般提供になりました。一つ目は、トークンを使わずにCIから公開する信頼済み公開(trusted publishing)の設定を、一つのパッケージに複数持てるようになったこと。安定版、プレリリース版、検証用といったワークフローを分けて運用できるようになり、これまでOIDCでまかなえない経路のために長期間有効なトークンを残しておく、といった回避策が要らなくなります。

二つ目は、公開待ちのパッケージはマルウェアの検査が終わるまで承認ボタンが押せなくなったこと。三つ目は、npmjs.comの版一覧で、それぞれの版が承認されたのか、却下されたのか、まだ待ち状態なのかという履歴がメンテナーから見えるようになったことです。

興味深いのは、信頼済み公開の設定は既定で「ステージまで」しかできず、直接の公開は設定ごとに明示的に有効にしないと使えない、という点です。GitHubは設定をステージ専用のままにしておくことを勧めています。ワークフローが乗っ取られても、人の承認がなければレジストリまで届かない。8月の件で破られた部分を、ちょうど塞ぐ形になっています。

トークンにも「ステージまで」の権限ができた

9月18日には、細かく権限を絞れるアクセストークン(granular access token)に、読み書きのうち「ステージのみ」という選択肢が加わりました。このトークンを使う自動化の処理は、npm stage publishで版を公開待ちに出すことはできますが、npm publishで直接公開しようとすると拒否されます。二要素認証の迂回を許可する設定にしていても同じです。

背景には、npmが2027年1月をめどに、二要素認証を迂回するトークンによる直接公開を廃止する予定だという事情があります。信頼済み公開にすぐ移れない現場向けの、移行の足がかりという位置づけです。ただし、ステージ専用トークンも配布タグの付け替えや版の非推奨化といった書き込み権限は残っているため、ほかの書き込み用トークンと同じように慎重に扱うよう注意書きがあります。利用にはnpm CLI 11.15.0以降、Node.js 22.14.0以降が必要とされています。

8月のワームが増殖に使ったのは、まさに二要素認証を迂回できる書き込み用のトークンでした。ステージ専用に切り替わっていれば、盗まれても勝手に新しい版を世に出すことはできません。ここでも、狙われた経路に対してピンポイントで手が打たれているのがわかります。

アカウントを取り戻したあとの猶予期間

9月9日の更新はもう少し地味で、リカバリーコードでサインインしたアカウントに、72時間の保留期間を設けるというものです。これまでは影響の大きいアカウントだけに適用されていた保護が、すべてのnpmアカウントに広がりました。

保留中は、サインインやパッケージの閲覧、インストールはできますが、公開やアクセストークンの作成といった影響の大きい操作が止まります。期間が過ぎれば自動で解除され、問い合わせなどは必要ありません。リカバリーコードが盗まれてアカウントを乗っ取られた場合に、すぐに悪意ある版を出されるのを遅らせるための仕組みです。自分で使った覚えがないのに公開できなくなったら、すぐにnpmのサポートに連絡してほしいとされています。

インストールする側の既定値も変わる

ここまでは公開する側の話でしたが、使う側にも大きな変更が予告されています。6月に発表されたnpm v12の破壊的変更では、npm installの挙動のうち、これまで自動で動いていたものを明示的に許可する方式に切り替えるとされています。

中心になるのは、依存パッケージのpreinstall、install、postinstallといったスクリプトを、既定では実行しなくなるという変更です。ネイティブ拡張のビルドも対象に含まれます。どのパッケージのスクリプトが止まるかはnpm approve-scriptsで一覧でき、信頼するものだけを許可すると、その許可リストがpackage.jsonに書き込まれます。あわせて、Gitリポジトリやhttpsのtarballといった外部の場所から依存を取ってくる動作も、既定では許可しない方向です。これらはnpm 11.16.0以降で警告として先に確認できます。

8月のワームが最初に動き出したきっかけはpreinstallスクリプトでした。インストールしただけで任意のコードが走るという、長年の前提そのものに手が入るわけで、影響は小さくありません。

制作会社の現場で見直しておきたいこと

npmにパッケージを公開していない制作会社でも、使う側としての備えは必要です。まず、案件ごとのリポジトリでnpmのバージョンを上げ、どのパッケージがインストール時にスクリプトを実行しているのかを一度洗い出しておくと、v12への移行で慌てずに済みます。古い案件ほど、ビルドの途中でネイティブ拡張を組み立てるパッケージが紛れていることがあり、許可リストの作成に意外と手間がかかるかもしれません。

次に、CIに置いているトークンの棚卸しです。今回の分析では、盗まれた情報の中心がCIの環境変数や認証情報でした。保守契約で複数のサイトを預かっている場合、デプロイ用の鍵やサーバーの認証情報がCIにまとまって置かれていることも多いはずです。npmのトークンに限らず、権限が広すぎないか、使っていないものが残っていないかを確かめておく価値はあります。

自社でプラグインやライブラリを公開しているなら、信頼済み公開とステージ公開への移行を検討するよい時期です。承認の手間は増えますが、少人数の現場ほど「誰かのアカウントが一つ破られたら終わり」という状態になりやすく、人の目を一段挟む意味は大きいと感じます。

私たちRESONIXでも、テーマやプラグインの開発にnpmを日常的に使っています。便利な仕組みの上に乗っている以上、その仕組みが変わる方向は追いかけておきたいところです。今回の一連の変更は、自動化を減らすのではなく、自動化の最後に人の判断を戻すという整理の仕方で、ほかのツールにも広がっていきそうな考え方だと思います。

再読み込みのない画面切り替えも速度計測の対象に

つくば市のホームページ制作会社

表示速度の指標として広く使われている Core Web Vitals には、長いあいだ埋まらない空白があった。JavaScript で画面の中身だけを差し替えるタイプのサイトでは、アドレスバーの URL が変わっても「新しいページを読み込んだ」とは扱われず、最初の読み込み時に測った数値がそのまま残り続けていた。その空白を埋める仕組みが Chrome に入り、解析サービス側の対応もこの夏から動き出している。

操作とURLと描画がそろった瞬間を区切りとみなす

Chrome の開発者向け資料では、この仕組みは「ソフトナビゲーション」と呼ばれている。何をもって画面の切り替わりとみなすかについて、ユーザーの操作が起点になっていること、ユーザーから見える形で URL が変わること、その操作の結果として実際に描画が起きること、という三つの条件が示された。この三つがそろったときにはじめて、ブラウザは新しい時間の起点を置く。

これが長らく難しかった理由も、あわせて説明されている。web.dev の解説によると、画面の一部だけを差し替える作りには標準的な型がなく、URL を更新するタイミングも、中身を読み込む順序も、サイトごとにばらばらだという。ちょっとした表示状態の変化でも URL を書き換えるサイトがある一方、まとまった単位でしか書き換えないサイトもある。この差を無視して一律に数え始めると、かえって実態から離れた数字になってしまう。だからこそ、フレームワークの違いに左右されない共通の線引きが必要だった。

二種類の記録が時系列に追加された

実装は Chrome 151 に入り、既定で有効になっている。パフォーマンスの時系列に、soft-navigation と interaction-contentful-paint という二種類の記録が追加された。前者は操作をきっかけにした同一文書内の履歴変化を報告し、そこから先の計測を最初の URL ではなく現在の画面に結びつける。後者は、操作によって書き換えられた部分に新しく描かれた内容を報告するもので、非同期の読み込みをまたいだ待ち時間も追える。

この二つがあると、切り替え後の画面についても LCP や INP、CLS を区切って測れるようになる。ただし細かい扱いには注意点が多い。同じ画像を出し続けている箇所は再描画されないため LCP の対象から外れ、通常の読み込みと切り替え後とで最大要素が変わることがある。最初のバイトが返るまでの時間にあたる TTFB は、切り替え時には便宜的にゼロとして扱うのが現在の推奨だ。こうした処理を自前で書かずに済むよう、公式の計測ライブラリ web-vitals は v6.0.0 でこの仕組みに対応している。

解析サービス側の数字が動くことがある

ブラウザが対応しても、実際に数値を見るのは解析サービスの画面だ。そちらの動きも出てきている。Cloudflare は 8 月 21 日に Web Analytics の計測改善を告知し、その変更履歴では 9 月 4 日に展開が完了したとしている。従来の全画面遷移に加えて、新しい API が使える環境での切り替えと、使えない環境で履歴の書き換えから推測した切り替えを、それぞれ別の種類として記録するようになった。後者では LCP は取れないが、ほかの指標は取得できるという。

注意したいのは、告知のなかで、ページビューや訪問の集計値、そして LCP の数値が変動しうると明記されている点だ。サイトの作りによって振れ幅は変わる。数字が動いたときにサイト側の不調を疑う前に、計測方法が変わったのではないかと一度立ち止まれるかどうかで、無駄な調査時間はかなり変わってくる。

手元のサイトで気にしておきたいこと

中小企業のサイトの多くは、ページごとに読み込み直す普通の作りなので、この話が直接効いてくる場面は限られる。とはいえ、商品の絞り込み、予約や見積もりの入力画面、地図や一覧の切り替えなど、部分的に画面を差し替えている箇所は珍しくない。そこがどれくらい待たされているかは、これまで数字として残りにくかった部分だ。

現時点で対応しているのは Chromium 系のブラウザだけで、検索まわりで参照される実測データにいつ反映されるかも、まだ示されていない。順位のために慌てて何かを変える話ではない。それでも、開発者ツールの計測画面ではすでに切り替えの区切りが見えるようになっている。自社サイトで JavaScript による画面の差し替えを使っているなら、その部分の待ち時間を一度自分の目で確かめておくと、次に改善に手をつけるときの判断材料になる。

端末の性能の目安をブラウザから受け取る仕組み

つくば市のホームページ制作会社

自分の作業機では軽快に動くのに、お客様の手元ではもたつく。制作の現場では何度も出会う話です。8月25日に安定版が公開されたChrome 152に、この端末ごとの差を扱うための小さな仕組みが入りました。CPU Performance APIと呼ばれるもので、閲覧している端末の処理性能の目安を、ごく粗い段階の数値としてJavaScriptから読み取れます。

使い方はそっけないほど簡単で、navigator.cpuPerformance を参照すると小さな整数が返ってきます。値が大きいほど性能の高い端末、という意味づけです。Chromeの開発者向けブログでは、描画の作り込みを加減する、重い計算を減らす、裏で走らせる処理の量を調整するといった使い方が挙げられています。

これまでは自前で測るしかなかった

仕様草案によると、端末の性能に応じて中身を出し分けたいという要望は以前からあり、実現しているアプリは自前でベンチマーク相当の処理を走らせるか、ウェブには開かれていない内部的な機能に頼っていたとされています。性能を測るために端末に余計な仕事をさせるのは、順序が逆さまな感じもします。提案の目的のひとつは、この無駄をなくすことだと書かれています。

考え方としては、以前からある端末メモリ量の取得と似ています。細かい実測値ではなく、あらかじめ用意された区分のどれに当てはまるかだけを返す。navigator に読み取り専用の値をひとつ足すという形も同じ流儀です。

段階の分け方と、身元の割り出しへの配慮

返る値は1から4までの4段階で、判定できなかった場合は0です。基本の分け方は、OSが報告するコア数をもとにした素朴なもので、1コアなら1、2から4コアなら2、5から10コアなら3、それ以上なら4と決まっています。そのうえで、特定のCPUがコア数から想像される性能と大きく違うと分かっている場合に限り、ブラウザ側が段階を上下に1つずらしてよいことになっています。

おもしろいのは、この区分を将来にわたって動かさないと決めている点です。もっと高性能な端末が出てきたら、既存の端末を格下げするのではなく5段目を足す。同じ端末なら、混雑していても電池が減っていても、いつでも同じ値を返す。古い端末で古いアプリを開いたときの見え方が、時間が経っても変わらないようにするための約束事です。

もうひとつの軸が、閲覧者の身元を割り出されにくくすることです。CPUの製造元や型番、コア数をそのまま渡せば、端末を特定する手がかりが増えてしまいます。そのため仕様では、それぞれの段階に既存のCPU機種の1割以上、実際に使われている端末の1割以上が入るくらいの粗さを保つべきだとしています。利用できるのはHTTPS接続の場面に限られます。

参考値として付き合う

気に留めておきたいのは、この値が絶対的な事実ではないことです。Chromeでは閲覧者自身が設定画面から報告される段階を上書きでき、組織のパソコンでは管理者が方針で指定することもできます。値はあくまで判断の材料であって、これを根拠に機能を完全に閉ざす作りにすると、上書きした人が困ることになります。

他のブラウザの姿勢も、現時点では表明されていません。提案文書でChromeは前向きとされている一方、Edge、Firefox、Safariは公開の意見なしと記されています。当面はChromeだけで読める値だと考え、取得できないときや0が返ったときにどう振る舞うかを先に決めておく必要があります。仕様の例では、判定できなかった端末は高性能側と同じ扱いにしています。

加えて、この値が示すのは端末の地力であって、いまその端末が忙しいかどうかではありません。今この瞬間の混み具合を見たい場合は、別途用意されているCompute Pressure APIと組み合わせる想定です。読み込み時に演出を出すかどうかを決め、その後の負荷を見ながら止めたり戻したりする、という二段構えの例が示されています。

中小企業のサイトで、この値をすぐに使う場面はそう多くないはずです。ただ、同じページでも端末によって体験がまるで違うという前提は、値を読むかどうかとは関係なく効いてきます。凝った動きを見せ場にするなら、それが動かない端末でも内容が伝わるか。制作側が握っているのは結局そこで、こうしたAPIはその判断を少しだけ具体的にしてくれる道具だと考えています。

Firefoxの新版で並び順と行の余白がCSSから扱える

つくば市のホームページ制作会社

Firefoxの新しい版が8月18日に公開された。目玉機能が一つあるという内容ではなく、これまで制作側が工夫して回避してきた場面に、ブラウザ側の受け皿がいくつか用意されたという性格の更新になっている。派手さはないが、日々の作業で手計算していた部分が減るという意味では効いてくる。

Mozillaが開発者向けに出している変更点の一覧を見ると、CSSとJavaScriptの両方に追加があり、加えて既定では無効のまま入っている実験的な項目もある。実務で関係しそうなところを順に並べてみる。

要素が何番目かをCSSから直接取れる

sibling-index() と sibling-count() という関数が使えるようになった。前者は親要素の中でその要素が何番目かを整数で返し、後者は自分を含めた兄弟要素の総数を返す。番号は1から始まる点が、:nth-child() と同じ考え方になっている。

これまで、リストの並び順に応じて幅や表示の遅れを変えたい場合は、:nth-child() で一件ずつ書き並べるか、テンプレート側から順番を表す変数を各要素に埋め込むのが定番だった。sibling-index() は整数を返すので、calc() の中でそのまま計算に使える。animation-delay を sibling-index() 倍で指定しておけば、項目が増えても減っても順番にずれて現れる。

似た用途の関数に counter() があるが、こちらは文字列を返すため生成コンテンツ向きで、計算には向かない。項目数が運用の中で動く一覧やナビゲーションを抱えている案件では、テンプレート側の小細工を一つ減らせることになる。

書体によってばらつく行の上下を削る

text-box-trim と text-box-edge、そして両者をまとめて書ける text-box が入った。文字の高さは書体ファイルが持つ情報に左右されるため、同じ font-size を指定しても書体が違えば行の箱の高さが変わり、上下の余白が揃わない。この差を吸収するための指定になる。

text-box-trim では削る側を選ぶ。trim-start なら上、trim-end なら下、trim-both で両方、none なら削らない。どこまで削るかは text-box-edge で決める。上を大文字の高さに、下をベースラインに揃える指定にすれば、書体を差し替えても見出しの上下の見え方が安定する。

見出しとその下の本文の間隔を、余白の値を一つずつ詰めて調整していた箇所は多いはずだ。大きな文字を置くヒーロー部分やカードの見出しなど、書体依存で崩れやすいところから恩恵がある。MDNの表示では、この二つの機能はいずれも今年8月から広く使える段階に入ったと案内されている。

繰り返し処理まわりのJavaScriptの追加

イテレータに対して使えるメソッドが四つ増えた。includes() は指定した値が含まれるかを調べ、join() は取り出した要素を区切り文字でつないだ文字列を返す。どちらも配列の同名メソッドと同じ感覚で書けるので、覚え直すことはほとんどない。

chunks() と windows() は、要素をまとまりで取り出すためのものになる。chunks() は指定した個数ずつ連続した配列に区切り、windows() は一つずつずらしながら同じ長さの配列を返す。前者は表示を数件ずつに分けたいとき、後者は隣り合う値を比べたいときに向いている。手で添字を管理していた処理を短く書ける。

既定では切ってあるが用意された指定

設定画面から有効にすると試せる項目もある。接頭辞なしで書ける line-clamp、最小値と最大値の間のどのあたりかを数値として計算できる progress()、text-decoration-inset にパーセントで指定できるようになった件、CSSの値を文字列ではなく型付きのオブジェクトとして扱う仕組みなどが該当する。

このうち line-clamp は、MDNの説明では接頭辞なしの版はまだ広く使える状態ではなく、no-ellipsis と文字列の指定にも未対応とされている。従来の -webkit-line-clamp は表示形式の指定との組み合わせが仕様として定められており、今後も動く。行数で本文を切る処理を、今すぐ書き換える必要はない。

実験段階のものを除けば、並び順を返す関数も行の余白を削る指定も、主要ブラウザが揃った段階に来ている。とはいえ、企業サイトの訪問者には古い環境も混ざる。値が効かなくても崩れない書き方を選んでおけば、対応済みの環境から順に見え方が整っていく形になる。手元の案件で余白を目分量で詰めている箇所があるなら、置き換えの候補として頭の隅に置いておきたい。

ライブラリの棚卸しにBaselineを使うという発想

つくば市のホームページ制作会社

一度入れた外部ライブラリを、あとから見直すことはあまりない。動いているし、テストも通っているし、あえて触る理由がない。ただ、その間にもブラウザ側は動いていて、いま package.json に並んでいるもののうち何割かは、すでにブラウザが自前で持っている機能と重なっている。Smashing Magazine に出た依存関係の棚卸しの記事が、その重なりを具体的な数字で示していて面白かった。

入れたきりの依存が積み上がっていく

記事によると、中規模のJavaScriptアプリでは、圧縮後でおよそ60KBから90KB分の依存が、いまやブラウザ側で代替できる範囲に入っているという。日付や数値の書式、HTTP通信、モーダル、ツールチップ、オブジェクトの複製、配列のグループ化。数年前までは確かに穴だった領域が、順に埋まってきた結果だ。

それでもライブラリが残り続けるのは、怠慢だからではないと筆者は書いている。セキュリティの観点で npm audit は回していても、「このライブラリは今もブラウザにできないことをやっているのか」という問いを立てる機会が、そもそも運用の中に組み込まれていない。だから入れたまま何年も過ぎる。複数サイトの保守を抱えている制作の現場だと、この感覚は身に覚えがあるのではないかと思う。

Baselineという安全度の目盛り

棚卸しの物差しとして使われているのが Baseline だ。WebDX Community Group による指標で、ある機能が主要ブラウザ(Chrome、Edge、Firefox、Safari)でどこまで安全に使えるかを三段階で示す。全エンジンには載っていない「限定的な利用可能性」、出そろった直後の「新しく利用可能」、出そろってから30か月が経った「広く利用可能」という並びになっている。

この30か月の差が、棚卸しでは効いてくる。広く利用可能なものは、基本的に今日そのまま置き換えを検討できる。新しく利用可能な段階のものは、自分のサイトの訪問者層を確かめてから決める話になる。状態は webstatus.dev や、MDN の各機能ページに付いているバッジで引ける。

消す前に通しておきたい三つの問い

「ブラウザができるようになった」と読んで、すぐ削り始めないほうがいい、というのが記事の立場だ。紙の上では無料に見える置き換えが、一部の利用者の環境を静かに壊すことがあるし、気づかずに頼っていた機能を落とすこともある。そこで、削る前に三つ確認する。

ひとつめは、代替となる機能が自分の利用者にとって安全かどうか。一般論としてのBaselineではなく、アクセス解析や browserslist の設定と突き合わせて判断する。社内向けの管理画面と、古い端末からの流入が長く続く一般向けサイトでは、答えが変わる。

ふたつめは、置き換えの費用。ブラウザ側の対応が足りずポリフィルを足すことになり、それが外したライブラリより重ければ、容量は増えている。

みっつめは、ブラウザの機能が実際の使い方をカバーしているか。ライブラリは見た目の似た標準機能より多くの仕事をしていることが多い。記事が挙げているのが axios で、fetch に置き換えると、404や500で拒否されない、共通処理を差し込むインターセプタがない、自動再試行がない、アップロードの進捗が取れない、といった差が出る。実際にどこまで使っているかを見てから決める、という順番になる。

置き換えが効きやすいのは書式と画面部品まわり

記事はライブラリを一個ずつではなく、かたまりで見ていく。いちばん取りやすいのが国際化まわりで、相対時間、数値や通貨の書式、複数形、配列を文章に連結する処理は、ブラウザの Intl 系で大半が置き換えられる。この一群でおよそ14KBという計算だ。ただし継続時間の書式は主要エンジンに出そろったのが2025年3月で、広く利用可能になるのは2027年の見込みとされている。

もうひとつ大きいのが画面部品で、こちらはツールチップやポップオーバーのライブラリまで含めて合計およそ24KB。このうちモーダル用のライブラリ、フォーカスを閉じ込める処理、背景のスクロールを止める処理が、dialog要素とCSSの一行にまとまる。showModal で開けば、フォーカスが中に移り、背後が操作できなくなり、Escapeで閉じ、閉じたあとは元の要素にフォーカスが戻る。重なり順もブラウザが面倒を見るので、z-index と格闘しなくてよくなる。手書きの実装より結果的に読み上げ環境への配慮が行き届く、という指摘もうなずける。

通信まわりも同じ見方ができる。よく使われるHTTPクライアントは圧縮後で17KBから19KBほどあり、単純な取得や送信であれば fetch と中断用の仕組みで足りる。タイムアウトも標準の指定で書ける。ここは前述のみっつめの問いが効く場所で、共通処理や再試行に頼っているなら、外した分を自分で書き直すことになる。

配列やオブジェクトの操作も、グループ化や深い複製、集合の和や積は標準側に入った。一方で debounce と throttle には今も標準の代わりがないので、そこは残す。全部捨てるという話ではなく、ブラウザがすでに持っている部分を二重に配らない、という整理だ。

今は手放さないという判断も同じ枠組みから出る

この記事の良いところは、置き換えない例をきちんと入れているところだ。JavaScriptの日付処理を置き換える Temporal は、2026年3月に仕様策定の最終段階に達し、Firefox と Chrome には載ったが、Safari の安定版にはまだ来ていない。全ブラウザで使うにはポリフィルが要る。

そこで数字を並べると、軽量な日付ライブラリが圧縮後3KB程度なのに対し、公式のポリフィルは44KB前後ある。今すぐ乗り換えると容量は減るどころか増える。三つの問いに通すと、機能の良さでは勝っていても、利用者の範囲と費用で落ちる。だから今は現状維持で、Safari が対応してBaselineに入った時点でもう一度見る。判断を「保留」として記録しておける枠組みは、実務では地味に効く。

ブラウザ側の受け皿は今も増えている

置き換え先が増え続けているのも事実で、Chrome 150では、矢印キーでの移動やフォーカス位置の記憶を属性の指定だけで賄える focusgroup が入った。従来は tabindex を書き換える手書きのスクリプトで実現していた部分だ。文字を枠幅に合わせて拡縮する text-fit や、border-image の回り道なしでグラデーションの枠線を描ける background-clip の新しい値も同じ流れにある。

続く Chrome 151 のベータでは、コンポーネントの内側にある要素を aria-labelledby などから参照できる仕組みや、複合的な部品の中の補助的な操作を支援技術に伝える aria-actions が挙がっている。手書きのJavaScriptで補っていた振る舞いが、少しずつ宣言的な記述に移っていく。

中小企業向けのサイトだと、そもそも巨大な依存を抱えていないことも多い。それでも、テーマやプラグインが読み込んでいるものを一度数えてみる価値はある。四半期に一度、本番に出ている依存だけを並べ、それぞれが実際のビルドでどれだけ容量を占めているかを解析ツールで測り、代わりになる機能のBaselineの状態を確かめる。そのうえで先ほどの三つの問いに通し、いま標準になっているものを返していく。それだけで表示は軽くなり、更新を追いかける対象も減る。まずは一つの分野だけ選んで手元の設定ファイルを開いてみる、という始め方が現実的だと思う。

読み込み直さない画面切り替えの速さをChromeが測れるようになった

つくば市のホームページ制作会社

サイトの表示速度を測る指標として、Core Web Vitalsはすっかり定着しました。ところが、この指標には長らく穴があると言われてきました。ページを読み込み直さずに中身だけを差し替える作りのサイトでは、最初の一回しか計測されないという問題です。Chromeの最新版で、この部分をブラウザ側で測る仕組みが正式に使えるようになりました。

Chromeの開発者向け資料によると、Soft Navigations APIと呼ばれるこの機能は、試験運用の期間を経て、2026年7月に公開された版から設定を切り替えずに利用できるようになりました。名前のとおり、ソフトナビゲーション、つまり読み込み直さない画面遷移を計測の対象にするものです。

これまで測れていなかった部分

従来のCore Web Vitalsは、ブラウザがURLを開いて新しい文書を読み込む、いわゆる通常の遷移を前提に設計されています。表示までの時間を示すLCP、レイアウトのずれを示すCLS、操作への反応を示すINPは、どれもそのページが開かれた時点を起点に集計されます。

JavaScriptで画面を組み立てる作りのサイトでは、二画面目以降はURLだけが書き換わり、文書の読み込みは起きません。ブラウザから見れば一枚のページがずっと開かれたままなので、二画面目の表示がどれだけ遅くても、最初の一枚の数字に埋もれてしまいます。逆に、最初の表示さえ速ければ全体が良好に見えてしまうこともありました。計測ツール側で独自に区切りを入れる回避策はありましたが、実装ごとに基準が違い、横に並べて比べられる数字にはなりにくい状態でした。

ブラウザはどこで区切りを判断するのか

新しい仕組みでは、ブラウザ自身が三つの条件をもとに画面の切り替わりを見分けます。利用者の操作がきっかけになっていること、利用者から見えるURLの変化を伴うこと、そしてその結果として実際に画面が描き直されること。この三つがそろったときに、ひとつの区切りとして扱われます。

あくまで推測にもとづく判定なので、公式の説明でも、サイトの作り方によっては拾いすぎたり拾いそこねたりすることがあると断っています。それでも、判定の基準がブラウザ側に統一されたこと自体に意味があります。計測ツールを乗り換えても、同じ考え方で区切られた数字が並ぶからです。

計測する側で増えたもの

開発者から見ると、パフォーマンス情報を受け取る仕組みに新しい種類の記録が追加された形になります。切り替わりそのものを表す記録と、切り替わったあとの主要な描画を表す記録が加わり、既存の各種タイミング情報にも何番目の遷移かを示す値が付くようになりました。これで、ひとつの記録がどの画面のものかを判別できます。

ただし、これらを直接扱うのはそれなりに骨が折れます。読み込み直さない遷移では最初の応答までの時間がゼロとして扱われるなど、通常の遷移とは数字の意味が変わる場面もあるためです。Googleが公開している計測用のライブラリweb-vitalsは、新しい版でこのあたりを内部で吸収するようになっており、URLの対応付けや数値のリセットを任せられます。自前で計測基盤を持っているところ以外は、ライブラリの更新に乗るほうが現実的でしょう。

今すぐ効いてくる話ではない

注意しておきたいのは、この計測結果が検索での評価にそのまま反映されるわけではない点です。実利用者のデータを集めたChrome User Experience Reportにも読み込み直さない遷移の分を加えることは目指されていますが、どのような形で反映されるかは未定とされています。対応もChromium系のブラウザに限られます。つまり現時点では、自分たちで測って改善に使うための道具という位置づけになります。

WordPressで作られた一般的な企業サイトのように、リンクを踏むたびにページを読み込み直す作りであれば、直接の影響はほとんどありません。関わってくるのは、予約や検索の絞り込み、会員向けの管理画面など、画面の一部だけを差し替える作りを取り入れている場合です。最近はView Transitionsのように、通常の遷移でもアプリらしい見せ方ができる手段が増えており、境目は少しずつ曖昧になっています。

数字が見えるようになると、これまで感覚で語られていた二画面目が重いという話を、根拠を持って共有できるようになります。制作側と運用側で改善の優先順位を決めるとき、この差は思ったより大きいはずです。

地域ごとの週の始まりや暦をブラウザ標準で引ける仕組み

つくば市のホームページ制作会社

日付まわりの表示は、サイトを作っていればどこかで必ず触ることになります。予約フォームのカレンダー、記事の投稿日、営業日の一覧。一見どれも単純ですが、対象の地域が変わると前提そのものが変わります。週の始まりは日曜なのか月曜なのか、週末はどの曜日にあたるのか、どの暦を併記するのか。こうした知識は、これまでブラウザの外から持ってくるしかありませんでした。

2026年7月、JavaScriptの国際化機能であるIntl.Localeに加わった一連のメソッドが、主要ブラウザすべてで使える状態になりました。web.devの月次まとめによると、Firefox 153が対応したことで、Baselineの「新しく利用可能」に入ったとされています。地味な機能ですが、カレンダー部品を自作したことがある人ほど、ありがたみが分かる種類の追加です。

これまでは辞書を自前で抱えていた

「この地域では週が月曜から始まる」といった知識は、CLDRという国際的なデータベースにまとめられています。ただ、ブラウザからその中身を直接引く手段が長らくなく、カレンダーの見た目を自分で組む場合は、データの一部を写し取ったライブラリを読み込むのが普通でした。週の初日を表す値ひとつのために、数十キロバイトの追加読み込みが発生することも珍しくありません。

Intl自体はかなり前からあり、Intl.DateTimeFormatを使えば日付を地域の書式に整えることはできました。ただしそれは整形済みの文字列が返ってくるだけで、UIを自分で組み立てるために必要な素の情報、たとえば曜日を並べる順番の起点までは取り出せません。今回埋まったのは、ちょうどこの隙間にあたる部分です。

Intl.Localeから引けるようになった情報

書き方は素直で、ロケールを表すオブジェクトを作ってメソッドを呼ぶだけです。new Intl.Locale("ja-JP").getWeekInfo() のように書くと、週の始まりの曜日、週末にあたる曜日、その年の最初の週とみなすための最小日数がまとめて返ってきます。曜日は1が月曜、7が日曜という決まりになっています。

同じ要領で、その地域で使われる暦の一覧を返す getCalendars()、時刻を12時間制と24時間制のどちらで扱うかを返す getHourCycles()、文字を左から右に並べるか右から左に並べるかを返す getTextInfo()、地域に結び付いたタイムゾーンの一覧を返す getTimeZones() が用意されています。ほかに数字の表記体系や並べ替えの規則を返すものもあり、いずれも MDNのIntl.Localeのページに一覧があります。

返ってくるのは配列や小さなオブジェクトなので、そのまま画面に出すというより、自分のUIの初期値として使う性格のものです。

日本語のサイトで効いてくる場面

日本のロケールで getCalendars() を呼ぶと、グレゴリオ暦と和暦の識別子が返ってきます。行政関連の書類を扱うサイトや、年号の併記が求められる申込フォームでは、この結果を起点にIntl.DateTimeFormatへ和暦を指定する、という流れが自然に組めます。和暦を出すかどうかを地域の慣習として扱えるので、判定を自前のif文で書き分けずに済みます。

週の始まりも実務的です。日本語圏では日曜始まり、英国では月曜始まりというように、カレンダーの見た目は地域で割れます。多言語対応のサイトで同じカレンダー部品を使い回すとき、対応表を自分で抱えなくてよくなるのは負担が減るところです。予約カレンダーや営業日の表示は、中小企業のサイトでも決して珍しい要素ではありません。

使う前に確認しておきたいところ

Baselineの「新しく利用可能」は、主要ブラウザの最新版で動くという意味であって、少し前の端末まで含めて安全という意味ではありません。企業サイトの訪問者には更新の止まった端末も混ざりますから、メソッドがあるかどうかを確かめて、無ければ従来どおりの既定値を使う、という組み方が現実的です。値が取れなくても表示が壊れないようにしておけば十分です。

もう一点、以前の実装ではメソッドではなくプロパティとして提供されていた時期があります。古い解説記事のコードをそのまま持ってくると動かないことがあるので、参照する情報の新しさには注意しておきたいところです。

外部ライブラリに頼っていた小さな機能が標準側に移ると、依存パッケージがひとつ減り、更新の手間もその分軽くなります。派手さはありませんが、次にカレンダーまわりを触る機会があれば、置き換えられる部分がないか見ておく価値はありそうです。

JavaScriptで組んでいた部品がHTML側に移りつつある

つくば市のホームページ制作会社

ウェブ制作の現場で長く続いてきた作業のひとつが、ブラウザに足りない機能をJavaScriptで補うことでした。開閉するパネル、画面全体に出るダイアログ、装飾された選択メニュー。本来はただの部品なのに、ライブラリを読み込み、初期化のコードを書き、キーボード操作や読み上げの面倒まで見て、数年後の保守で頭を抱える。制作に関わっていれば、たいてい心当たりのある流れだと思います。

ここ数年、その前提が少しずつ変わってきています。7月28日に安定版が出たChromeの最新版の変更点を眺めると、方向がかなりはっきり見えます。カメラとマイクの扱い、Shadow DOMの組み立て、画面切り替えの計測。どれもこれまではJavaScriptの領分だったものが、HTMLの要素や属性、あるいはブラウザ標準の計測項目として整理されつつあります。今回はこの流れを、直近のブラウザ各社の動きと並べて眺めてみます。

カメラとマイクの入口がHTMLの要素になる

目を引くのは usermedia という新しい要素です。ブラウザが用意した操作部品として画面に置かれ、そこからカメラやマイクの利用が始まります。Chromeの開発者向けブログによると、利用者の意図をはっきりさせた上で許可を求め、映像や音声のストリームを受け取るところまでを、この要素が受け持つとされています。

従来はJavaScriptから取得用の関数を呼ぶと、いきなりブラウザの許可ダイアログが出る作りでした。押した覚えのないタイミングで「カメラを使いますか」と聞かれれば、多くの人はまず拒否します。そして一度拒否されると、設定から手で戻してもらうしかない。許可の取りこぼしは技術の問題ではなく導線の設計の問題で、その導線をブラウザ側に寄せるという判断は理にかなっています。

使いどころとしては、オンライン相談の受付ページ、採用ページで応募者に短い動画を録ってもらう仕組み、業務用の写真アップロードなどが考えられます。ただし現時点ではChromeだけの機能なので、これ抜きでも成立する作りにした上で、対応ブラウザでは体験が良くなる、という積み方が現実的です。

影の中の差し込み口も属性で書ける

同じ版では、template 要素に shadowrootslotassignment という属性が加わりました。Shadow DOMの中で、どの中身をどの差し込み口に入れるかを手動で割り当てる指定です。これまでは JavaScript から Shadow DOM を作るときにオプションで渡すしかなく、スクリプトが動くまで組み立てが完了しませんでした。

地味な変更に見えますが、意味は小さくありません。サーバー側が吐き出したHTMLだけで部品が完成するなら、最初の表示が崩れて後から整うという、あの落ち着かない一瞬が減ります。PHPでHTMLを組み立てるWordPressのような環境とも相性が良く、ブロックやテーマの作り込みで恩恵を受ける場面はありそうです。

見た目の調整からスクリプトが抜けていく

この半年ほどの各ブラウザの更新を並べると、同じ傾向がもっと広い範囲で起きていることが分かります。グリッドやフレックスの隙間に線を引く指定、箱の幅に合わせて文字の大きさを自動調整する指定、入力欄が中身の量に応じて伸縮する指定。最後のものはFirefoxが対応したことで、主要なブラウザエンジンすべてで使える状態になりました。矢印キーでの移動先をまとめて宣言できる属性も加わっています。

どれも、かつては手で書いていた処理です。文字幅を測って収まるまで縮めるコード、入力のたびに高さを再計算するコード、キーボード操作を自前で組み立てるコード。案件ごとにコピーして、少しずつ挙動が違う状態で増えていく類のものでした。それが数行のCSSや属性ひとつに置き換わるなら、書く量が減るだけでなく、動作の説明もしやすくなります。

制作者側の実利は、たぶん「新しい表現ができる」よりも「消せるコードが増える」ところにあります。納品後に触る人が読む量が減るのは、それ自体が品質です。

足並みがそろわない例もある

とはいえ、宣言的に書ける方向へ一直線に進んでいるわけではありません。分かりやすい例が、選択メニューの見た目を自由に整えられる仕組みです。Chromeでは去年のうちに安定版に入り、Safariは開発者向けの先行版で確認できる段階、Firefoxは試験版でフラグを立てて試す段階。MDNの解説でも、広く使われるブラウザの一部で動かないため安定して使える状態には達していない、という位置づけになっています。

ブラウザごとの歩幅の違いも、この7月にそのまま表れました。Chromeが新しい要素を入れた前日にはSafariの更新版が出ていますが、こちらはWebAssemblyまわりの小さな追加と、CSSや通信の不具合修正が中心です。文字の大きさの単位が拡大表示でずれる問題や、要素の配置指定が意図した位置に戻らない問題が直されています。新機能を並べる回もあれば、土台を固める回もある、というだけの話ですが、対応状況を「だいたい揃った」で済ませられない理由ではあります。

ブラウザ間の差を埋める取り組みとしては、Apple、Google、Igalia、Microsoft、Mozillaが共同で進めるInterop(相互運用性)のプロジェクトがあります。今年の重点領域は二十近く挙げられており、テストの通過率がダッシュボードで公開されているので、気になる機能の足並みを自分で確かめられます。営業資料に「最新の書き方に対応」と書く前に、こういう一次情報で裏を取る癖をつけておくと安全です。

体感速度の測り方も追いついてきた

もうひとつ、Chromeの最新版には計測まわりの追加があります。画面を読み込み直さずに表示を切り替える作りで、その切り替えを一区切りとして扱い、操作をきっかけに描かれた主要な内容が出るまでを測れるようになりました。

これは長く空いていた穴です。表示速度の指標は最初の一画面に強い一方、その後の画面遷移は測りにくく、「最初は速いのに使い始めると重い」という感想を数字で示せませんでした。予約フォーム、商品の絞り込み、地図の切り替えなど、中小企業のサイトでも読み込みを挟まず描き替える作りは増えています。改善の順番を決めるときに、体感に近い数字が手元にあるかどうかは大きな差になります。

もっとも、指標が増えれば追う手間も増えます。全部を見るのではなく、その画面で一番使われる操作をひとつ決めて、その前後だけ測るくらいでも十分に判断材料になります。

どこから取り入れるか

実務での見極めは、三つに分けて考えると迷いません。まず、主要なブラウザすべてで使える状態になったものは、素直に置き換えの候補にできます。入力欄の伸縮や要素同士を結びつける配置指定はこの段階です。次に、特定のブラウザだけで動くものは、無くても成立する上乗せとして扱う。カメラの新しい要素は今のところここに入ります。最後に、置き換えによって読み込んでいるライブラリやプラグインを一つ減らせるかどうかを見る。減らせるなら優先度は上がります。

この最後の観点が、長く運用するサイトでは一番効きます。数年前に選んだライブラリの更新が止まり、依存関係の警告だけが増えていくという話は珍しくありません。ブラウザに入った機能は簡単には消えないので、同じことができるなら標準の側に寄せておくほうが、後々の手間は少なくて済みます。

新機能の一覧を追いかけるのは楽しい作業ですが、実利という意味では逆向きの棚卸しのほうが効くのかもしれません。いま抱えているJavaScriptのうち、どれがすでにHTMLやCSSで書けるようになっているのか。手元の案件をひとつ開いて、読み込んでいるファイルを上から見ていくだけでも、消せる候補はいくつか見つかるはずです。