是否有包含某些文本的元素的CSS选择器?

我正在为下表寻找CSS选择器:

Peter    | male    | 34
Susanne  | female  | 12

是否有任何选择器来匹配所有包含“男性”的TD?

1077241 次浏览

如果我正确阅读的规范,没有。

您可以匹配元素、元素中属性的名称以及元素中命名属性的值。不过,我没有看到任何用于匹配元素中内容的内容。

恐怕这是不可能的,因为内容没有属性,也不能通过伪类访问。CSS3选择器的完整列表可以在CSS3规范中找到。

您必须使用malefemale值向名为data-gender的行添加数据属性,并使用属性选择器:

超文本标记语言:

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

css:

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

看起来他们正在为CSS3规范但没能晋级考虑它。

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

使用jQuery:

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

实际上,这是一个非常概念性的基础,为什么没有实施。它基本上是三个方面的结合:

  1. 元素的文本内容实际上是该元素的子元素
  2. 您不能直接定位文本内容
  3. CSS不允许使用选择器进行提升

这三者结合在一起意味着当你拥有文本内容时,你不能升序回包含元素,也不能为当前文本设置样式。这可能很重要,因为降序只允许对上下文和SAX样式解析进行单一跟踪。升序或其他涉及其他轴的选择器引入了对更复杂遍历或类似解决方案的需求,这将大大复杂化CSS对DOM的应用。

对于那些正在寻找Selenium CSS文本选择的人来说,这个脚本可能会有一些用处。

技巧是选择您要查找的元素的父元素,然后搜索具有文本的子元素:

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];
}

如果有多个元素,这将返回第一个元素,因为在我的例子中,它总是一个元素。

由于CSS缺乏此功能,您将不得不使用JavaScript按内容设置单元格的样式。例如XPath的contains

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

然后像这样使用结果:

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

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

您可以将内容设置为数据属性,然后使用属性选择器,如下所示:

/* Select every cell matching the 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-content="Susanne">Susanne</td>
<td data-content="female">female</td>
<td data-content="14">14</td>
</tr>
</table>

您还可以使用jQuery轻松设置data-content属性:

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

@voyager关于使用data-*属性的回答(例如data-gender="female|male"是2017年最有效的符合标准方法:

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

几乎大多数目标可以都可以实现,因为有一些面向文本的选择器(尽管有限)。::f第一封信是一个伪元素,可以对元素的第一个字母应用有限的样式。除了明显选择元素(例如段落)的第一行之外,还有一个::f第一行伪元素也意味着很明显CSS可以用于扩展这种现有功能以设置text Node的特定方面。

在这种倡导成功之前被实施,我可以建议的下一个最好的事情是使用空格分隔符的explode/split单词,在span元素中输出每个单独的单词,然后如果单词/样式目标是可预测的: n个选择器结合使用:

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

否则如果不可预测再次使用voyager关于使用data-*属性的回答。使用PHP的示例:

$p = explode(' ',$words);
foreach ($p as $key1 => $value1)
{
echo '<span data-word="'.$value1.'">'.$value1.'</span>;
}

我同意的数据属性(旅行者的答案)应该如何处理,但是,CSS规则如下:

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

通常可以更容易设置,特别是使用像angularjs这样的客户端库,它可以像以下这样简单:

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

只需确保内容只有一个单词!或者您甚至可以使用以下命令映射到不同的CSS类名:

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

为了完整性,这里是数据属性方法:

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

这里的大多数答案都试图提供如何编写超文本标记语言代码以包含更多数据的替代方案,因为至少在CSS3之前,你不能通过部分内部文本选择元素。但这是可以做到的,你只需要添加一点香草JavaScript,注意,由于女性也包含男性,它将被选择:

      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>

如果您使用的是黑猩猩/Webdriver.io,它们比CSS规范支持更多的CSS选择器

例如,这将单击包含“坏熊”字样的第一个锚点:

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

像这样做小的过滤器小部件:

    var searchField = document.querySelector('HOWEVER_YOU_MAY_FIND_IT')
var faqEntries = document.querySelectorAll('WRAPPING_ELEMENT .entry')


searchField.addEventListener('keyup', function (evt) {
var testValue = evt.target.value.toLocaleLowerCase();
var regExp = RegExp(testValue);


faqEntries.forEach(function (entry) {
var text = entry.textContent.toLocaleLowerCase();


entry.classList.remove('show', 'hide');


if (regExp.test(text)) {
entry.classList.add('show')
} else {
entry.classList.add('hide')
}
})
})

这个问题的语法看起来像Robot Framework语法。 在这种情况下,虽然没有可用于包含的css选择器,但您可以使用SeleniumLibrary关键字代替。 等待元素包含.

示例:

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

如果您不自己创建DOM(例如在用户脚本中),您可以使用纯JS执行以下操作:

for ( td of document.querySelectorAll('td') ) {
console.debug("text:", td, td.innerText)
td.setAttribute('text', td.innerText)
}
for ( td of document.querySelectorAll('td[text="male"]') )
console.debug("male:", td, td.innerText)
<table>
<tr>
<td>Peter</td>
<td>male</td>
<td>34</td>
</tr>
<tr>
<td>Susanne</td>
<td>female</td>
<td>12</td>
</tr>
</table>

控制台输出

text: <td> Peter
text: <td> male
text: <td> 34
text: <td> Susanne
text: <td> female
text: <td> 12
male: <td text="male"> male

如果你不想使用javascript或jQuery,我发现属性选项是你最好的选择。

例如,为所有表格单元格设置单词就绪的样式,在超文本标记语言中这样做:

 <td status*="ready">Ready</td>

然后在css中:

td[status*="ready"] {
color: red;
}

截至2021年1月,有一些东西可以做到这一点.: has()…只有一个问题:任何浏览器都不支持这一点

示例:以下选择器仅匹配直接包含子元素的元素:

a:has(> img)

参考文献:

https://developer.mozilla.org/en-US/docs/Web/CSS/: has

https://caniuse.com/?search=has

如果您想将样式应用于您想要的内容。简单的技巧。

    td { border: 1px solid black; }
td:empty { background: lime; }
td:empty::after { content: "male"; }
    <table>
<tr>
<td>Peter</td>
<td><!--male--></td>
<td>34</td>
</tr>
<tr>
<td>Susanne</td>
<td>female</td>
<td>14</td>
</tr>
</table>

https://jsfiddle.net/hyda8kqz/

很好的答案,但我想我可以添加一些在实际场景中对我有用的东西:利用CSS的aria-label属性。

对于不知道的读者:aria-label是一个属性,它与其他类似属性结合使用,让屏幕阅读器知道什么是什么,以防有视觉障碍的人正在使用您的网站。许多网站将这些属性添加到包含图像或文本的元素中,作为“描述符”。

这使得它高度特定于网站,但如果您的元素包含此内容,则使用属性的内容选择该元素非常简单:

超文本标记语言:

<td aria-label="male">Male</td>
<td aria-label="female">Female</td>

css:

td[aria-label="male"] {
outline: 1px dotted green;
}

从技术上讲,这与使用数据属性解决方案是一样的,但如果你不是网站的作者,这将适用于你,另外,这不是专门为支持此用例而设计的一些偏僻的解决方案;它本身相当常见。它的一个缺点是,真的不能保证你的预期元素会存在此属性。