기존 텍스트 하이라이트 방식의 문제:
<span class="highlight"> 같은 래퍼 요소를 삽입해야 했음Custom Highlight API는 DOM을 건드리지 않고도 텍스트 범위를 정확하게 스타일링할 수 있게 해주는 해결책.
사용 순서:
[Range Objects] → [Highlight] → [CSS.highlights Registry] → CSS ::highlight()
const parentNode = document.getElementById("foo");
const range1 = new Range();
range1.setStart(parentNode, 10);
range1.setEnd(parentNode, 20);
const range2 = new Range();
range2.setStart(parentNode, 40);
range2.setEnd(parentNode, 60);
const highlight = new Highlight(range1, range2);
const user1Highlight = new Highlight(user1Range1, user1Range2);
const user2Highlight = new Highlight(user2Range1, user2Range2, user2Range3);
CSS.highlights.set("user-1-highlight", user1Highlight);
CSS.highlights.set("user-2-highlight", user2Highlight);
CSS.highlights.delete("user-1-highlight");
CSS.highlights.clear();
::highlight(user-1-highlight) {
background-color: yellow;
color: black;
}
CSS.highlights)목표: 입력한 검색어와 일치하는 텍스트를 하이라이트
<label>Search within text <input id="query" type="text" /></label>
<article>
<!-- paragraphs... -->
</article>
const article = document.querySelector("article");
const treeWalker = document.createTreeWalker(article, NodeFilter.SHOW_TEXT);
const allTextNodes = [];
let currentNode = treeWalker.nextNode();
while (currentNode) {
allTextNodes.push(currentNode);
currentNode = treeWalker.nextNode();
}
query.addEventListener("input", () => {
if (!CSS.highlights) return;
CSS.highlights.clear();
const str = query.value.trim().toLowerCase();
if (!str) return;
const ranges = allTextNodes
.map((el) => ({ el, text: el.textContent.toLowerCase() }))
.map(({ text, el }) => {
const indices = [];
let startPos = 0;
while (startPos < text.length) {
const index = text.indexOf(str, startPos);
if (index === -1) break;
indices.push(index);
startPos = index + str.length;
}
return indices.map((index) => {
const range = new Range();
range.setStart(el, index);
range.setEnd(el, index + str.length);
return range;
});
});
const searchResultsHighlight = new Highlight(...ranges.flat());
CSS.highlights.set("search-results", searchResultsHighlight);
});
::highlight(search-results) {
background-color: #ff0066;
color: white;
}
→ 검색어 입력 즉시 DOM 구조 변경 없이 깔끔한 하이라이트 기능 제공.
| 브라우저 | 지원 |
|---|---|
| Chrome 105+ | ✔ |
| Edge 105+ | ✔ |
| Firefox 140+ | ✔ |
| Safari 17.2+ | ✔ |
| iOS Safari 17.2+ | ✔ |
| Android Chrome 105+ | ✔ |