Łączenie pseudoelementów CSS, „: after” the „: last-child”


122

Chcę tworzyć listy „poprawne gramatycznie” za pomocą CSS. Oto, co mam do tej pory:

Te <li>znaczniki są wyświetlane poziomo przecinkami po nich.

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

li:after { content: ", "; }

To działa, ale chcę, aby „ostatnie dziecko” miało kropkę zamiast przecinka. I jeśli to możliwe, chciałbym również umieścić „i” przed „ostatnim dzieckiem”. Stylizowane przeze mnie listy są generowane dynamicznie, więc nie mogę po prostu dać klasy „ostatnim dzieciom”. Nie można łączyć pseudoelementów, ale w zasadzie taki efekt chcę osiągnąć.

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

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

Jak mam to zrobić?


4
naprawdę nie powinieneś używać do tego css.
Funky Dude

2
Muszę się trochę zgodzić z Funky Dude. Byłoby lepiej zrobić to w kodzie HTML (lub za kodem, jeśli jest to coś więcej niż zwykły HTML). CSS służy do formatowania :)
Zyphrax

16
Ja ... osobiście skłaniam się do twierdzenia, że ​​na liście formatowanie jest drobiazgiem, a nie koniecznością. W takim przypadku użycie CSS pozwala na prostsze dodawanie lub usuwanie z listy, niż użycie kodowania HTML lub po stronie serwera. Ale czasami jestem taki dziwny i, szczerze ymmv, etc ... =)
David mówi przywrócenie Monice

9
I +1 za używanie przecinka Oxford! :)
Brandon Rhodes

5
+1 za „+1 dla przecinka Oxford”. Nigdy o tym nie słyszałem (nie jestem tubylcem). Ale szybkie wyszukiwanie wiki mówi, że jest to naturalne, ponieważ nie jest używane w wielu językach. Zabawne, czego można się nauczyć na temat stack-googlowania CSS;)
jakub.g

Odpowiedzi:


168

To działa :) (mam nadzieję, że wiele przeglądarek, Firefox to lubi)

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
Podobny problem występuje w przypadku oddzielania pozycji menu pionowymi znakami. To samo rozwiązanie działa. Jednak ostatni atrybut treści musi być ustawiony na {content: none;}, aby wyeliminować ostatni znak pionowej kreski.
aridlehoover

2
Porządek też jest ważny. li:last-child:afterdziała, ale li:after:last-childnie działa.
Richard Ayotte

1
Pamiętaj, że :last-childnie należy to do specyfikacji CSS3, więc nie jest obsługiwane przez IE8 i poprzednie wersje.
Cthulhu,

23

Robię to w przypadku elementów listy w elementach <menu>. Rozważ następujące znaczniki:

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

Stylizuję to za pomocą następującego CSS:

menu > li {
  display: inline;
}

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

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

Wyświetli się:

Profile | Options | Logout

Jest to możliwe dzięki temu, co Martin Atkins wyjaśnił w swoim komentarzu

Zauważ, że w CSS 2 użyjesz :after, a nie ::after. Jeśli używasz CSS 3, użyj ::after(dwie półkolumny), ponieważ ::afterjest to pseudoelement (pojedyncza półkolumna jest przeznaczona dla pseudoklas).


16

Stary wątek, ale ktoś może na tym skorzystać:

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

Powinno to działać w CSS3 i [nieprzetestowanym] CSS2.


11

Państwo może połączyć pseudo-elementy! Przepraszam, sam to wymyśliłem wkrótce po wysłaniu pytania. Może jest rzadziej używany z powodu problemów ze zgodnością.

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

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

Działa to płynnie. CSS jest niesamowity.


12
To jest trochę „rogu NIT dla zbierania za” a, ale „last-child” jest w rzeczywistości pseudo klasy , podczas gdy „przed” i „po” są pseudo-elementów. Różnica polega na tym, że pseudoklasa jest dodatkowym ograniczeniem istniejącego elementu, podczas gdy pseudoelement jest w rzeczywistości całkowicie nowym elementem w drzewie prezentacji, które zostało wygenerowane w CSS, a nie w HTML. Możesz je łączyć z tego powodu: last-childjest modyfikatorem w li, a następnie po wybraniu wszystkich lielementów, które są ostatnimi elementami podrzędnymi, wybierasz (i niejawnie tworzysz) nowy element przed i po każdym.
Martin Atkins

