web-dev-qa-db-fra.com

Existe-t-il un sélecteur CSS pour les éléments contenant du texte?

Je recherche un sélecteur CSS pour le tableau suivant:

Peter    | male    | 34
Susanne  | female  | 12

Y at-il un sélecteur pour faire correspondre tous les TD contenant "mâle"?

376
jantimon

Si je lis la spécification correctement, non. 

Vous pouvez faire correspondre un élément, le nom d'un attribut dans l'élément et la valeur d'un attribut nommé dans un élément. Je ne vois cependant rien pour faire correspondre le contenu d'un élément.

286
Dean J

Utilisation de jQuery: 

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

On dirait qu'ils y pensaient pour la spécification CSS3 mais cela n'a pas fait la différence.

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

119
Jeff Beaman

Vous devez ajouter un attribut de données aux lignes appelé data-gender avec une valeur male ou female et utiliser le sélecteur d'attribut:

HTML:

<td data-gender="male">...</td>

CSS:

td[data-gender="male"] { ... }
92
Esteban Küber

Il existe en fait une base très conceptuelle pour expliquer pourquoi cela n'a pas été mis en œuvre. C'est une combinaison de 3 aspects principaux:

  1. Le contenu textuel d'un élément est effectivement un enfant de cet élément
  2. Vous ne pouvez pas cibler directement le contenu du texte
  3. CSS ne permet pas l'ascension avec des sélecteurs

Ces 3 ensemble signifient que lorsque vous avez le contenu du texte, vous ne pouvez plus remonter à l'élément qui le contient et vous ne pouvez pas styliser le texte actuel. Ceci est probablement significatif car décroissant ne permet qu'un suivi singulier du contexte et de l'analyse syntaxique de style SAX. Les sélecteurs ascendants ou autres impliquant d'autres axes impliquent le besoin de solutions de traversée plus complexes ou de solutions similaires qui compliqueraient grandement l'application de CSS au DOM.

59
Matt Whipple

Vous pouvez définir le contenu en tant qu'attribut de données, puis utiliser sélecteurs d'attributs , comme indiqué ici:

/* 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;
}
<table>
  <tr>
    <td data-content="Peter">Peter</td>
    <td data-content="male">male</td>
    <td data-content="34">34</td>
  </tr>
  <tr>
    <td data-conten="Susanne">Susanne</td>
    <td data-content="female">female</td>
    <td data-content="14">14</td>
  </tr>
</table>

Vous pouvez également utiliser jQuery pour définir facilement les attributs de contenu de données:

$(function(){
  $("td").each(function(){
    var $this = $(this);
    $this.attr("data-content", $this.text());
  });
});
20
Buksy

Comme CSS ne dispose pas de cette fonctionnalité, vous devrez utiliser javascript pour styliser les cellules en fonction du contenu. Par exemple, avec xpath contient

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

Ensuite, utilisez le résultat comme suit:

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

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

4
user40521

Pour ceux qui cherchent à faire des sélections de texte Selenium CSS, ce script pourrait être utile.

L'astuce consiste à sélectionner le parent de l'élément que vous recherchez, puis à rechercher l'enfant qui contient le texte: 

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<IWebElement>)element)[0];
}

Cela renverra le premier élément s'il y en a plus d'un puisqu'il s'agit toujours d'un élément, dans mon cas.

4
Matas Vaitkevicius

Je crains que cela ne soit pas possible, car le contenu n'est pas un attribut et n'est pas accessible via une pseudo-classe. La liste complète des sélecteurs CSS3 se trouve dans la spécification CSS3 .

4
Edwin V.

Je suis d'accord l'attribut data (réponse du voyageur) est la façon dont il devrait être traité, MAIS, des règles CSS telles que 

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

peut souvent être beaucoup plus facile à configurer, en particulier avec des bibliothèques côté client comme angularjs, qui pourraient être aussi simples que:

<td class="{{person.gender}}">

Assurez-vous simplement que le contenu n'est qu'un mot! Vous pouvez également mapper des noms de classes CSS différents avec:

<td ng-class="{'masculine': person.isMale(), 'feminine': person.isFemale()}">

Pour être complet, voici l'approche des attributs de données:

<td data-gender="{{person.gender}}">
2
DJDaveMark

Vous pouvez également utiliser content avec attr() et les cellules de table de style qui sont :not:empty :

th::after { content: attr(data-value) }
td::after { content: attr(data-value) }
td[data-value]:not(:empty) {
  color: Fuchsia;
}
<table>
  <tr>
    <th data-value="Peter"></th>
    <td data-value="male">&#x0200B;</td>
    <td data-value="34"></td>
  </tr>
  <tr>
    <th data-value="Susanne"></th>
    <td data-value="female"></td>
    <td data-value="12"></td>
  </tr>
  <tr>
    <th data-value="Lucas"></th>
    <td data-value="male">&#x0200B;</td>
    <td data-value="41"></td>
  </tr>
</table>

Un ZeroWidthSpace est utilisé pour modifier la couleur et peut être ajouté à l'aide de JavaScript Vanille:

const hombres = document.querySelectorAll('td[data-value="male"]');
hombres.forEach(hombre => hombre.innerHTML = '&#x0200B;');

Bien que la balise de fin <td>s peut être omise cela peut entraîner son traitement comme non vide.

1
Josh Habdas

La syntaxe de cette question ressemble à la syntaxe Robot Framework. Dans ce cas, bien qu’il n’y ait pas de sélecteur css que vous puissiez utiliser pour les contenus, vous pouvez utiliser un mot-clé SeleniumLibrary. Le Attendre que l'élément contienne .

Exemple:

Wait Until Element Contains  | ${element} | ${contains}
Wait Until Element Contains  |  td | male
0
Eftychia Thomaidou

La plupart des réponses ici tentent d’offrir une alternative à la façon d’écrire le code HTML pour inclure plus de données car au moins jusqu’à CSS3, vous ne pouvez pas sélectionner un élément avec un texte interne partiel. Mais cela peut être fait, il vous suffit d’ajouter un peu de JavaScript Vanille, remarquez que puisque la femme contient aussi un homme, il sera sélectionné:

      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)
    	}
    });
 <table>
      <tr>
        <td>Peter</td>
        <td>male</td>
        <td>34</td>
      </tr>
      <tr>
        <td>Susanne</td>
        <td>female</td>
        <td>14</td>
      </tr>
    </table>

<table>
  <tr>
    <td data-content="Peter">Peter</td>
    <td data-content="male">male</td>
    <td data-content="34">34</td>
  </tr>
  <tr>
    <td data-conten="Susanne">Susanne</td>
    <td data-content="female">female</td>
    <td data-content="14">14</td>
  </tr>
</table>
0
Eduard Florinescu

Si vous utilisez Chimp / Webdriver.io , ils prennent en charge beaucoup plus de sélecteurs CSS que la spécification CSS. 

Ceci, par exemple, cliquera sur la première ancre contenant les mots "Mauvais ours":

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