Existe um seletor de CSS para elementos contendo determinado texto?

Estou procurando um seletor de CSS para a tabela a seguir:

Peter | male | 34 Susanne | female | 12 

Existe algum seletor para combinar todos os TDs contendo “macho”?

Se eu ler a especificação corretamente, não.

Você pode combinar em um elemento, o nome de um atributo no elemento e o valor de um atributo nomeado em um elemento. Eu não vejo nada para correspondência de conteúdo dentro de um elemento, no entanto.

Usando jQuery:

 $('td:contains("male")') 

Parece que eles estavam pensando sobre isso para as especificações CSS3, mas não foi feito .

:contains() seletor CSS3 http://www.w3.org/TR/css3-selectors/#content-selectors

Você teria que adicionar um atributo de dados às linhas chamadas data-gender com um valor male ou female e usar o seletor de atributos:

HTML:

 ... 

CSS:

 td[data-gender="male"] { ... } 

Na verdade, existe uma base muito conceitual para o motivo pelo qual isso não foi implementado. É uma combinação de basicamente 3 aspectos:

  1. O conteúdo de texto de um elemento é efetivamente um filho desse elemento
  2. Você não pode segmentar o conteúdo de texto diretamente
  3. CSS não permite ascensão com seletores

Esses três juntos significam que, quando você tiver o conteúdo do texto, não poderá ascender ao elemento que o contém e não poderá estilizar o texto atual. Isso é provavelmente significativo, pois a descida só permite um acompanhamento singular do contexto e da análise de estilo SAX. Os seletores ascendentes ou outros que envolvem outros eixos introduzem a necessidade de soluções de passagem ou similares mais complexas que complicariam muito a aplicação do CSS no DOM.

Você pode definir o conteúdo como atributo de dados e usar seletores de atributo

 /* Select every cell containing word "male" */ td[data-content="male"] { color: red; } /* Select every cell starting on "p" case insensitive */ td[data-content^="p" i] { color: blue; } /* Select every cell containing "4" */ td[data-content*="4"] { color: green; } 
 
Peter male 34
Susanne female 14

Para aqueles que estão procurando seleções de texto CSS Selenium, este script pode ser de alguma utilidade.

O truque é selecionar o pai do elemento que você está procurando e, em seguida, procurar o filho que tem o texto:

 public static IWebElement FindByText(this IWebDriver driver, string text) { var list = driver.FindElement(By.CssSelector("#RiskAddressList")); var element = ((IJavaScriptExecutor)driver).ExecuteScript(string.Format(" var x = $(arguments[0]).find(\":contains('{0}')\"); return x;", text), list); return ((System.Collections.ObjectModel.ReadOnlyCollection)element)[0]; } 

Isso retornará o primeiro elemento se houver mais de um, pois é sempre um elemento, no meu caso.

Como o CSS não possui esse recurso, você terá que usar o javascript para estilizar as células pelo conteúdo. Por exemplo, com xpath contém

 var elms = document.evaluate( "//td[contains(., 'male')]" ,node, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null ) 

Então use o resultado da seguinte forma:

 for ( var i=0 ; i < elms.snapshotLength; i++ ){ elms.snapshotItem(i).style.background = "pink"; } 

https://jsfiddle.net/gaby_de_wilde/o7bka7Ls/9/

Temo que isso não seja possível, porque o conteúdo não é um atributo nem é acessível por meio de uma pseudo-class. A lista completa de seletores CSS3 pode ser encontrada na especificação CSS3 .

A resposta do @ voyager sobre o uso do atributo data-* (por exemplo, data-gender="female|male" é a abordagem mais eficaz e compatível com os padrões a partir de 2017:

 [data-gender='male'] {background-color: #000; color: #ccc;} 

Quase todos os objectives podem ser alcançados, pois há alguns seletores limitados, orientados em torno do texto. A primeira letra é um pseudoelemento que pode aplicar um estilo limitado à primeira letra de um elemento. Há também um pseudoelemento :: first-line , além de obviamente selecionar a primeira linha de um elemento (como um parágrafo) também implica que é óbvio que o CSS poderia ser usado para estender essa capacidade existente para estilizar aspectos específicos de um textNode .

Até que tal defesa seja bem sucedida e implementada, a próxima melhor coisa que eu poderia sugerir quando aplicável é explode / split palavras usando um delineador de espaço, gerar cada palavra individual dentro de um elemento span e então se a meta de palavra / estilo for previsível, use em combinação com : nth seletores :

 $p = explode(' ',$words); foreach ($p as $key1 => $value1) { echo ''.$value1.'; } 

Senão, se não for previsível , use novamente a resposta do viajante sobre o uso do atributo data-* . Um exemplo usando PHP:

 $p = explode(' ',$words); foreach ($p as $key1 => $value1) { echo ''.$value1.'; } 

Eu concordo que o atributo de dados (resposta do viajante) é como ele deve ser tratado, MAS, regras de CSS como:

 td.male { color: blue; } td.female { color: pink; } 

muitas vezes pode ser muito mais fácil de configurar, especialmente com bibliotecas do lado do cliente, como o angularjs, que podem ser tão simples quanto:

  

Apenas certifique-se que o conteúdo é apenas uma palavra! Ou você pode até mapear para diferentes nomes de classs CSS com:

  

Para completar, aqui está a abordagem do atributo de dados:

  

A maioria das respostas aqui tenta oferecer alternativas a como escrever o código HTML para include mais dados, porque pelo menos até o CSS3 você não pode selecionar um elemento pelo texto interno parcial. Mas isso pode ser feito, você só precisa adicionar um pouco de baunilha JavaScript, observe que o feminino também contém macho que será selecionado:

  cells = document.querySelectorAll('td'); console.log(cells); [].forEach.call(cells, function (el) { if(el.innerText.indexOf("male") !== -1){ //el.click(); click or any other option console.log(el) } }); 
  
Peter male 34
Susanne female 14

Se você está usando o Chimp / Webdriver.io , eles suportam muito mais seletores CSS do que a especificação CSS.

Isso, por exemplo, clicará na primeira âncora que contenha as palavras “Urso ruim”:

 browser.click("a*=Bad Bear");