是否有包含特定文本的元素的CSS选择器?

jan*_*mon 456 css css-selectors

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

Peter    | male    | 34
Susanne  | female  | 12
Run Code Online (Sandbox Code Playgroud)

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

Dea*_*n J 349

如果我正确阅读了规范,没有.

您可以匹配元素,元素中属性的名称以及元素中命名属性的值.但是,我没有看到任何元素内的匹配内容.

  • 有一个边缘案例:`:empty`. (212认同)
  • 回答我自己的问题:是的,今天仍然如此!内容选择器已弃用!自CSS3以来没有更多的内容选择器.(https://www.w3.org/TR/css3-selectors/#selectors) (31认同)
  • @CiroSantilliTRUMPBANISBAD,从技术上讲,**还不是边缘情况**,`:empty()`只选择没有子项的内容,DOM中的文本不是“只是”文本,它是文本**节点**。与 `:has()` 类似的原理,如果采用 **DRAFT** 中的以下功能,这个 **可能**(或可能不会)将来会有所改变 - **任何浏览器尚不支持以下功能(2021)**:“:empty 伪类表示没有子元素的元素,除了可选的文档空白字符。”https://drafts.c​​sswg.org/selectors-4/#empty-pseudo (4认同)

moe*_*ger 152

使用jQuery:

$('td:contains("male")')
Run Code Online (Sandbox Code Playgroud)

  • 除了不是CSS,那就是JavaScript. (253认同)
  • 但是fe*male*这个词本身也包含"男性"这个词吗?它的工作原理只是'男性是第一位的吗?如果重新订购错误等待发生? (17认同)
  • 同意 - 这就是为什么我的回答说我使用的是jQuery,而不是CSS.但我的答案的那部分已被删除.=) (8认同)
  • 结束需要与此相反,即:jQuery(element).not(":contains('string')") (6认同)
  • @Michael Durrant:你开玩笑,但是跨元素字符串匹配(这是一个比同一元素中常规子字符串匹配更大的问题)实际上是最大的原因之一:contains()被删除了. (5认同)
  • 不是CSS,与这个问题无关。 (3认同)
  • 是的,这不是 CSS,但是当上面所有的答案都说这在 CSS 中不可能时,它在 jQuery 中是可能的就变得相关了。一旦/如果通过 CSS 支持所有主要浏览器,你就可以说这不相关 (3认同)

小智 140