Wiem, że prawdopodobnie dawno zapomniałeś o tym konkretnym wątku, ale skoro wspomniałeś, że twoje listy mają zmienną długość, warto zauważyć, że w większości kontekstów lista zawierająca dokładnie dwa elementy nie byłaby poprawna z przecinkiem w języku angielskim. Innymi słowy, gdybyś chciał „chleb z masłem”. zamiast „chleba i masła”. - wtedy większość podanych tutaj rozwiązań byłaby niekompletna. Wymyśliłem sposób na obejście tego i zamieściłem to poniżej jako odpowiedź, na wypadek, gdyby pomogło to każdemu, kto nadal szuka tak daleko w wątku.
Matt Wagner,

6

Wystarczy wspomnieć, w CSS 3

:po

powinien być używany w ten sposób

::po

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

Notacja :: after została wprowadzona w CSS 3 w celu rozróżnienia pseudoklas i pseudoelementów. Przeglądarki akceptują również notację: po wprowadzeniu w CSS 2.

Więc powinno być:

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

3
Każda przeglądarka obsługująca ::składnię CSS3 z podwójnym dwukropkiem obsługuje również tylko :składnię, ale IE 8 obsługuje tylko pojedynczy dwukropek, więc na razie zaleca się używanie po prostu dwukropka, aby uzyskać najlepszą obsługę przeglądarki. ::to nowszy format z wcięciem w celu odróżnienia pseudo treści od pseudoselektorów. Jeśli nie potrzebujesz obsługi IE 8, możesz użyć podwójnego dwukropka. Z tego artykułu
JohnnyQ,

2
IE 8 nie jest już graczem pod względem standardów przeglądarek. Nie jest obsługiwany przez Microsoft i nie obsługuje HTML5 ani CSS3 (pseudoelementy, transformacje itp.). Wiele pracowałem nad kompatybilnością wsteczną, do roku temu, wracając do IE6 / IE7 (przez Modernizr.) Przeszliśmy długą drogę i jeśli zamierzasz, aby Twoja witryna prezentowała swoją tożsamość online w perspektywie długoterminowej - bez stania się rozwiązaniem krótkowzrocznym - po prostu weź pod uwagę przychody, które zarobiłbyś od kogoś używającego IE8. Nada. Nawet seniorzy, którzy mają 20 lat spóźnienia, korzystają teraz z tabletów i laptopów 2 w 1.
Steven Ventimiglia

2

Dodając kolejną odpowiedź na to pytanie, ponieważ potrzebowałem dokładnie tego, o co prosił @derek i już poszedłem trochę dalej, zanim zobaczyłem odpowiedzi tutaj. W szczególności potrzebowałem CSS, który mógłby również uwzględniać przypadek z dokładnie dwoma elementami listy, gdzie przecinek NIE jest pożądany. Na przykład, niektóre wpisy autorstwa, które chciałem stworzyć, wyglądałyby następująco:

Jeden autor: By Adam Smith.

Dwóch autorów: By Adam Smith and Jane Doe.

Trzech autorów: By Adam Smith, Jane Doe, and Frank Underwood.

Podane tutaj rozwiązania działają dla jednego autora i dla 3 lub więcej autorów, ale pomijają przypadek dwóch autorów - gdzie styl „przecinka oksfordzkiego” (w niektórych częściach znany również jako „przecinek Harvard”) nie ma zastosowania - tj. przed spójnikiem nie powinno być przecinka.

Po popołudniu majsterkowania wymyśliłem następujące rzeczy:

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

Wyświetla listę boczną, tak jak mam je powyżej.

Ostatecznie musiałem również pozbyć się białych znaków między lielementami, aby obejść irytację: w przeciwnym razie właściwość inline-block pozostawiłaby spację przed każdym przecinkiem. Prawdopodobnie istnieje alternatywny, przyzwoity hack, ale nie jest to przedmiotem tego pytania, więc zostawię to komuś innemu, aby mógł odpowiedzieć.

Fiddle tutaj: http://jsfiddle.net/5REP2/


2

Aby mieć coś takiego jak Jeden, dwa i trzy , należy dodać jeszcze jeden styl CSS

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

Spowoduje to usunięcie przecinka z przedostatniego elementu.

Kompletny kod

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

Używam tej samej techniki w zapytaniu o media, która skutecznie zmienia listę punktowaną w listę wbudowaną na mniejszych urządzeniach, ponieważ oszczędzają miejsce.

Więc zmiana z:

  • Pozycja listy 1
  • Pozycja listy 2
  • Pozycja listy 3

do:

Lista pozycji 1; Pozycja listy 2; Pozycja listy 3.


Próbuje to zrobić za pomocą CSS. Twoja metoda to zakodowany na stałe kod HTML. Ta metoda jest zwykle używana do wyświetlania nawigacji.
Sparatan117
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.