Como Encontrar Elementos DOM por Texto
Não existe getElementByText() na API DOM. Se você precisa localizar um elemento com base no que ele diz em vez do que ele é, você terá que construir essa capacidade por conta própria. Isso surge com mais frequência do que você imagina — scripts de automação, testes de UI, análise de conteúdo dinâmico — e a abordagem correta depende de quanta flexibilidade você precisa.
Principais Conclusões
- A API DOM não possui um método nativo para selecionar elementos por conteúdo de texto, mas três abordagens nativas preenchem essa lacuna: filtragem com
querySelectorAll, travessia comTreeWalkere consulta com XPath. TreeWalkeré a opção nativa mais versátil para buscas completas de texto no DOM em qualquer tipo de elemento sem coletar uma grande NodeList antecipadamente.- Prefira
textContentem vez deinnerTextpara correspondência de texto — é mais rápido, evita acionar o recálculo de layout e se comporta de forma consistente independentemente da visibilidade do elemento. - Fique atento a armadilhas comuns como espaços em branco extras, texto de descendentes aninhados e conteúdo injetado dinamicamente que pode não estar presente quando seu script for executado.
Por Que querySelector Não Pode Consultar o DOM por Conteúdo de Texto
querySelector() e querySelectorAll() aceitam apenas seletores CSS. Embora o CSS tenha uma pseudo-classe :has() e seletores de atributo, não existe um seletor CSS padrão para corresponder ao conteúdo de texto de um elemento. Seletores como div:text("Submit") simplesmente não existem na especificação.
Isso deixa você com três abordagens práticas: filtrar um conjunto de candidatos, percorrer o DOM com uma API nativa ou usar XPath.
Método 1: Filtrar um Conjunto de Candidatos por Texto
A abordagem mais simples é consultar elementos por tag ou classe e depois filtrar por texto. Isso funciona bem quando você conhece o tipo de elemento antecipadamente.
function findByText(tag, text) {
return [...document.querySelectorAll(tag)].filter(el =>
el.textContent.trim() === text
)
}
// Uso
const buttons = findByText('button', 'Submit')
Isso é legível e rápido quando o conjunto de candidatos é pequeno. A fraqueza: pesquisa apenas um tipo de elemento por vez. Pesquisar todos os elementos com '*' funciona, mas é mais lento em DOMs grandes.
Método 2: Percorrer o DOM com TreeWalker
TreeWalker é uma API DOM nativa que permite percorrer nós de forma eficiente. É bem suportada em todos os navegadores modernos e evita a sobrecarga de coletar uma NodeList completa antecipadamente.
function findElementsByText(root, text) {
const walker = document.createTreeWalker(
root,
NodeFilter.SHOW_ELEMENT,
{
acceptNode(node) {
return node.textContent.trim() === text
? NodeFilter.FILTER_ACCEPT
: NodeFilter.FILTER_SKIP
}
}
)
const results = []
while (walker.nextNode()) results.push(walker.currentNode)
return results
}
// Uso
const matches = findElementsByText(document.body, 'TV')
Isso pesquisa qualquer tipo de elemento em toda a árvore — uma solução genérica que a abordagem específica por tag não pode fornecer. Também suporta término antecipado se você precisar apenas da primeira correspondência.
Nota sobre
FILTER_SKIPvs.FILTER_REJECT: UsarFILTER_SKIPaqui significa que o walker ainda desce para os filhos de um nó que não corresponde. Se você usasseFILTER_REJECT, o walker pularia o nó e toda a sua subárvore. Para busca de texto,FILTER_SKIPé quase sempre o que você quer, já que otextContentde um pai pode não corresponder mesmo que um descendente mais profundo corresponda.
Discover how at OpenReplay.com.
Método 3: Busca de Texto XPath no DOM
Para correspondência mais expressiva, document.evaluate() suporta expressões XPath, incluindo consultas baseadas em texto. Esta é a opção mais poderosa para padrões complexos.
function findByXPath(expression, context = document) {
const result = document.evaluate(
expression,
context,
null,
XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,
null
)
return Array.from({ length: result.snapshotLength }, (_, i) =>
result.snapshotItem(i)
)
}
// Encontrar qualquer elemento contendo o texto "Submit"
const els = findByXPath('//*[contains(text(), "Submit")]')
A busca de texto XPath no DOM lida com correspondências parciais e condições complexas de forma limpa. O compromisso é a legibilidade — a sintaxe XPath não é familiar para a maioria dos desenvolvedores frontend.
Uma coisa a ter em mente: contains(text(), "Submit") corresponde apenas aos nós de texto diretos do elemento. Se “Submit” estiver dentro de um elemento filho, essa expressão não corresponderá ao pai. Para pesquisar em todo o texto descendente, use contains(., "Submit"), onde . refere-se ao valor de string do elemento inteiro, incluindo seus descendentes.
textContent vs. innerText: Qual Usar para Correspondência
Ambas as propriedades retornam texto, mas se comportam de forma diferente:
| Propriedade | Retorna | Aciona Layout? |
|---|---|---|
textContent | Texto bruto do DOM, incluindo elementos ocultos | Não |
innerText | Apenas texto renderizado | Sim (reflow) |
Use textContent para correspondência de texto. É mais rápido, não aciona recálculo de layout e funciona consistentemente em todos os elementos, independentemente da visibilidade.
Armadilhas Comuns ao Encontrar Elementos DOM por Texto
Espaços em branco: textContent inclui espaços em branco da formatação HTML. Sempre use .trim() antes de comparar.
Texto aninhado: O textContent de um elemento inclui todo o texto descendente. <div><span>TV</span></div> — o textContent da div também é "TV". Seja específico sobre qual nível de elemento você está segmentando.
Conteúdo dinâmico: Texto injetado após o carregamento da página não estará presente quando seu script for executado. Use um MutationObserver ou execute sua busca após confirmar que o conteúdo existe.
Escolhendo a Abordagem Certa
- Tipo de elemento conhecido, correspondência simples → filtrar com
querySelectorAll - Qualquer tipo de elemento, busca completa no DOM →
TreeWalker - Correspondência parcial ou padrão complexo → XPath via
document.evaluate()
Se você está trabalhando em um contexto de testes, ferramentas como Testing Library fornecem getByText() integrado — vale a pena saber, embora as técnicas nativas acima permaneçam essenciais para scripts que não são de teste.
Conclusão
A busca no DOM baseada em texto é uma lacuna na API padrão, mas essas três abordagens cobrem todos os casos práticos. Use querySelectorAll com um filtro para buscas rápidas e direcionadas quando você conhece o tipo de elemento. Recorra ao TreeWalker quando precisar de uma travessia completa do DOM sem se comprometer com uma tag específica. Recorra ao XPath quando a lógica de correspondência exigir texto parcial ou condições complexas. Qualquer que seja o método escolhido, prefira textContent em vez de innerText, remova espaços em branco antes de comparar e considere o texto de descendentes aninhados para evitar correspondências falsas.
Perguntas Frequentes
Não. querySelector e querySelectorAll aceitam apenas seletores CSS, e o CSS não tem seletor para corresponder ao conteúdo de texto. Você precisa usar abordagens baseadas em JavaScript, como filtrar um conjunto de resultados de querySelectorAll, percorrer o DOM com TreeWalker ou executar uma expressão XPath com document.evaluate para localizar elementos pelo que eles contêm.
FILTER_SKIP diz ao TreeWalker para pular o nó atual, mas ainda visitar seus filhos. FILTER_REJECT pula o nó e toda a sua subárvore. Para buscas baseadas em texto, FILTER_SKIP geralmente é a escolha certa porque um pai pode não corresponder enquanto um descendente mais profundo corresponde.
Não. A expressão contains(text(), value) verifica apenas os nós de texto diretos do elemento. Se a string alvo estiver dentro de um elemento filho aninhado, use contains(., value). O operador ponto refere-se ao valor de string completo do elemento, incluindo todo o texto descendente.
textContent é mais rápido porque não aciona um reflow de layout. Retorna todo o texto na subárvore do DOM, independentemente da visibilidade CSS, tornando-o consistente e previsível. innerText retorna apenas texto renderizado e força o navegador a recalcular o layout, o que adiciona sobrecarga desnecessária para fins de correspondência.
Complete picture for complete understanding
Capture every clue your frontend is leaving so you can instantly get to the root cause of any issue with OpenReplay — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data.
Check our GitHub repo and join the thousands of developers in our community.