2015-07-13 18 views
20

Chúng tôi có một selector :empty có thể phù hợp với một phần tử khi nó là hoàn toàn trống rỗng:chọn CSS cho rỗng hoặc khoảng trắng

<p></p> 

Nhưng tôi có một điều kiện mà nó có thể là rỗng, hoặc nó có thể chứa dòng phá vỡ hoặc không gian trống:

<p> </p> 

tôi tìm thấy một giải pháp cho Firefox, :-moz-only-whitespace:

:empty { width: 300px; height: 15px; background: blue; } 
 
:-moz-only-whitespace { width: 300px; height: 15px; background: orange; }
<p></p> 
 
<p> </p> 
 
<p>This is paragraph three.</p>

Có giải pháp tương tự cho các trình duyệt khác không?

+0

Bạn có thể cung cấp ví dụ về mã trên JSFiddle không? –

+0

https://jsfiddle.net/fzax9qj1/ – Deadpool

+0

Bạn đã gắn thẻ thẻ này với jQuery - bạn có thể thêm vị từ kiểm tra trống của riêng mình nếu điều đó có thể phục vụ mục đích của bạn. – Pointy

Trả lời

15

Trong khi câu hỏi mô tả một phần tử <p> chứa một số ký tự khoảng trắng, có vẻ giống như giám sát, nó phổ biến hơn nhiều để xem đánh dấu nơi các phần tử chỉ chứa khoảng trắng ở dạng thụt lề và dòng trống, chẳng hạn như:

<ul class="items"> 
    <li class="item"> 
    <div> 
     <!-- Some complex structure of elements --> 
    </div> 
    </li> 
    <li class="item"> 
    </li> <!-- Empty, except for a single line break and 
      indentation preceding the end tag --> 
</ul> 

Một số yếu tố, như <li> trong ví dụ trên cũng như <p>, có thẻ kết thúc không bắt buộc, có thể gây tác dụng phụ ngoài ý muốn trong chế biến DOM cũng như trong sự hiện diện của phần tử liên khoảng trắng. Ví dụ, hai <ul> yếu tố sau đây không tạo ra cây nút tương đương, đặc biệt là người đầu tiên không dẫn đến một li:empty:

