Có bộ chọn CSS cho các thành phần có chứa văn bản nhất định không?


512

Tôi đang tìm kiếm một bộ chọn CSS cho bảng sau:

Peter    | male    | 34
Susanne  | female  | 12

Có bộ chọn nào phù hợp với tất cả các TD có chứa "nam" không?


1
Vấn đề là điều này sẽ rất khó thực hiện theo cách thức biểu diễn.
Ms2ger

7
Bộ chọn XPath có thể làm điều đó với phương thức .text () (nếu bạn không muốn sử dụng trình thực thi JavaScript).
djangofan

11
Đây là một ví dụ về cách bạn có thể làm điều đó bằng xpath: // h1 [text () = 'Phiên'] và bạn có thể kiểm tra xpath trong Chrome bằng cách nhập $ x ("// h1 [text () = 'Phiên']" ) trong bảng điều khiển
VinnyG

1
Điều này sẽ rất thuận tiện. Ví dụ: một ô bảng chứa dấu kiểm hoặc chuỗi "Có", "Đạt", "OK", v.v. có thể có màu xanh lá cây.
Andreas Rejbrand

các $xcâu trả lời câu hỏi. đối với câu hỏi ban đầu, hãy $x("//td[text()='male']")thực hiện mẹo
Xiao

Câu trả lời:


394

Nếu tôi đọc các đặc điểm kỹ thuật chính xác, không.

Bạn có thể khớp trên một phần tử, tên của một thuộc tính trong phần tử và giá trị của một thuộc tính được đặt tên trong một phần tử. Tuy nhiên, tôi không thấy bất cứ điều gì phù hợp với nội dung trong một yếu tố.


228
Có một trường hợp cạnh : :empty.
Ciro Santilli 郝海东 冠状 病 事件

34
Để trả lời câu hỏi của riêng tôi: Vâng, nó vẫn đúng cho ngày hôm nay! Bộ chọn nội dung không được dùng nữa! Không có nhiều bộ chọn nội dung kể từ CSS3. ( w3.org/TR/css3-selector/#selector )
Wlad

158

Sử dụng jQuery:

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

7
Cuối cùng, cần phải có điều ngược lại, đó là: jQuery (phần tử) .not (": chứa ('chuỗi')")
Jazzy

311
Ngoại trừ đó không phải là CSS, đó là JavaScript.
Synetech

9
Đồng ý - đó là lý do tại sao câu trả lời của tôi nói rằng tôi đang sử dụng jQuery, không phải CSS. Nhưng đó là một phần câu trả lời của tôi đã được chỉnh sửa. =)
moetser 7/07/2015

18
Nhưng bản thân từ nam cũng có từ 'nam' không? Là nó làm việc chỉ là nam cos đầu tiên? Lỗi chờ đợi xảy ra nếu chúng được đặt hàng lại?
Michael Durrant

5
@Michael Durrant: Bạn vui vẻ, nhưng khớp chuỗi phần tử chéo (là vấn đề thậm chí còn lớn hơn so với các chuỗi con thông thường trong cùng một phần tử) thực tế là một trong những lý do lớn nhất: chứa () bị loại bỏ.
BoltClock

158

Có vẻ như họ đã suy nghĩ về nó cho thông số CSS3 nhưng nó không thực hiện được .

:contains()Bộ chọn CSS3 http://www.w3.org/TR/css3-selector/#content-selector


9
Looks like they were thinking about it for the CSS3 spec but it didn't make the cut.Và vì lý do chính đáng, nó sẽ vi phạm toàn bộ tiền đề của việc tách biệt kiểu dáng, nội dung, cấu trúc và hành vi.
Synetech

56
@Synetech Nó thực sự có thể giúp tách biệt kiểu dáng khỏi nội dung, vì điều đó có nghĩa là nội dung không cần biết về khách hàng của nó sẽ được coi là quan trọng đối với kiểu dáng cơ sở. Ngay bây giờ, nội dung html của chúng tôi thường được ghép nối chặt chẽ với css bằng cách bao gồm các lớp mà chúng tôi biết nhà tạo mẫu quan tâm. Họ đã chuyển sang cho phép CSS tại nội dung, bằng chứng là các bộ chọn giá trị thuộc tính trong CSS3.
DanielMeister 16/07/2015

