
Abordagens Principais para Destaque de Texto
Destacar texto pode parecer simples à primeira vista—apenas mudar o fundo para amarelo—mas na verdade é bastante complexo. Veja este exemplo abaixo, onde a parte destacada abrange múltiplos elementos e contém texto parcial de elementos abaixo.
A seguir, vou percorrer várias abordagens comuns para implementar destaque de texto, discutindo seus prós e contras junto com casos de uso práticos para delinear as principais soluções técnicas.
CSS Highlight API — Destaque de Texto Moderno e Eficiente
Esta é atualmente a melhor escolha para implementar destaque de texto, sendo simples de usar e performante. A única desvantagem é que os navegadores precisam de versões relativamente recentes para suporte, embora em 2025 todos os navegadores principais já o suportem.
Objeto Highlight
Primeiro, você precisa criar um objeto Range
para cada área destacada. Range é uma API de longa data que representa uma seção contínua na árvore DOM—se você não estiver familiarizado com ela, precisará estudá-la.
const range = new Range();
range.setStart(someNode, startOffset);
range.setEnd(someNode, endOffset);
Então adicione-o a um objeto Highlight
. Como o destaque pode ter múltiplas áreas não contíguas, um único objeto Highlight
pode conter vários Ranges.
const highlight = new Highlight(range1, range2, ..., rangeN);
É similar a um objeto Set, então você pode usar métodos como add
, delete
, etc., para modificar os Ranges contidos.
CSS.highlights
Então adicione o objeto Highlight ao CSS.highlights
. É similar a um objeto Map, com métodos para adicionar e remover membros como get
, set
, delete
, etc., e os mesmos métodos de iteração.
Assim como um Map, ao adicionar um Highlight, você precisa dar-lhe uma chave como nome do highlight. Este nome é muito útil—como veremos abaixo, usamos este nome para definir o estilo de destaque, como um fundo verde. Então todos os destaques no mesmo objeto Highlight têm o mesmo estilo. Se você quiser destacar outro pedaço de texto em azul, precisará criar um novo highlight.
CSS.highlights.set("my-highlight", highlight);
Definindo o Pseudo-elemento ::highlight
A seguir, os estilos CSS entram em cena. Você pode definir estilos de destaque usando o pseudo-elemento ::highlight(nome-do-highlight)
.
::highlight(my-highlight) {
background-color: yellow;
color: black;
}
Nota: Apenas algumas propriedades CSS podem ser usadas, como
background-color
,color
,cursor
, etc. Veja a especificação para detalhes.
Modificando Dinamicamente os Intervalos de Destaque
CSS.highlights
é como um Map com métodos similares para atualizar Highlights:
CSS.highlights.clear()
set(highlightName, Highlight)
delete(highlightName)
O objeto Highlight
é como um Set com métodos similares para atualizar Ranges:
Highlight.add(range)
delete(range)
Modificando Estilos de Elementos de Texto
Alcance o destaque percorrendo o DOM para encontrar nós de texto alvo e modificando diretamente seus estilos de fundo.
- Requer modificações do DOM, causando reflow do navegador com sobrecarga significativa de performance.
- Implementar destaque entre elementos (onde o intervalo de destaque abrange múltiplos elementos) é bastante complexo.
- Adequado para cenários onde o conteúdo destacado é relativamente fixo e o intervalo é pequeno.
Sobrepondo Camadas Adicionais para Renderizar Destaques Sem Modificar o DOM do Texto
Crie uma camada de sobreposição transparente, calcule a posição na tela do texto alvo, então desenhe destaques semi-transparentes na sobreposição.
Posicionando Áreas de Destaque
- Use
Element.getClientRects()
ougetBoundingClientRect()
para obter coordenadas do texto na página. - Ao lidar com texto de múltiplas linhas, cada linha corresponde a uma área retangular que precisa de blocos de destaque separados.
- Mudanças no tamanho da janela ou tamanho da fonte requerem recálculo das posições de destaque, o que pode impactar a performance.
Métodos de Desenho de Destaque
DIV como Sobreposição
Use contêineres pai com posicionamento absoluto e elementos filho com fundo semi-transparente para sobrepor texto. Por exemplo, o editor Monaco usa esta abordagem para implementar destaque de palavras iguais.
<div class="editor" style="position: relative;">
<div class="overlay" style="position: absolute; height: 0;">
<div
class="highlight"
style="top:0; left:57px; width:23px; background-color: rgba(173,214,255,0.15);"
></div>
<!-- Adicionar mais áreas de highlight -->
</div>
<div class="content">
<!-- Conteúdo de texto -->
</div>
</div>
- A posição do overlay é absolute, enquanto garante que o elemento pai não seja
position: static
, para que o posicionamento absoluto funcione. Isso permite que elementos de destaque internos sejam posicionados em qualquer lugar. - Para colocar acima do texto, simplesmente coloque o overlay antes do contêiner de texto no HTML. A altura do overlay é 0 para evitar afetar a interação com o texto abaixo.
- Adicione elementos dentro, defina
background-color
para a cor de destaque semi-transparente, posicione na localização do texto destacado e defina a largura. - O editor Monaco (VSCode é baseado nele) usa este método. Veja a demo oficial. Após selecionar uma palavra-chave, as mesmas palavras-chave são destacadas. Olhando o HTML, você encontrará que essas palavras-chave não mudaram estilos, mas há um Overlay na interface do editor com cores de destaque semi-transparentes desenhadas dentro (veja a div com
class="view-overlays"
).
SVG como Sobreposição
- Defina overlay com as mesmas dimensões da página
- Adicione
<rect>
dentro, então desenhe nas posições do texto destacado - foliate-js usa este método. Veja overlayer.js.
Usando Selection API e Pseudo-elemento ::selection — Destaque de Seleção de Texto Padrão do Navegador
Navegadores naturalmente destacam texto selecionado, então controlar a seleção pode indiretamente alcançar destaque. Estilos podem ser personalizados através do pseudo-elemento ::selection
do CSS.
const range = new Range();
range.setStart(parentNode, startOffset);
range.setEnd(parentNode, endOffset);
// Definir seleção
const selection = document.getSelection();
selection.removeAllRanges();
selection.addRange(range);
::selection {
background-color: #c3c2c2;
color: white;
}
Este método é bastante inteligente, simples e tem amplo suporte do navegador, mas tem uma grande desvantagem: já que apenas uma seleção pode existir por vez, seleções programáticas e seleções reais do usuário entrarão em conflito e se sobrescreverão mutuamente. Portanto, é adequado apenas para cenários que atendem às seguintes condições:
- Usuários não podem selecionar texto
- Há apenas um segmento de texto destacado contínuo
- Você precisa suportar navegadores mais antigos
- Você quer ser preguiçoso e evitar outros métodos