li:empty::before { content: '(empty)'; font-style: italic; color: #999; }
<ul> 
 
    <li> 
 
</ul> 
 
<ul> 
 
    <li></li> 
 
</ul>

Cho rằng HTML considers inter-element whitespace to be transparent by design, nó không phải là vô lý khi muốn để nhắm mục tiêu các yếu tố như vậy với CSS mà không cần phải sửa đổi HTML hoặc ứng dụng tạo ra nó (đặc biệt nếu bạn phải thực hiện và kiểm tra một trường hợp đặc biệt chỉ để làm như vậy).

Như đã đề cập, :blank pseudo-class in Selectors 4 sẽ giải quyết vấn đề này. Thật không may, nó đã không làm cho nó thành tiêu chuẩn hiện tại, hoặc bởi vì nó đã không được đề xuất trước đó, hoặc có đơn giản là không có cơ hội để xác thịt nó ra. Ngay cả tên của nó vẫn chưa được hoàn thiện, và nó không rõ ràng nếu hành vi được mô tả đã được kiểm tra hoặc hoàn thành.

Vì nó là một đề nghị tương đối mới với tiêu chuẩn, không có triển khai được biết đến bên ngoài của :-moz-only-whitespace, mà MDN có this nói:

Các :-moz-only-whitespace pseudo-class phù hợp với một yếu tố mà không có con các nút ở tất cả hoặc các nút văn bản trống hoặc các nút văn bản chỉ có khoảng trắng trong chúng. Chỉ khi có các nút phần tử hoặc các nút văn bản có một hoặc nhiều ký tự bên trong phần tử, phần tử không khớp với lớp giả này nữa.

... trong đó, khi kiểm tra kỹ hơn, có vẻ như không phù hợp với mô tả của thông số kỹ thuật :blank, tôi khuyên bạn không nên sử dụng nó trong quá trình sản xuất.

Vì không được triển khai ở bất kỳ nơi nào khác, hiện tại không có tương đương với bất kỳ trình duyệt nào khác.Trong khi chờ đợi, việc sửa đổi HTML tùy chọn duy nhất, cho dù ở nguồn hay thông qua thao tác DOM bằng cách sử dụng tập lệnh.

2

@BoltClock cung cấp câu trả lời tuyệt vời cho câu hỏi này, cho thấy rằng (hiện tại, đó là, làm việc với CSS Specification 3) không thể đạt được chỉ bằng CSS.

@BoltClock nói rằng yếu tố đó là thực sự trống (mà là một nét lạ như được giải thích) có thể được nhắm mục tiêu bằng cách sử dụng các pseudo selector :empty. Bộ chọn giả này chỉ có sẵn trong CSS 3 và S W KHÔNG chọn các phần tử chỉ có khoảng trắng làm nội dung.

@BoltClock đã tuyên bố rằng cách duy nhất để xóa các phần tử chỉ có khoảng trắng là nội dung là sửa HTML, nhưng điều đó không hoàn toàn chính xác. Điều này cũng có thể đạt được thông qua việc thực hiện Javascript.

GIỮ TRONG MÙA H!! Javascript mà tôi cung cấp để giải quyết vấn đề này có thể mất một thời gian rất dài để thực thi, vì vậy phương pháp tốt nhất là dọn sạch HTML thô thay vì nếu có thể. Nếu điều đó là không thể, thì điều này có thể làm việc như một giải pháp, miễn là bạn không có quá nhiều cây DOM.

tôi sẽ từng bước làm thế nào để viết kịch bản cho mình ...

Trước hết, khởi động tất cả mọi thứ sau khi tải trang.

Điều này sẽ khá rõ ràng. Bạn cần đảm bảo rằng DOM đã được tải đầy đủ trước khi chạy tập lệnh của bạn. Thêm một event listener cho tải trang:

window.addEventListener("load", cleanUpMyDOM); 

... và, tất nhiên, trước đó, tạo ra một function gọi cleanUpMyDOM. Chúng ta sẽ viết phần còn lại của logic trong hàm này.

Thứ hai, thu thập các yếu tố mà chúng tôi đang kiểm tra.

Trong ví dụ của chúng tôi, chúng tôi sẽ kiểm tra toàn bộ DOM, nhưng đây là nơi tập lệnh của chúng tôi có thể nhận được rất nhiều và có thể làm cho trang của bạn không hồi đáp. Bạn có thể muốn giới hạn số lượng nút bạn đang lặp lại.

Chúng tôi có thể lấy các nút được đề cập bằng cách sử dụng document.querySelectorAll. Điều thú vị về chức năng này là nó sẽ loại bỏ cây DOM và chúng tôi sẽ không phải tái xử lý các con của mỗi nút.

var nodes = document.querySelectorAll("*"); 

Như tôi đã nói ở trên, mã này sẽ lấy nút EVERY DOM, và đó có thể KHÔNG phải là ý hay.

Ví dụ: tôi đang làm việc với WordPress và một số trang nội bộ có một số trang trong đó. May mắn thay, chúng là tất cả các phần tử p là con của phần tử div.body, vì vậy tôi có thể thay đổi bộ chọn của mình thành document.querySelectorAll("div.body p"), chỉ chọn p phần tử là con của phần tử div.body đệ quy của chúng tôi. Điều này sẽ tối ưu hóa rất nhiều kịch bản của tôi.

Thứ ba, lặp lại các nút và tìm các nút trống.

Chúng tôi sẽ tạo vòng lặp cho mảng nodes và kiểm tra từng nút trong đó. Sau đó, chúng tôi sẽ phải kiểm tra xem liệu nút có trống không. Nếu nó trống, chúng tôi sẽ áp dụng một lớp học với tên là blank.

Tôi chỉ chụp từ hông ở đây, vì vậy nếu bạn nhận thấy có lỗi trong mã này, vui lòng cho tôi biết.

for(var i = 0; i < nodes.length; i++){ 
    nodes[i].innerHTML = nodes[i].innerHTML.trim(); 
    if(!nodes[i].innerHTML) 
     nodes[i].className += " blank"; 
} 

Tôi chắc chắn rằng có cách viết sạch hơn ở trên, nhưng việc này sẽ hoàn thành công việc.

Cuối cùng, tất cả những gì bạn cần làm là nhắm mục tiêu các phần tử trống bằng CSS của bạn.

Thêm quy tắc này để stylesheet của bạn:

.blank { 
    display:none; 
} 

Và có bạn có nó! Tất cả các nút "trống" của bạn đã bị ẩn.

Đối với những người chỉ muốn nhảy về phía trước, đây là kịch bản hoàn chỉnh:

function cleanUpMyDOM(){ 
    var nodes = document.querySelectorAll("*"); 
    for(var i = 0; i < nodes.length; i++){ 
     nodes[i].innerHTML = nodes[i].innerHTML.trim(); 
     if(!nodes[i].innerHTML) 
      nodes[i].className += " blank"; 
    } 
} 
window.addEventListener("load", cleanUpMyDOM); 

Một lần nữa, nếu bạn nhận thấy bất kỳ vấn đề với mã của tôi, xin vui lòng cho tôi biết trong các ý kiến ​​dưới đây.

Hy vọng điều này sẽ hữu ích!

P.S. Nhiều người có thể tự hỏi tại sao bạn muốn làm điều này, vì nó cảm thấy như thực hành xấu. Tôi sẽ tránh làm điều này, nhưng tôi đang ở trong một tình huống mà tôi bắt đầu cân nhắc nó. Nội dung của các trang trên trang web của tôi được tạo thông qua trình soạn thảo WYSIWYG. Nội dung này được tạo ra và sửa đổi liên tục bởi đội ngũ tiếp thị và tôi nhận được khá choáng ngợp xử lý sự hỗ trợ cho các phiếu của họ. Nó không phải công việc của tôi để sửa chữa trình soạn thảo WYSIWYG của WordPress (cũng không bao giờ tôi muốn), nhưng tôi có thể viết một kịch bản rất đơn giản có thể xử lý một số công việc cho tôi. Điều đó chắc chắn có vẻ như là câu trả lời tốt hơn cho tôi, bên cạnh việc đào tạo nhóm hỗ trợ về quản lý khoảng trắng của họ khi thực hiện chỉnh sửa.

+1

Viết lại 'innerHTML' là xấu. Bạn sẽ xóa tất cả dữ liệu nội bộ như trình xử lý sự kiện, kiểm tra, thuộc tính tùy chỉnh, v.v. Cách thích hợp sẽ lặp lại tất cả các nút văn bản tại DOMContentLoaded và loại bỏ các nút chỉ chứa khoảng trắng. Sau đó, ': empty' sẽ hoạt động. – Oriol

+0

Điểm tốt @Oriol. Như tôi đã nói, đây không phải là cách tiếp cận tốt nhất. Tôi nên chỉnh sửa câu trả lời của mình để nhắm mục tiêu cụ thể hơn các nút văn bản. – WebWanderer

Các vấn đề liên quan