본문 바로가기
Frontend2026년 8월 16일5분 읽기

CSS Custom Highlight API — DOM 안 건드리고 텍스트 하이라이트하기

YS
김영삼
조회 8
CSS Custom Highlight API — DOM 안 건드리고 텍스트 하이라이트하기

CSS Custom Highlight API는 DOM을 건드리지 않고 텍스트의 특정 구간에 색을 입히는 브라우저 기능입니다. Range 객체로 '어디부터 어디까지'를 지정하고, ::highlight() 가상 요소로 그 구간의 스타일을 정합니다. 검색어 하이라이트나 코드 에디터의 문법 강조를 <span> 떡칠 없이 구현할 수 있죠.

이게 반가운 이유가 있습니다. 예전엔 검색어를 노랗게 칠하려고 텍스트를 잘라 <mark>를 끼워 넣었는데, 그러면 이벤트 리스너가 끊기고 텍스트 노드가 쪼개져 골치가 아팠거든요. 이 API는 원본 DOM을 그대로 두고 '위에 덧칠'만 합니다.

세 단계로 끝난다

흐름은 단순합니다. Range를 만들고, Highlight에 담고, 레지스트리에 등록하고, CSS로 칠합니다.

// 1) 강조할 구간을 Range로 표시
const range = new Range();
range.setStart(textNode, 5);
range.setEnd(textNode, 12);
// 2) Highlight 객체에 담기
const hl = new Highlight(range);
// 3) 이름 붙여 레지스트리에 등록
CSS.highlights.set('search', hl);
/* 4) 그 이름으로 스타일 지정 */
::highlight(search) {
  background: var(--color-orange);
  color: #fff;
}

Highlight에 Range를 여러 개 넣을 수 있어서, 검색 결과 12곳을 한 번에 칠하는 것도 간단합니다.

실전: 검색어 전부 칠하기

function highlightAll(root, term) {
  CSS.highlights.delete('search');
  if (!term) return;
  const hl = new Highlight();
  const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT);
  let node;
  while ((node = walker.nextNode())) {
    const text = node.textContent.toLowerCase();
    let i = text.indexOf(term);
    while (i !== -1) {
      const r = new Range();
      r.setStart(node, i);
      r.setEnd(node, i + term.length);
      hl.add(r);
      i = text.indexOf(term, i + term.length);
    }
  }
  CSS.highlights.set('search', hl);
}

보다시피 DOM 구조는 하나도 안 바꿉니다. 지우는 것도 CSS.highlights.delete() 한 줄이면 깔끔합니다. 예전 방식처럼 끼워 넣은 <mark>를 다시 풀어내느라 고생할 일이 없어요.

칠할 수 있는 속성은 제한적

여기가 함정입니다. ::highlight()는 아무 CSS나 먹지 않습니다. 텍스트 '위에 덧칠'하는 개념이라 레이아웃을 바꾸는 속성은 무시됩니다.

되는 것안 되는 것
color, background-colormargin, padding
text-decorationfont-size, display
text-shadowborder(외곽선)

즉 글자 색과 배경, 밑줄 정도로 표현합니다. 박스처럼 테두리를 두르고 싶다면 이 API는 맞지 않습니다.

우선순위도 다룬다

같은 글자에 여러 하이라이트가 겹치면 priority로 순서를 정합니다. 숫자가 클수록 위에 올라갑니다.

const spell = new Highlight(...);
spell.priority = 1;
const sel = new Highlight(...);
sel.priority = 2;  // 선택 강조가 맞춤법 강조 위로

자주 묻는 질문

<mark> 태그랑 비교하면요?

<mark>는 DOM을 실제로 바꿉니다. 텍스트 노드가 쪼개지고 이벤트·선택 영역이 영향을 받죠. Custom Highlight API는 원본을 그대로 두고 렌더링만 덧칠하므로, 자주 바뀌는 하이라이트(검색·커서·문법 강조)에 훨씬 유리합니다.

지원 범위는 어떻게 되나요?

2026년 기준 크로미엄·사파리·파이어폭스 등 모던 브라우저에서 대체로 사용할 수 있습니다. 다만 기능이 없으면 하이라이트만 안 보일 뿐 콘텐츠는 멀쩡하므로, CSS.highlights 존재 여부를 확인해 점진적으로 적용하면 됩니다.

클릭 이벤트도 받을 수 있나요?

하이라이트 자체는 순수 시각 효과라 직접 클릭 대상이 되지 않습니다. 클릭 상호작용이 필요하면 좌표로 caretPositionFromPoint() 등을 써서 어느 구간을 눌렀는지 계산하거나, 상호작용이 핵심이면 실제 요소를 쓰는 편이 낫습니다.

댓글 0

아직 댓글이 없습니다.
Ctrl+Enter로 등록