k8o

CSS Custom Highlight APIで任意の範囲のテキストをハイライトする

Firefox 140でCSS Custom Highlight APIがサポートされ、DOMを変更せずに任意のテキスト範囲をハイライトできるようになりました。JavaScriptでRangeオブジェクトを定義し、Highlightオブジェクトとして登録後、CSSの::highlight擬似要素でスタイリングしてハイライトを作ります。

公開: 2025年6月28日(土)
更新: 2025年6月28日(土)
閲覧数29 views

はじめに

Firefox 140がリリースされ、CSS Custom Highlight APIがサポートされました。この新機能により、JavaScriptで定義した任意のテキスト範囲をCSSでスタイリングできるようになります。

これは、構文ハイライト、検索結果のハイライト、スペルミスの表示など、多くの用途で活用できる画期的な機能です。

CSS Custom Highlight APIとは

CSS Custom Highlight APIは、ページ内のDOMに影響を与えることなく任意のテキスト範囲をハイライトさせるAPIです。

このAPIは::selection::spelling-error::grammar-error::target-textのような擬似要素を拡張したようなもので、::highlight擬似要素を利用します。

特徴

  1. DOMに影響を与えることなく、任意のテキスト範囲に対してハイライト可能
  2. JavaScriptから動的にハイライトの追加、変更、削除が可能
  3. ハイライトの優先順位を設定可能
  4. 支援技術に対してハイライトの意味的情報を提供可能

利用方法

まず初めに、Rangeオブジェクトを使用して、ハイライトしたいテキストの範囲を定義します。

// ハイライトするテキストのElementを取得
const targetNode = document.getElementById('target-text');

// Rangeオブジェクトを作成
const range = new Range();

// テキストノードの開始位置と終了位置を設定(例では最初の2文字めまで)
range.setStart(targetNode, 0);
range.setEnd(targetNode, 2);

次に、Rangeオブジェクトを使用してHighlightオブジェクトを作成し、それをHighlightRegistryに登録します。

HighlightRegistryにはCSS.highlightsからアクセスします。

// Highlightオブジェクトを作成
const highlight = new Highlight(range);

// HighlightRegistryにHighlightオブジェクトをmy-highlightとして登録
CSS.highlights.set('my-highlight', highlight);

最後に、::highlight擬似要素を用いてmy-highlightで登録した箇所のスタイルを定義します。

::highlight(my-highlight) {
  background-color: yellow;
  color: black;
}

これで完了です。指定したテキスト範囲がハイライトされ、スタイルが適用されます。

12文字以降をハイライトした例

知らざるを知らずとなす、これ知るなり

APIへの理解を深める

Highlightオブジェクト

Highlightオブジェクトは、一連のRangeオブジェクトを同じハイライトを行うグループとして管理するためのものです。

オブジェクトの作成

Highlightオブジェクトは、1つ以上のRangeオブジェクトを追加して作成されます。

const highlight = new Highlight(range1, range2, range3);

複数のRangeオブジェクトを渡すことで、1つのハイライトに複数のテキスト範囲を指定できます。

オブジェクト作成後の操作

Highlightオブジェクトの作成後も、それが持つRangeオブジェクトを操作できます。

Highlightオブジェクトが持つRangeオブジェクトはsizeプロパティで確認できます。

console.log(highlight.size);

addメソッドは新たなRangeオブジェクトを追加するために使用されます。

highlight.add(newRange);

clearメソッドは、すべてのRangeオブジェクトを削除します。

highlight.clear();

deleteメソッドは、特定のRangeオブジェクトを削除します。

highlight.delete(range1);

この他にも、Setオブジェクトが持つようなentriesforEachkeysvalueshasメソッドも利用可能です。

つまり、HighlightオブジェクトはRangeだけを持つSetオブジェクトなような振る舞いをします。

優先度の設定

複数のハイライトが重複する場合、Highlightオブジェクトのpriorityプロパティを参照して、どのハイライトが優先されるかを決定します。

const highPriorityHighlight = new Highlight(range1);
highPriorityHighlight.priority = 10;

const lowPriorityHighlight = new Highlight(range1);
lowPriorityHighlight.priority = 1;

const defaultPriorityHighlight = new Highlight(range1);

console.log(highPriorityHighlight.priority); // 10
console.log(lowPriorityHighlight.priority); // 1
console.log(defaultPriorityHighlight.priority); // 0

priorityのデフォルトは0です。上記の例では、highPriorityHighlightが最も優先され、次にlowPriorityHighlight、最後にdefaultPriorityHighlightが適用されます。

優先度の異なるハイライトの例

Imagination is more important than knowledge

上記の例では、Imaginationの部分に3つのハイライトを定義しています。一つは優先度1で青色、もう一つは優先度1で黄色、最後は優先度0で赤色です。

定義の通り優先度が高い青色と黄色が優先して表示されます。そして、優先度が同じ場合はCSS.highlightsに後から登録されたハイライトが優先されます。

今回は青色->黄色->赤色の順に登録したので、黄色が優先されて表示されています。

ハイライトの意味を指定

typeプロパティはハイライトの意味を指定できます。これにより、支援技術がハイライトの内容を理解しやすくなります。

const spellErrorHighlight = new Highlight(errorRange);
spellErrorHighlight.type = 'spelling-error';

typeにはデフォルトのhighlightの他に、spelling-errorgrammar-errorなどの値を指定できます。

highlightには特別な意味がありません。spelling-errorはスペルミス、grammar-errorは文法エラーを意味します。

grammer-errorでハイライトした例

食べれる

HighlightRegistry

HighlightRegistryは、複数のHighlightオブジェクトを管理するためのオブジェクトでCSSオブジェクトに静的に組み込まれています。

HighlightオブジェクトがSetオブジェクトのような振る舞いをするのに対して、HighlightRegistryMapオブジェクトのような振る舞いをします。

keyはハイライトの名前で、valueHighlightオブジェクトです。

CSS.highlights.set('my-highlight', highlight); // Highlightオブジェクトを登録
CSS.highlights.get('my-highlight'); // Highlightオブジェクトを取得
CSS.highlights.has('my-highlight'); // Highlightオブジェクトが存在するか確認
CSS.highlights.delete('my-highlight'); // Highlightオブジェクトを削除
CSS.highlights.clear(); // すべてのHighlightオブジェクトを削除

setメソッドはHighlightRegistryオブジェクト自体を返すので連鎖的に記述することも可能です。

CSS.highlights
  .set('my-highlight', highlight1)
  .set('another-highlight', highlight2);

::highlight擬似要素

::highlight擬似要素は、HighlightRegistryに登録されたハイライトをCSSでスタイリングするために使用します。

::highlight(my-highlight) {
  background-color: yellow;
  color: black;
}

この中ではcolorbackground-colortext-decorationtext-shadowしか、利用できないことに注意してください(-webkitから始まる一部のプロパティも利用可能です)。

まとめ

Firefox 140でのCSS Custom Highlight API対応により、柔軟で効率的なテキストハイライト機能を実装できるようになりました。

DOMを操作するような古典的な手法と比較して、パフォーマンス面でも大きなメリットがあるため利用していきたいですね!

この記事はどうでしたか?

500文字以内でご記入ください

ブログの購読

k8oのブログを購読する

k8oのブログを購読することで、最新の情報を受け取ることができます。

登録いただいたメールアドレスは、購読のためにのみ使用されます。