8
@Synetech và chính xác thì nó là "hành vi" như thế nào? Đối với tôi đó là một vấn đề trình bày. Nó không làm gì cả - nó trình bày một số loại nội dung theo một cách nhất định.
BarbaraKwarc

4
@DannyMeister, oh bạn không cần phải thuyết phục tôi. Một vài năm và tôi thấy mình trở lại đây trong khi cố gắng tìm kiếm chính xác chức năng này, và buồn bã rằng nó không chỉ không tồn tại mà còn bị từ chối. 😒 eBay chỉ thay đổi giao diện người dùng của họ và làm cho trang web của họ rất khó sử dụng. Tôi đang cố gắng sửa nó bằng biểu định kiểu người dùng, nhưng đánh dấu của họ không phân biệt giữa đấu giá và danh sách BIN, vì vậy cách duy nhất để làm nổi bật số lượng giá thầu trong danh sách là bằng cách khớp phần tử theo nội dung văn bản của nó. Tất cả chỉ cần thuyết phục ai đó là để họ trải nghiệm kịch bản trường hợp sử dụng trực tiếp.
Synetech

8
Để đảm bảo phân tách tốt nội dung và kiểu dáng, chúng tôi sẽ không có bộ chọn: chứa (). Vì vậy, thay vì tạo kiểu cho một ô dựa trên nội dung của nó (ví dụ: cột "trạng thái" của "Mở" hoặc "Đã giải quyết"), chúng tôi sẽ sao chép nội dung trong cả hai thuộc tính hiển thị và lớp, sau đó chọn vào đó . Thông minh!
Jon Kloske

122

Bạn sẽ phải thêm một thuộc tính dữ liệu vào các hàng được gọi data-genderbằng a malehoặc femalevalue và sử dụng bộ chọn thuộc tính:

HTML:

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

CSS:

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

10
Hoàn toàn ổn khi sử dụng các thuộc tính dữ liệu tùy chỉnh với Javascript và CSS. Xem MDN bằng cách sử dụng các thuộc tính dữ liệu
Michael Benjamin

1
Tôi đồng ý thuộc tính dữ liệu là cách xử lý nó, NHƯNG, một quy tắc CSS như td.male thường dễ thiết lập hơn nhiều, đặc biệt là với góc có thể trông giống như: <td class = "{{person.gender}} ">
DJDaveMark

Giới tính tất nhiên là một ví dụ điển hình nơi các lớp học sẽ làm việc. Nhưng nếu dữ liệu thay đổi nhiều hơn chỉ malehoặc female? Thực tế classlà chứa đầy các lớp khác, thứ tự của chúng không được đảm bảo, có thể có các tập hợp với các tên lớp khác, vv làm cho classmột nơi tồi tệ hơn cho loại công cụ này. Một data-*thuộc tính chuyên dụng tách biệt dữ liệu của bạn khỏi tất cả những thứ đó và giúp dễ dàng thực hiện khớp một phần, v.v. bằng cách sử dụng các bộ chọn thuộc tính.
Stijn de Witt

Có một câu trả lời khác với đoạn mã làm việc sử dụng các thuộc tính dữ liệu theo cách tương tự.
Josh Habdas

65

Thực sự có một cơ sở khái niệm cho lý do tại sao điều này đã không được thực hiện. Nó là sự kết hợp của 3 khía cạnh cơ bản:

  1. Nội dung văn bản của một yếu tố thực sự là con của yếu tố đó
  2. Bạn không thể nhắm mục tiêu nội dung văn bản trực tiếp
  3. CSS không cho phép thăng thiên với bộ chọn

Cả 3 cùng có nghĩa là vào thời điểm bạn có nội dung văn bản, bạn không thể quay lại thành phần chứa và bạn không thể định kiểu văn bản hiện tại. Điều này có thể có ý nghĩa vì giảm dần chỉ cho phép theo dõi số ít bối cảnh và phân tích cú pháp kiểu SAX. Tăng dần hoặc các bộ chọn khác liên quan đến các trục khác đưa ra nhu cầu về các giải pháp tương tự phức tạp hơn hoặc tương tự sẽ làm phức tạp đáng kể việc áp dụng CSS vào DOM.


