Kết hợp các phần tử giả CSS, “: after” với “: last-child”


122

Tôi muốn tạo danh sách "đúng ngữ pháp" bằng cách sử dụng CSS. Đây là những gì tôi có cho đến nay:

Các <li>thẻ được hiển thị theo chiều ngang với dấu phẩy sau chúng.

li { display: inline; list-style-type: none; }

li:after { content: ", "; }

Điều đó hiệu quả, nhưng tôi muốn "con cuối cùng" có dấu chấm thay vì dấu phẩy. Và, nếu có thể, tôi cũng muốn đặt "và" trước "con cuối cùng". Các danh sách mà tôi đang tạo kiểu được tạo động, vì vậy tôi không thể chỉ cho "những đứa trẻ cuối cùng" một lớp. Bạn không thể kết hợp các yếu tố giả, nhưng về cơ bản đó là hiệu quả mà tôi muốn đạt được.

li:last-child li:before { content: "and "; }

li:last-child li:after { content: "."; }

Làm thế nào để tôi làm cho nó hoạt động?


4
bạn thực sự không nên sử dụng css cho việc này.
Funky Dude

2
Tôi phải đồng ý với Funky Dude một chút. Sẽ tốt hơn nếu thực hiện điều này trong HTML (hoặc mã phía sau nếu nó không phải là HTML thuần túy). CSS dành cho định dạng :)
Zyphrax

16
Cá nhân tôi ... có xu hướng lập luận rằng, trong một danh sách, định dạng là một điều tốt đẹp, không phải là một điều cần thiết. Đó là trường hợp sử dụng CSS cho phép bổ sung hoặc xóa khỏi danh sách đơn giản hơn so với sử dụng html hoặc mã hóa phía máy chủ. Nhưng tôi kỳ lạ như thế, đôi khi, và, một cách trung thực YMMV, vv ... =)
David nói Khôi phục Monica

9
Và +1 để sử dụng Dấu phẩy Oxford! :)
Brandon Rhodes

5
+1 cho "+1 cho Dấu phẩy Oxford". Chưa bao giờ nghe nói về nó (tôi không phải là người bản xứ). Nhưng tra cứu nhanh wiki nói rằng điều đó là tự nhiên, vì nó không được sử dụng trong nhiều ngôn ngữ. Vui gì người ta có thể học hỏi các vấn đề CSS stack-googling;)
jakub.g

Câu trả lời:


168

Điều này hoạt động :) (Tôi hy vọng nhiều trình duyệt, Firefox thích nó)

li { display: inline; list-style-type: none; }
li:after { content: ", "; }
li:last-child:before { content: "and "; }
li:last-child:after { content: "."; }
<html>
  <body>
    <ul>
      <li>One</li>
      <li>Two</li>
      <li>Three</li>
    </ul>
  </body>
</html>


2
Một vấn đề tương tự là trường hợp bạn đang tách các mục menu bằng các ký tự ống dẫn. Giải pháp tương tự hoạt động. Tuy nhiên, thuộc tính nội dung cuối cùng cần được đặt thành {content: none;} để loại bỏ ký tự cuối cùng.
aridlehoover

2
Thứ tự cũng quan trọng. li:last-child:afterhoạt động nhưng li:after:last-childkhông.
Richard Ayotte

1
Lưu ý rằng :last-childnó không thuộc về thông số kỹ thuật CSS3, vì vậy nó không được hỗ trợ bởi IE8 và các phiên bản trước.
Cthulhu

23

Tôi thích điều này cho các mục danh sách trong phần tử <menu>. Hãy xem xét đánh dấu sau:

<menu>
  <li><a href="/member/profile">Profile</a></li>
  <li><a href="/member/options">Options</a></li>
  <li><a href="/member/logout">Logout</a></li>
</menu>

Tôi tạo kiểu cho nó bằng CSS sau:

menu > li {
  display: inline;
}

menu > li::after {
  content: ' | ';
}

menu > li:last-child::after {
  content: '';
}

Điều này sẽ hiển thị:

Profile | Options | Logout

Và điều này có thể xảy ra vì những gì Martin Atkins giải thích trên bình luận của mình

Lưu ý rằng trong CSS 2 bạn sẽ sử dụng :afterchứ không phải ::after. Nếu bạn sử dụng CSS 3, hãy sử dụng ::after(hai nửa cột) vì ::afterlà phần tử giả (một nửa cột duy nhất dành cho lớp giả).


