CSS Custom Highlight APIで行う文字スタイル変更 前編 利用用途例と基本的な使い方
CSS Custom Highlight APIについて、まずはどのようなことに使えそうかを見てから、基本的な使い方を見てみましょう。JavaScriptで任意のテキスト範囲を定義し、CSSでその範囲にスタイルを適用していきます。
- カテゴリー
- CSS >
- CSSプロパティ
- JavaScript/TypeScript >
- ブラウザAPI
発行
はじめに
CSSには、::selectionという擬似要素があります。これを使うと、ユーザーが選択しているテキストの背景色や文字色といったスタイルを変更できます。
CodeGridのWebサイトでも、テキストを選択すると背景色が薄い黄緑色になります。
こういった強調のための擬似要素は、他にも::spelling-errorや::grammar-errorなどがあります。
- ::selection - CSS | MDN
- ::spelling-error - CSS | MDN
- ::grammar-error - CSS | MDN
- ::target-text - CSS | MDN
これらは、テキストのある範囲に対してスタイルを変更できる擬似要素であり、本記事ではこれらを「強調表示擬似要素(Highlight Pseudo-elements)」と呼ぶことにします。
強調表示擬似要素は、HTMLの構造に手を加えることなく「選択したテキスト」や「綴りや文法エラーがあるテキスト」に対してスタイルを適用できるため、とても便利です。
ただし、どの範囲が強調されるかはブラウザ側であらかじめ決められており、ウェブサイトの制作者が自由に指定することはできません。たとえば、::selectionの場合はユーザーがマウスやキーボードで選択した範囲が強調されますし、::spelling-errorや::grammar-errorはブラウザがスペルミスや文法エラーと判断した範囲が強調されます。
そこで登場するのがCSS Custom Highlight APIです。このAPIを使うと、JavaScriptで任意のテキスト範囲を定義し、その範囲に対してCSSでスタイルを適用できるようになります。
この記事では、テキスト選択や検索結果のハイライトを、JavaScriptとCSSで自由に制御できるCSS Custom Highlight APIの基本と、実践的な使用方法について解説していきます。
これって何に使えそう?
「任意のテキスト範囲を定義してスタイルを変更できる」と言われても、最初はピンと来ないかもしれません。
筆者がまず思いついた用途は、次の2つです。
- 検索結果のマッチしたキーワードを強調表示する
- シンタックスハイライトを行う
検索結果のマッチしたキーワードに色を付ける
文章の中からキーワードを検索するUIでは、検索語にマッチしたテキストを強調表示することがよくあります。そのような場面で、CSS Custom Highlight APIは非常に有用です。
特に便利なのは、検索結果を強調表示するためにHTML構造を変更する必要がない点です。
たとえば、次のようなHTMLがあるとします。
元のHTML
<p>インポート属性として定められている構文は、<code>import</code>文の末尾に<code>with</code>キーワードを続け、...このとき、「import文」の部分を次のように強調表示したいとします。
CSS Custom Highlight APIを使わずに強調表示するのであれば、次のように対象のキーワードをmark要素などで囲む必要があります。
CSS Custom Highlight APIを使わずに強調表示する
<p>インポート属性として定められている構文は、<mark><code>import</code>文</mark>の末尾に<code>with</code>キーワードを続け、...この方法では、検索のたびにHTML構造を書き換える必要があり、実装や管理が煩雑になります。
しかしCSS Custom Highlight APIを使えば、HTMLの構造を変更せずに、任意の範囲、たとえばcode要素をまたいだテキスト範囲でも強調表示できます。
シンタックスハイライト
ウェブサイト上にHTMLやJavaScriptのコードを表示する際には、シンタックスハイライト用のライブラリを使うのが一般的です。CodeGridでも利用しているshikiやhighlight.js、Prismなどが有名です。
これらのライブラリでは、色を変える対象の文字列をspan要素で囲むことで、シンタックスハイライトを実現しています。
その結果、1行のコードの中に大量のspan要素が生成されることも珍しくありません。
CSS Custom Highlight APIを使えば、DOMを汚さずにテキストの見た目だけを変更できるため、場合によってはこのようなspan要素を減らせる可能性があります。
基本的な使い方
CSS Custom Highlight APIで任意のテキストの範囲を定義するには、次の2つのことを行います。
- JavaScriptで、任意のテキストの範囲を定義する
- CSSで、その範囲に適用するスタイルを定義する
1.JavaScriptで任意のテキストの範囲を定義する
JavaScript側では、次の2つを行います。
- Rangeオブジェクトを使って、テキストの範囲を定義する
- そのRangeをまとめた Highlightオブジェクトを作成し、CSSから参照できるように登録する
ここで例とする、ハイライト対象のHTMLは次のとおりです。
ハイライト対象のHTML
<p id="text">CSS Custom Highlight API は便利です。</p>それでは、JavaScriptを見ていきましょう。まず、ハイライトしたい要素を取得し、その中の「文字そのもの」を表すTextNodeを取得します。
// 1) ハイライトしたい要素を取る
const p = document.getElementById("text");
// 2) pの中の「文字そのもの(TextNode)」を取る
// p.firstChild は "CSS Custom Highlight API は便利です。" という TextNode
const textNode = p.firstChild;次に、Rangeオブジェクトを作成し、どこからどこまでを強調表示するかを指定します。
// 3) Rangeで「どこからどこまで」を決める
const range = new Range();ここではCSS Custom Highlight API は便利です。という文字列の中から、文頭のCSSという単語を選択したいと思います。
// ここでは "CSS" を選びたいので、0〜3
range.setStart(textNode, 0);
range.setEnd(textNode, 3);始点を指定するrange.setStartでは0番目、終点を示すrange.setEndでは3番目(の手前まで)を指定することになります。次の表は各文字の文字の位置(index)を表したものです。空白文字(スペース)もindexの1つとしてカウントされる点に注意してください。
| 文字 | C | S | S | C | u | s | t | o | |
|---|---|---|---|---|---|---|---|---|---|
| index | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
そして、作成したRangeを使ってHighlightオブジェクトを作成します。
// 4) RangeをHighlightに入れる
const highlight = new Highlight(range);範囲が複数個ある場合はnew Highlight(range, range2, range3)のように複数指定もできます。
// 5) 名前をつけてブラウザに登録する
// "my-highlight" が CSS の ::highlight(my-highlight) と対応する
CSS.highlights.set("my-highlight", highlight);最後に、このHighlightに名前を付けてブラウザに登録します。この名前(my-highlight)を使って、CSSからスタイルを指定できるようになります。
CSSでハイライトのスタイルを定義する
CSS側では非常に簡単です。
::highlight擬似要素の引数に、先程JavaScriptで登録したカスタムハイライトの名前my-highlightに対してスタイルを定義するだけです。
CSSでハイライトのスタイルを定義
::highlight(my-highlight) {
background: yellow;
}ただし、注意しなくてはならないのが、次のプロパティのみが利用可能という点です。
- color
- background-color
- text-decoration および関連するプロパティ
- text-shadow
- stroke-color
- fill-color
- stroke-width
- カスタムプロパティ
たとえばfont-size: 30px;やfont-weight: bold;としても無視されてしまうので、利用するCSSのプロパティには注意が必要です。
これで、任意の部分(CSS Custom Highlight API は便利です。のCSS)をハイライトさせられるようになりました。
::highlight()擬似要素は、執筆現在(2025年12月22日)のFirefoxでは部分的なサポートとなっていて、text-decorationとtext-shadowは利用できません。
ここまでのまとめ
前編では、CSS Custom Highlight APIの概要と基本的な使い方を解説しました。
CSS Custom Highlight APIは、HTML構造を変更せずに、JavaScriptで指定した任意のテキスト範囲を強調表示できます。
基本的な手順は次のとおりです。
- JavaScriptでの範囲定義をする
- Rangeオブジェクトを使ってテキストの開始・終了位置を指定し、それをHighlightオブジェクトにまとめる。最後に
CSS.highlights.set()で名前を付けて登録
- Rangeオブジェクトを使ってテキストの開始・終了位置を指定し、それをHighlightオブジェクトにまとめる。最後に
- CSSでのスタイル定義をする
::highlight()擬似要素の引数にJavaScriptで登録した名前を指定し、スタイルを記述
::highlight()に指定できるCSSプロパティは、colorやbackground-color、text-decorationなど一部に限られます。font-sizeやfont-weightなどは適用されないため注意が必要です。
次回は、CSS Custom Highlight APIを活用した具体例を解説します。