Menggabungkan CSS Pseudo-elements, ": after" the ": last-child"

122

Saya ingin membuat daftar yang "secara tata bahasa benar" menggunakan CSS. Inilah yang saya miliki sejauh ini:

The <li>tag ditampilkan secara horizontal dengan koma setelah mereka.

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

li:after { content: ", "; }

Itu berhasil, tapi saya ingin "anak terakhir" memiliki titik, bukan koma. Dan, jika memungkinkan, saya juga ingin meletakkan "dan" sebelum "anak terakhir". Daftar yang saya buat gaya dibuat secara dinamis, jadi saya tidak bisa begitu saja memberi kelas "anak-anak terakhir". Anda tidak dapat menggabungkan elemen pseudo, tetapi pada dasarnya itulah efek yang ingin saya capai.

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

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

Bagaimana cara membuat ini berfungsi?

Derek
sumber
4
Anda seharusnya tidak menggunakan css untuk ini.
Funky Dude
2
Saya harus sedikit setuju dengan Funky Dude. Akan lebih baik melakukan ini dalam HTML (atau codebehind jika lebih dari HTML biasa). CSS untuk pemformatan :)
Zyphrax
16
Saya ... secara pribadi, cenderung berpendapat bahwa, dalam daftar, pemformatannya bagus, bukan suatu keharusan. Karena itu, penggunaan CSS memungkinkan penambahan atau penghapusan yang lebih sederhana dari daftar, daripada menggunakan kode html atau sisi server. Tapi saya aneh seperti itu, kadang-kadang, dan, sejujurnya ymmv, dll ... =)
David mengatakan mengembalikan Monica
9
Dan 1 untuk menggunakan Oxford Comma! :)
Brandon Rhodes
5
1 untuk "+1 untuk Oxford Comma". Tidak pernah mendengar tentang itu (saya bukan penduduk asli). Tetapi pencarian wiki cepat mengatakan itu wajar, karena tidak digunakan dalam banyak bahasa. Lucu apa yang bisa dipelajari tentang masalah CSS stack-googling;)
jakub.g

Jawaban:

168

Ini berfungsi :) (Saya harap multi-browser, Firefox menyukainya)

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>

Zyphrax
sumber
2
Masalah serupa adalah kasus di mana Anda memisahkan item menu dengan karakter pipa. Solusi yang sama berhasil. Tapi, atribut konten akhir perlu disetel ke {content: none;} untuk menghilangkan karakter pipa terakhir.
aridlehoover
2
Urutan juga penting. li:last-child:afterbekerja tetapi li:after:last-childtidak.
Richard Ayotte
1
Ingatlah bahwa :last-childitu bukan milik spesifikasi CSS3, jadi tidak didukung oleh IE8 dan versi sebelumnya.
Cthulhu
23

Saya suka ini untuk item daftar di elemen <menu>. Pertimbangkan markup berikut:

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

Saya menatanya dengan CSS berikut:

menu > li {
  display: inline;
}

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

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

Ini akan menampilkan:

Profile | Options | Logout

Dan ini dimungkinkan karena apa yang dijelaskan Martin Atkins dalam komentarnya

Perhatikan bahwa di CSS 2 Anda akan menggunakan :after, bukan ::after. Jika Anda menggunakan CSS 3, gunakan ::after(dua semi-kolom) karena ::aftermerupakan pseudo-element (satu semi-kolom untuk pseudo-class).

Gabriel Hautclocq
sumber
16

Sebuah utas lama, namun seseorang bisa mendapatkan keuntungan dari ini:

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

Ini harus bekerja di CSS3 dan CSS2 [belum diuji].

pengguna5341733
sumber
11

Anda bisa menggabungkan elemen semu! Maaf teman-teman, saya menemukan yang ini sendiri tak lama setelah memposting pertanyaan. Mungkin itu kurang umum digunakan karena masalah kompatibilitas.

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

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

Ini bekerja dengan baik. CSS itu luar biasa.

Derek
sumber
12
Ini sedikit "sudut pemetik nit", tetapi "anak terakhir" sebenarnya adalah kelas semu , sedangkan "sebelum" dan "setelah" adalah elemen semu. Perbedaannya adalah bahwa pseudo-class merupakan batasan tambahan pada elemen yang sudah ada, sedangkan pseudo-element secara efektif merupakan elemen yang sama sekali baru dalam pohon presentasi yang dibuat dalam CSS dan bukan dalam HTML. Anda dapat menggabungkan ini karena alasan ini: the last-childis a modifier on the li, lalu setelah Anda memilih semua lielemen yang merupakan turunan terakhir, Anda kemudian memilih (dan secara implisit membuat) elemen baru sebelum dan sesudah masing-masing.
Martin Atkins
Saya tahu Anda mungkin sudah lama melupakan utas khusus ini, tetapi karena Anda menyebutkan bahwa daftar Anda panjangnya bervariasi, perlu ditunjukkan bahwa, dalam kebanyakan konteks, daftar dengan tepat dua item tidak akan benar dengan koma dalam bahasa Inggris. Dengan kata lain, jika Anda menginginkan "roti dan mentega". daripada "roti, dan mentega". - maka sebagian besar solusi yang diberikan di sini tidak lengkap. Saya memang menemukan jalan keluarnya, dan mempostingnya di bawah ini sebagai jawaban, jika itu membantu siapa pun yang masih melihat sejauh ini di utas.
Matt Wagner
6