16

Một chủ đề cũ, nhưng ai đó có thể được hưởng lợi từ điều này:

li:not(:last-child)::after { content: ","; }
li:last-child::after { content: "."; }

Điều này sẽ hoạt động trong CSS3 và CSS2 [chưa được kiểm tra].


11

Bạn có thể kết hợp các yếu tố giả! Xin lỗi các bạn, tôi đã tự mình tìm ra điều này ngay sau khi đăng câu hỏi. Có thể nó ít được sử dụng hơn vì các vấn đề tương thích.

li:last-child:before { content: "and "; }

li:last-child:after { content: "."; }

Điều này hoạt động một cách bơi lội. CSS thật tuyệt vời.


12
Đây là một chút về "góc của người chọn nit", nhưng "cuối cùng" thực sự là một lớp giả , trong khi "trước" và "sau" là các phần tử giả. Sự khác biệt là lớp giả là một ràng buộc bổ sung đối với phần tử hiện có, trong khi phần tử giả thực sự là một phần tử hoàn toàn mới trong cây trình bày được tạo trong CSS chứ không phải trong HTML. Bạn có thể kết hợp chúng vì lý do này: last-childlà một bổ ngữ trên li, và sau khi bạn đã chọn tất cả các liphần tử là phần tử con cuối cùng, bạn chọn (và hoàn toàn tạo) một phần tử mới trước và sau mỗi phần tử.
Martin Atkins

Tôi biết có lẽ bạn đã quên chủ đề cụ thể này từ lâu, nhưng vì bạn đã đề cập rằng danh sách của bạn có độ dài thay đổi nên đáng để chỉ ra rằng, trong hầu hết các ngữ cảnh, một danh sách có chính xác hai mục sẽ không đúng bằng dấu phẩy trong tiếng Anh. Nói cách khác, nếu bạn muốn "bánh mì và bơ." chứ không phải "bánh mì và bơ." - thì hầu hết các giải pháp được cung cấp ở đây sẽ không đầy đủ. Tôi đã nghĩ ra một cách để giải quyết vấn đề này và đăng nó dưới đây như một câu trả lời, trong trường hợp nó giúp ích cho bất kỳ ai vẫn đang tìm kiếm vấn đề này.
Matt Wagner

6

Chỉ cần đề cập, trong CSS 3

:sau

nên được sử dụng như thế này

::sau

Từ https://developer.mozilla.org/de/docs/Web/CSS/ :: after :

Ký hiệu :: after được giới thiệu trong CSS 3 để thiết lập sự phân biệt giữa các lớp giả và phần tử giả. Các trình duyệt cũng chấp nhận ký hiệu: sau khi được giới thiệu trong CSS 2.

Nên nó phải là:

li { display: inline; list-style-type: none; }
li::after { content: ", "; }
li:last-child::before { content: "and "; }
li:last-child::after { content: "."; }

3
Mọi trình duyệt hỗ trợ ::cú pháp dấu hai chấm CSS3 cũng chỉ hỗ trợ :cú pháp, nhưng IE 8 chỉ hỗ trợ dấu hai chấm, vì vậy hiện tại, bạn chỉ nên sử dụng dấu hai chấm để hỗ trợ trình duyệt tốt nhất. ::là định dạng mới hơn được thụt lề để phân biệt nội dung giả với bộ chọn giả. Nếu bạn không cần hỗ trợ IE 8, hãy sử dụng dấu hai chấm. Từ đó bài viết
JohnnyQ

2
IE 8 không còn là một trình duyệt về tiêu chuẩn trình duyệt. Không được Microsoft hỗ trợ và không hỗ trợ HTML5 hoặc CSS3 (phần tử giả, chuyển đổi, v.v.) Tôi đã từng làm rất nhiều việc về khả năng tương thích ngược, cách đây một năm, quay trở lại IE6 / IE7 (thông qua Modernizr.) Chúng tôi đã đi được một chặng đường dài và nếu bạn có ý định để trang web của mình thể hiện danh tính trực tuyến của nó lâu dài - mà không cần nó trở thành một giải pháp thiển cận - thì chỉ cần xem xét doanh thu mà bạn sẽ kiếm được từ một người nào đó sử dụng IE8. Không. Ngay cả những người cao tuổi, chậm hơn 20 năm so với thời đại, cũng đang sử dụng máy tính bảng và máy tính xách tay 2 trong 1.
Steven Ventimiglia

