Back

CSS Custom Highlight APIを使用したテキストのスタイリング

CSS Custom Highlight APIを使用したテキストのスタイリング

CSS Custom Highlight APIは根本的な問題を解決します:DOMにラッパー要素を散らかすことなく、プログラムでテキスト範囲をハイライトする方法です。検索インターフェース、テキストエディタ、教育アプリを構築している場合、このAPIは従来の<mark>やspan要素ベースの手法よりも、よりクリーンで高性能なアプローチを提供します。

要点

  • CSS Custom Highlight APIはDOM操作なしでテキストハイライトを可能にします
  • ハイライトはRangeオブジェクト、Highlightオブジェクト、CSS.highlightsレジストリを通じて動作します
  • レイアウトの再計算が発生しないため、パフォーマンスが大幅に向上します
  • 複数の非連続範囲を同時にハイライトできます

CSS Custom Highlight APIの違い

従来のテキストハイライトはDOM構造の変更を必要とします。<mark>要素やspanを使用することは、ノードの挿入、レイアウト再計算のトリガー、そしてハイライトが複数の要素にまたがる場合の複雑なHTML管理を意味します。CSS Custom Highlight APIは、JavaScriptの範囲と::highlight疑似要素を使用することで、DOMを汚すことなくこれらの問題を解決します。

このAPIは3つの核となるコンポーネントで構成されています:

  • テキストの境界を定義するRangeオブジェクト
  • 範囲をグループ化するHighlightオブジェクト
  • ハイライトをスタイルに接続するCSS.highlightsレジストリ

テキスト範囲の作成とスタイリング

最初のハイライトの構築

まず、ハイライトするテキストを定義するRangeオブジェクトを作成します:

const range = new Range();
const textNode = document.querySelector('p').firstChild;
range.setStart(textNode, 0);
range.setEnd(textNode, 20);

次に、Highlightオブジェクトを作成して登録します:

const highlight = new Highlight(range);
CSS.highlights.set('my-highlight', highlight);

最後に、::highlight疑似要素でスタイルを設定します:

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

検索結果ハイライトの実装

ドキュメント全体で検索結果をハイライトする実用的な例を以下に示します:

function highlightSearchResults(searchTerm) {
  // 既存のハイライトをクリア
  CSS.highlights.delete('search-results');
  
  const walker = document.createTreeWalker(
    document.body,
    NodeFilter.SHOW_TEXT
  );
  
  const ranges = [];
  let node;
  
  while (node = walker.nextNode()) {
    const text = node.textContent;
    const regex = new RegExp(searchTerm, 'gi');
    let match;
    
    while (match = regex.exec(text)) {
      const range = new Range();
      range.setStart(node, match.index);
      range.setEnd(node, match.index + searchTerm.length);
      ranges.push(range);
    }
  }
  
  if (ranges.length > 0) {
    const searchHighlight = new Highlight(...ranges);
    CSS.highlights.set('search-results', searchHighlight);
  }
}

高度なパターン:マルチ範囲ハイライト

真の力は、複数の非連続テキスト範囲を扱う際に現れます。単一のHighlightオブジェクトは複数のRangeオブジェクトを含むことができます:

// 複数の別々の段落をハイライト
const range1 = new Range();
range1.selectNodeContents(document.querySelector('#intro'));

const range2 = new Range();
range2.selectNodeContents(document.querySelector('#conclusion'));

const highlight = new Highlight(range1, range2);
CSS.highlights.set('important-sections', highlight);

複数のハイライトグループを同時に管理することも可能です:

// 異なるスタイルを持つ異なるハイライトタイプ
CSS.highlights.set('errors', new Highlight(...errorRanges));
CSS.highlights.set('warnings', new Highlight(...warningRanges));
CSS.highlights.set('info', new Highlight(...infoRanges));
::highlight(errors) {
  background-color: #fee;
  text-decoration: wavy underline red;
}

::highlight(warnings) {
  background-color: #ffa;
}

::highlight(info) {
  background-color: #e6f3ff;
}

パフォーマンスの利点とブラウザサポート

CSS Custom Highlight APIは、パフォーマンスが重要なシナリオで優秀な性能を発揮します。DOM操作とは異なり、ハイライトはレイアウトの再計算をトリガーせず、追加要素によるメモリオーバーヘッドも発生させません。ブラウザのレンダリングエンジンは、ペイントレイヤーでハイライトを処理するため、更新が非常に高速です。

2025年現在、Chrome、Edge、SafariがこのAPIをサポートしており、Firefoxのサポートは開発中です。古いブラウザでは、機能検出によるフォールバックを実装してください:

if ('CSS' in window && 'highlights' in CSS) {
  // Custom Highlight APIを使用
  const highlight = new Highlight(range);
  CSS.highlights.set('fallback-safe', highlight);
} else {
  // 従来のアプローチにフォールバック
  const span = document.createElement('span');
  span.className = 'highlight';
  range.surroundContents(span);
}

実用的な実装のヒント

本番環境でテキストハイライトを実装する際は:

  1. 使用されていないハイライトをクリーンアップしてメモリリークを防ぎます:

    CSS.highlights.delete('old-highlight');
  2. 動的コンテンツを処理するため、DOM変更時に範囲を更新します:

    highlight.add(newRange);
    highlight.delete(oldRange);
  3. 意味のあるハイライト名を使用して、その目的を説明します(例:‘search-results’、‘spell-check’、‘user-annotations’)

まとめ

CSS Custom Highlight APIは、ウェブでのテキストハイライトのアプローチを変革します。ハイライトロジックをDOM構造から分離することで、従来の手法よりも優れたパフォーマンス、よりクリーンなコード、そしてより多くの柔軟性を提供します。次のプロジェクトでハイライトテキスト範囲を試してみてください—ユーザー(そしてあなたのDOM)に感謝されるでしょう。

よくある質問

はい、このAPIは複数の要素にまたがるテキストをハイライトできます。Rangeオブジェクトは一つの要素で開始し、別の要素で終了することができるため、段落やspan要素の境界を越えるフレーズのハイライトに最適です。

ハイライトは元のRangeオブジェクトに付随したままです。DOMが変更された場合、範囲を手動で更新または再作成する必要があります。このAPIはDOM変更を自動的に追跡しないため、動的コンテンツには独自のオブザーバーパターンを実装してください。

複数のハイライトが同じテキスト範囲に重複できます。ブラウザは一致するすべてのハイライトスタイルを適用し、後で定義されたスタイルが優先されます。background-colorやopacityなどのCSSプロパティを通じて視覚的な重ね合わせを制御できます。

Truly understand users experience

See every user interaction, feel every frustration and track all hesitations with OpenReplay — the open-source digital experience platform. It can be self-hosted in minutes, giving you complete control over your customer data. . Check our GitHub repo and join the thousands of developers in our community..

OpenReplay