4
Đây là sự thật. Đây là những gì XPath dành cho. Nếu bạn có thể thực thi bộ chọn trong JS / jQuery hoặc thư viện phân tích cú pháp (trái ngược với chỉ CSS), thì có thể sử dụng text()hàm của XPath .
Mark Thomas

Đó là một điểm tốt về nội dung . Nhưng làm thế nào tôi muốn bạn có thể có một :contains(<sub-selector>)yếu tố có chứa các yếu tố cụ thể khác. Muốn div:contains(div[id~="bannerAd"])thoát khỏi quảng cáo và nó chứa.
Lawrence Dol

27

Bạn có thể đặt nội dung làm thuộc tính dữ liệu và sau đó sử dụng bộ chọn thuộc tính , như được hiển thị ở đây:

/* 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>

Bạn cũng có thể sử dụng jQuery để dễ dàng đặt các thuộc tính nội dung dữ liệu:

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

3
lưu ý rằng .text().textContentkhá nặng, cố gắng tránh chúng trong danh sách dài hoặc văn bản lớn khi có thể. .html().innerHTMLnhanh chóng
oriadam

@JoshHabdas bạn có thể tạo một ví dụ jsbin / jsfiddle về sự thay đổi của bạn không?
Buksy

1
Nếu bạn định sử dụng jQuery, hãy sử dụng bộ chọn chứa:$("td:contains(male)")
huwiler

Nếu người dùng có thể chỉnh sửa nội dung ( contenteditable='true'- trường hợp của tôi), thì không đủ để đặt giá trị của data-contentthuộc tính trước khi trang được hiển thị. Nó phải được cập nhật liên tục. Đây là những gì tôi sử dụng:<td onkeypress="event.target.setAttribute('data-content', event.target.textContent);">
caram

13

Vì CSS thiếu tính năng này, bạn sẽ phải sử dụng JavaScript để định kiểu các ô theo nội dung. Ví dụ với XPath's contains:

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

Sau đó sử dụng kết quả như vậy:

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

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


Đây là javascript, Làm thế nào điều này liên quan đến câu hỏi?
rubo77

3
Khi bạn không thể chọn theo nội dung trong css, bạn sẽ phải sử dụng js để làm điều đó. Mặc dù bạn đúng khi bạn chỉ ra rằng đây không phải là css, việc sử dụng thuộc tính dữ liệu không được chọn theo nội dung. Chúng tôi chỉ có thể đoán tại sao người đọc muốn chọn các ô theo nội dung, loại truy cập nào cô ấy có đối với html, có bao nhiêu kết
quả trùng

7

Tôi sợ điều này là không thể, bởi vì nội dung không có thuộc tính và cũng không thể truy cập được thông qua một lớp giả. Danh sách đầy đủ các bộ chọn CSS3 có thể được tìm thấy trong đặc tả CSS3 .


4

Đối với những người đang tìm cách thực hiện các lựa chọn văn bản CSS Selenium, tập lệnh này có thể được sử dụng.

Mẹo nhỏ là chọn cha mẹ của phần tử mà bạn đang tìm kiếm, sau đó tìm kiếm phần tử có văn bản:

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

Điều này sẽ trả về phần tử đầu tiên nếu có nhiều phần tử vì nó luôn là một phần tử, trong trường hợp của tôi.


Bạn có thể sử dụng TD:contains('male')nếu bạn đang sử dụng Selenium: imho chỉ sử dụng nó nếu bạn không thể cập nhật nguồn để thêm các lớp. ví dụ: nếu bạn đang kiểm tra mã kế thừa hoặc công ty của bạn sẽ không cho phép bạn nói chuyện với các nhà phát triển (eurgh!) vì các bài kiểm tra của bạn sẽ dễ vỡ và sẽ bị masculinehỏng nếu ai đó thay đổi văn bản sau đó hoặc thay đổi ngôn ngữ. Tài liệu SauceLabs cho thấy việc sử dụng containsở đây ( saucelabs.com/resource/articles/selenium-tips-css-selector ) + cc @matas vaitkevicius tôi đã bỏ lỡ điều gì chưa?
mã tuyết

3

Tôi đồng ý thuộc tính dữ liệu (câu trả lời của chuyến đi) là cách xử lý nó, NHƯNG, các quy tắc CSS như:

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

thường có thể dễ dàng hơn nhiều để thiết lập, đặc biệt với các lib phía máy khách như angularjs có thể đơn giản như:

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

Chỉ cần chắc chắn rằng nội dung chỉ có một từ! Hoặc thậm chí bạn có thể ánh xạ tới các tên lớp CSS khác nhau bằng:

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

Để hoàn thiện, đây là cách tiếp cận thuộc tính dữ liệu:

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

Các ràng buộc mẫu là một giải pháp tuyệt vời. Nhưng tôi cảm thấy hơi khó khăn khi tạo các tên lớp dựa trên cấu trúc đánh dấu (mặc dù đó là khá nhiều những gì BEM làm trong thực tế).
Josh Habdas

2

Câu trả lời của @ Journeyager về việc sử dụng data-*thuộc tính (ví dụ: cách tiếp cận tuân thủ tiêu chuẩndata-gender="female|male" và hiệu quả nhất kể từ năm 2017:

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

Khá nhiều mục tiêu thể đạt được vì có một số bộ chọn giới hạn mặc dù được định hướng xung quanh văn bản. Chữ cái đầu tiên là một phần tử giả có thể áp dụng kiểu dáng giới hạn cho chữ cái đầu tiên của một phần tử. Ngoài ra còn có một phần tử giả dòng đầu tiên bên cạnh việc rõ ràng chọn dòng đầu tiên của một phần tử (chẳng hạn như đoạn văn) cũng ngụ ý rằng rõ ràng CSS có thể được sử dụng để mở rộng khả năng hiện có này để định kiểu các khía cạnh cụ thể của textNode .

Cho đến khi việc vận động đó thành công được triển khai, điều tốt nhất tiếp theo tôi có thể đề xuất khi áp dụng là explode/ splitsử dụng một dấu phân cách không gian, xuất từng từ riêng lẻ bên trong một thành spanphần và sau đó nếu mục tiêu từ / kiểu dáng có thể dự đoán được sử dụng kết hợp với : bộ chọn thứ n :

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

Khác, nếu không dự đoán được , một lần nữa, sử dụng câu trả lời của chuyến đi về việc sử dụng data-*thuộc tính. Một ví dụ sử dụng PHP:

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


1

Hầu hết các câu trả lời ở đây đều cố gắng đưa ra giải pháp thay thế cho cách viết mã HTML để bao gồm nhiều dữ liệu hơn vì ít nhất lên đến CSS3, bạn không thể chọn một phần tử bằng văn bản bên trong một phần. Nhưng nó có thể được thực hiện, bạn chỉ cần thêm một chút JavaScript vanilla, chú ý vì nữ cũng chứa nam nó sẽ được chọn:

      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>

1

Tôi thấy tùy chọn thuộc tính là lựa chọn tốt nhất của bạn nếu bạn không muốn sử dụng javascript hoặc jquery.

Ví dụ: để tạo kiểu cho tất cả các ô của bảng với từ đã sẵn sàng, Trong HTML thực hiện điều này:

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

Sau đó trong css:

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

0

Bạn cũng có thể sử dụng contentvới attr()và các kiểu bảng ô là ::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>

A ZeroWidthSpaceđược sử dụng để thay đổi màu sắc và có thể được thêm bằng JavaScript vanilla:

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

Mặc dù <td>thẻ kết thúc s có thể bị bỏ qua vì vậy có thể khiến nó được coi là không trống.


0

Nếu bạn không tự tạo DOM (ví dụ: trong bản mô tả người dùng), bạn có thể thực hiện các thao tác sau với JS thuần túy:

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>

Bảng điều khiển đầu ra

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

-2

Thực hiện các Widget lọc nhỏ như thế này:

    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')
            }
        })
    })

-2

Cú pháp của câu hỏi này trông giống như cú pháp Robot Framework. Trong trường hợp này, mặc dù không có bộ chọn css mà bạn có thể sử dụng để chứa, nhưng có một từ khóa SeleniumL Library mà bạn có thể sử dụng thay thế. Các Chờ cho đến khi phần tử Có .

Thí dụ:

Wait Until Element Contains  | ${element} | ${contains}
Wait Until Element Contains  |  td | male
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.