2

Thêm một câu trả lời khác cho câu hỏi này vì tôi cần chính xác những gì @derek đang yêu cầu và tôi đã tìm hiểu thêm một chút trước khi xem câu trả lời ở đây. Cụ thể, tôi cần CSS cũng có thể giải quyết trường hợp có chính xác hai mục danh sách, trong đó KHÔNG mong muốn dấu phẩy. Ví dụ: một số dòng tác giả mà tôi muốn tạo ra sẽ giống như sau:

Một tác giả: By Adam Smith.

Hai tác giả: By Adam Smith and Jane Doe.

Ba tác giả: By Adam Smith, Jane Doe, and Frank Underwood.

Các giải pháp đã được đưa ra ở đây phù hợp với một tác giả và cho 3 tác giả trở lên, nhưng không tính đến trường hợp hai tác giả — trong đó kiểu "Dấu phẩy Oxford" (còn được gọi là kiểu "Dấu phẩy Harvard" trong một số phần) không áp dụng - tức là, không được có dấu phẩy trước liên từ.

Sau một buổi chiều mày mò, tôi đã nghĩ ra những điều sau:

<html>
 <head>
  <style type="text/css">
    .byline-list {
      list-style: none;
      padding: 0;
      margin: 0;
    }
    .byline-list > li {
      display: inline;
      padding: 0;
      margin: 0;
    }
    .byline-list > li::before {
      content: ", ";
    }
    .byline-list > li:last-child::before {
      content: ", and ";
    }
    .byline-list > li:first-child + li:last-child::before {
      content: " and ";
    }
    .byline-list > li:first-child::before {
      content: "By ";
    }
    .byline-list > li:last-child::after {
      content: ".";
    }
  </style>
 </head>
 <body>
  <ul class="byline-list">
   <li>Adam Smith</li>
  </ul>
  <ul class="byline-list">
   <li>Adam Smith</li><li>Jane Doe</li>
  </ul>
  <ul class="byline-list">
   <li>Adam Smith</li><li>Jane Doe</li><li>Frank Underwood</li>
  </ul>
 </body>
</html>

Nó hiển thị các dòng như tôi đã có ở trên.

Cuối cùng, tôi cũng phải loại bỏ bất kỳ khoảng trắng nào giữa licác phần tử, để tránh một điều khó chịu: thuộc tính khối nội tuyến sẽ để lại khoảng trắng trước mỗi dấu phẩy. Có lẽ có một cách hack khá phù hợp cho nó nhưng đó không phải là chủ đề của câu hỏi này nên tôi sẽ để người khác trả lời.

Fiddle tại đây: http://jsfiddle.net/5REP2/


2

Để có một cái gì đó giống như Một, hai và ba, bạn nên thêm một kiểu css nữa

li:nth-last-child(2):after {
    content: ' ';
}

Điều này sẽ xóa dấu phẩy khỏi phần tử cuối cùng thứ hai.

Hoàn thành mã

li {
  display: inline;
  list-style-type: none;
}

li:after {
  content: ", ";
}

li:nth-last-child(2):after {
  content: '';
}

li:last-child:before {
  content: " and ";
}

li:last-child:after {
  content: ".";
}
<html>

<body>
  <ul>
    <li>One</li>
    <li>Two</li>
    <li>Three</li>
  </ul>
</body>

</html>


0

Tôi đang sử dụng kỹ thuật tương tự trong một truy vấn phương tiện để biến một danh sách dấu đầu dòng thành danh sách nội tuyến trên các thiết bị nhỏ hơn một cách hiệu quả vì chúng tiết kiệm dung lượng.

Vì vậy, sự thay đổi từ:

  • Liệt kê mục 1
  • Liệt kê mục 2
  • Liệt kê mục 3

đến:

Liệt kê Mục 1; Liệt kê Khoản 2; Liệt kê Mục 3.


Anh ấy đang cố gắng làm điều này với CSS. Phương pháp của bạn là HTML được mã hóa cứng. Phương pháp này thường được sử dụng để hiển thị Điều hướng.
Sparatan117
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.