看起来他们正在考虑CSS3规范,但它并没有削减.

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

  • @Synetech它实际上可以帮助将样式与内容分离,因为这意味着内容不需要知道它的客户端将被认为是基于样式的重要.现在我们的html内容通常与css紧密配对,包括我们知道styler关心的类.他们已经转向在内容中使用CSS,CSS3中的属性值选择器就是证明. (45认同)
  • `看起来他们正在为CSS3规范考虑它,但它没有削减.而且有充分的理由,它会违反分离样式,内容,结构和行为的整个前提. (8认同)
  • @Synetech,究竟是什么"行为"?对我而言,这是一个介绍问题.它不会*做任何事情 - 它以某种方式呈现*某些类型的内容. (6认同)
  • 恕我直言,根据其类型对内容进行分组的整个概念是愚蠢的。我也总是在框架中看到这一点;脚本、样式表、图像等的单独文件夹......我想根据功能对内容进行分组。因此,'photo-album' 包包含用于相册功能的脚本、样式表、图像等。我也没有看到关于混合这些类型的主要反对意见。事实上,将它们很好地混合是我们建立伟大网站的工作。就像厨师混合他的配料。我们不需要带有不同食物类型的部分的盘子!:) (3认同)
  • 这对于 uBlock Origin / Adblock Plus 过滤器很有用。 (3认同)
  • @BarbaraKwarc,那不是我说的。查找网页设计原理。在良好的网页设计中,应将样式包含在CSS文件中,数据库中的内容,HTML文件中的结构以及JavaScript文件中的行为。理想情况下,您不应该混合使用它们。在这种情况下,混合的不是行为,而是样式和内容(将内容放入样式中)。这很糟糕,因为一方面,由于有了i18n,它使事情变得复杂。例如,对于您支持的每种语言,您都会有一个单独的CSS条目吗? (2认同)
  • @DannyMeister,哦,您不必说服我。几年后,我回到自己的位置,同时试图寻找确切的功能,但不但不知道它不存在,而且被拒绝了。eBay只是更改了用户界面,使他们的网站很难使用。我正在尝试使用用户样式表进行修复,但其标记无法区分拍卖和BIN列表,因此,突出显示列表中出价数量的唯一方法是通过元素的文本内容进行匹配。说服某人是让他们亲身体验用例场景所需要的。 (2认同)
  • 为了确保内容和样式之间的良好分离,我们将没有:contains()选择器。因此,我们将不根据其内容为单元格样式(例如,“打开”或“已解决”的“状态”列),而是在显示属性和类属性中复制内容,然后在该属性上进行选择。优秀! (2认同)
  • 有人填充这个吗?我在 GitHub 上逛了一圈,没有成功。哲学上的反对意见今天似乎站不住脚,因为我们可以根据元素的几乎任何其他内容(包括咏叹调标签)进行查询。马特·惠普尔的反对意见似乎仍然相当不错。但是,拥有 `:contains` 可用对于一种情况特别有用:现有应用程序的自定义样式表。 (2认同)
  • @JonMarnock 然后为每种支持的语言编写数百个选择器?您不必使用类来复制内容,而是提取其语义并将其放入类中(打开/解析)。通过使用`:content`,您可以在其中复制内容。 (2认同)

Est*_*ber 110

你不得不数据属性添加到所谓的行data-gendermalefemale值和使用属性选择:

HTML:

<td data-gender="male">...</td>
Run Code Online (Sandbox Code Playgroud)

CSS:

td[data-gender="male"] { ... }
Run Code Online (Sandbox Code Playgroud)

  • 使用Javascript和CSS自定义数据属性是完全可以的.请参阅[MDN使用数据属性](https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Using_data_attributes) (10认同)

Mat*_*ple 63

实际上有一个非常概念性的基础,为什么没有实现这一点.它基本上是3个方面的组合:

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

这三个一起意味着,当您拥有文本内容时,您无法提升回包含元素,并且您无法设置当前文本的样式.这可能很重要,因为降序只允许单一跟踪上下文和SAX样式解析.涉及其他轴的升序或其他选择器引入了对更复杂的遍历或类似解决方案的需求,这将使CSS的应用极大地复杂化.

  • 这是真的.这就是XPath的用途.如果你可以在JS/jQuery或解析库中执行选择器(而不是仅CSS),那么就可以使用XPath的`text()`函数. (4认同)
  • @LawrenceDol,它实际上于 2022 年 9 月作为 `:has()` 出现在某些浏览器中。 (4认同)

Buk*_*ksy 24

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

/* 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;
}
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)

您还可以使用jQuery轻松设置数据内容属性:

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

  • 请注意`.text()`和`.textContent`非常重,尽可能避免在长列表或大文本中使用它们.`.html()`和`.innerHTML`很快. (3认同)
  • 这是生成标记的一个非常方便的技巧 (2认同)
  • 如果您要使用 jQuery,请使用包含选择器:`$("td:contains(male)")` (2认同)

use*_*521 9

由于CSS缺少此功能,因此您将不得不使用javascript通过内容对单元格进行样式设置。例如,xpath 包含

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

然后像这样使用结果:

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

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

  • 由于您无法通过CSS中的内容进行选择,因此您将不得不使用js来做到这一点。当您指出这不是CSS时,就正确了,但data属性的使用并非按内容选择。我们只能猜测为什么读者希望按内容选择单元格,对html有什么样的访问权限,有多少匹配项,表格有多大等等。 (2认同)

Ger*_*ica 8

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

// Add a custom attribute 'text' to all td's, set their values to td.innerText:
for ( td of document.querySelectorAll('td') ) {
  console.debug("text:", td, td.innerText)
  td.setAttribute('text', td.innerText)
}

// Query for the custom attribute 'text' with a specific value:
for ( td of document.querySelectorAll('td[text="male"]') )
  console.debug("male:", td, td.innerText)
Run Code Online (Sandbox Code Playgroud)
<table>
  <tr>
    <td>Peter</td>
    <td>male</td>
    <td>34</td>
  </tr>
  <tr>
    <td>Susanne</td>
    <td>female</td>
    <td>12</td>
  </tr>
</table>
Run Code Online (Sandbox Code Playgroud)

控制台输出

text: <td> Peter
text: <td> male
text: <td> 34
text: <td> Susanne
text: <td> female
text: <td> 12
male: <td text="male"> male
Run Code Online (Sandbox Code Playgroud)


小智 6

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


Mat*_*ius 6

对于那些希望进行 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];
}
Run Code Online (Sandbox Code Playgroud)

如果有多个元素,这将返回第一个元素,因为在我的情况下它总是一个元素。


cst*_*992 6

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

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

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

HTML:

<td aria-label="male">Male</td>
<td aria-label="female">Female</td>
Run Code Online (Sandbox Code Playgroud)

CSS:

td[aria-label="male"] {
    outline: 1px dotted green;
}
Run Code Online (Sandbox Code Playgroud)

从技术上讲,这与使用数据属性解决方案是一样的,但如果您不是网站的作者,这对您有用,而且这不是专门为支持此目的而设计的一些偏僻的解决方案用例;它本身就很常见。它的一个缺点是,实际上无法保证您想要的元素将具有此属性。


Rya*_*ton 5

如果您使用Chimp / Webdriver.io,它们支持的 CSS 选择器比 CSS 规范多得多。

例如,这将单击包含“Bad bear”一词的第一个锚点:

browser.click("a*=Bad Bear");
Run Code Online (Sandbox Code Playgroud)