Sekadar menyebutkan, di CSS 3

:setelah

harus digunakan seperti ini

::setelah

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

Notasi :: after diperkenalkan di CSS 3 untuk menetapkan perbedaan antara pseudo-class dan pseudo-element. Browser juga menerima notasi: setelah diperkenalkan di CSS 2.

Jadi seharusnya:

li { display: inline; list-style-type: none; }
li::after { content: ", "; }
li:last-child::before { content: "and "; }
li:last-child::after { content: "."; }
Wolfgang Blessen
sumber
3
Setiap browser yang mendukung ::sintaks titik dua ganda CSS3 juga mendukung :sintaks, tetapi IE 8 hanya mendukung titik dua tunggal, jadi untuk saat ini, disarankan untuk hanya menggunakan titik dua tunggal untuk dukungan browser terbaik. ::adalah format lebih baru yang diindentasi untuk membedakan konten semu dari pemilih semu. Jika Anda tidak memerlukan dukungan IE 8, silakan gunakan titik dua ganda. Dari artikel
JohnnyQ
2
IE 8 tidak lagi menjadi pemain dalam hal standar browser. Tidak didukung oleh Microsoft dan tidak mendukung HTML5 atau CSS3 (elemen pseudo, transformasi, dll.) Saya biasa melakukan banyak pekerjaan tentang kompatibilitas ke belakang, hingga setahun yang lalu, kembali ke IE6 / IE7 (melalui Modernizr.) Kami telah menempuh perjalanan panjang, dan jika Anda bermaksud agar situs Anda menampilkan identitas online-nya dalam jangka panjang - tanpa menjadikannya solusi jangka pendek - maka cukup pertimbangkan pendapatan yang akan Anda peroleh dari seseorang yang menggunakan IE8. Nada. Bahkan warga senior, 20 tahun di belakang zaman, sekarang menggunakan tablet dan laptop 2-in-1.
Steven Ventimiglia
2

Menambahkan jawaban lain untuk pertanyaan ini karena saya membutuhkan secara tepat apa yang diminta @derek dan saya sudah melangkah lebih jauh sebelum melihat jawabannya di sini. Secara khusus, saya membutuhkan CSS yang juga dapat menjelaskan kasus dengan tepat dua item daftar, di mana koma TIDAK diinginkan. Sebagai contoh, beberapa byline kepenulisan yang ingin saya buat akan terlihat seperti berikut:

Satu penulis: By Adam Smith.

Dua penulis: By Adam Smith and Jane Doe.

Tiga penulis: By Adam Smith, Jane Doe, and Frank Underwood.

Solusi yang telah diberikan di sini berfungsi untuk satu penulis dan untuk 3 penulis atau lebih, tetapi lalai untuk memperhitungkan kasus dua penulis — di mana gaya "Oxford Comma" (juga dikenal sebagai gaya "Harvard Comma" di beberapa bagian) tidak berlaku - yaitu, tidak boleh ada koma sebelum konjungsi.

Setelah sore mengutak-atik, saya menemukan yang berikut:

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

Ini menampilkan bylines seperti yang saya dapatkan di atas.

Pada akhirnya, saya juga harus membuang spasi di antara lielemen, untuk menghindari gangguan: properti inline-block akan meninggalkan spasi sebelum setiap koma. Mungkin ada peretasan alternatif yang layak untuk itu tetapi itu bukan subjek pertanyaan ini jadi saya akan menyerahkannya kepada orang lain untuk menjawab.

Biola di sini: http://jsfiddle.net/5REP2/

Matt Wagner
sumber
2

Untuk memiliki sesuatu seperti Satu, dua dan tiga Anda harus menambahkan satu gaya css lagi

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

Ini akan menghapus koma dari elemen terakhir kedua.

Kode Lengkap

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>

Raj Sharma
sumber
0

Saya menggunakan teknik yang sama dalam kueri media yang secara efektif mengubah daftar peluru menjadi daftar sebaris pada perangkat yang lebih kecil karena mereka menghemat ruang.

Jadi perubahan dari:

  • Daftar item 1
  • Daftar item 2
  • Daftar item 3

untuk:

Daftar Item 1; Daftar Item 2; Daftar Item 3.

pengguna3064058
sumber
Dia mencoba melakukan ini dengan CSS. Metode Anda adalah HTML dengan kode keras. Metode ini biasanya digunakan untuk menampilkan Navigasi.
Sparatan117