Kombinieren von CSS-Pseudoelementen, ": nach" dem ": letzten Kind"

122

Ich möchte mit CSS "grammatikalisch korrekte" Listen erstellen. Das habe ich bisher:

Die <li>Tags werden horizontal mit Kommas angezeigt.

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

li:after { content: ", "; }

Das funktioniert, aber ich möchte, dass das "letzte Kind" einen Punkt anstelle eines Kommas hat. Und wenn möglich, möchte ich "und" auch vor das "letzte Kind" setzen. Die Listen, die ich gestalte, werden dynamisch generiert, sodass ich den "letzten Kindern" nicht einfach eine Klasse geben kann. Sie können keine Pseudoelemente kombinieren, aber das ist im Grunde der Effekt, den ich erzielen möchte.

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

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

Wie mache ich das?

Derek
quelle
4
Sie sollten wirklich nicht CSS dafür verwenden.
Funky Dude
2
Ich muss Funky Dude ein bisschen zustimmen. Es wäre besser, dies im HTML zu tun (oder Codebehind, wenn es mehr als nur HTML ist). CSS ist für die Formatierung :)
Zyphrax
16
Ich persönlich neige dazu zu argumentieren, dass in einer Liste die Formatierung eine nette Sache ist, keine Notwendigkeit. Die Verwendung von CSS ermöglicht einfachere Hinzufügungen oder Entfernungen aus der Liste als die Verwendung von HTML oder serverseitiger Codierung. Aber ich bin manchmal so seltsam und ehrlich gesagt, ymmv, etc ... =)
David sagt, Monica
9
Und +1 für die Verwendung des Oxford-Kommas! :)
Brandon Rhodes
5
+1 für "+1 für Oxford-Komma". Ich habe noch nie davon gehört (ich bin kein Muttersprachler). Eine schnelle Wiki-Suche sagt jedoch, dass dies natürlich ist, da es in vielen Sprachen nicht verwendet wird. Lustig, was man lernen kann, wenn man CSS-Probleme beim
Stapeln googelt

Antworten:

168

Das funktioniert :) (Ich hoffe Multi-Browser, Firefox mag es)

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
quelle
2
Ein ähnliches Problem ist der Fall, wenn Sie Menüelemente durch Pipe-Zeichen trennen. Die gleiche Lösung funktioniert. Das Attribut final content muss jedoch auf {content: none;} gesetzt werden, um das endgültige Pipe-Zeichen zu entfernen.
Aridlehoover
2
Ordnung ist auch wichtig. li:last-child:afterfunktioniert aber li:after:last-childnicht.
Richard Ayotte
1
Beachten Sie, dass :last-childdies nicht zur CSS3-Spezifikation gehört und daher von IE8 und früheren Versionen nicht unterstützt wird.
Cthulhu
23

Ich mag dies für Listenelemente in <menu> -Elementen. Betrachten Sie das folgende Markup:

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

Ich gestalte es mit folgendem CSS:

menu > li {
  display: inline;
}

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

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

Dies zeigt an:

Profile | Options | Logout

Und dies ist möglich aufgrund dessen, was Martin Atkins in seinem Kommentar erklärt hat

Beachten Sie, dass Sie in CSS 2 :afternicht verwenden würden ::after. Wenn Sie CSS 3 verwenden, verwenden Sie ::after(zwei Halbspalten), da ::afteres sich um ein Pseudoelement handelt (eine einzelne Halbspalte steht für Pseudoklassen).

Gabriel Hautclocq
quelle
16

Ein alter Thread, dennoch kann jemand davon profitieren:

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

Dies sollte in CSS3 und [ungetestetem] CSS2 funktionieren.

user5341733
quelle
11

Sie können Pseudoelemente kombinieren! Sorry Leute, ich habe das kurz nach dem Posten der Frage selbst herausgefunden. Möglicherweise wird es aufgrund von Kompatibilitätsproblemen weniger häufig verwendet.

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

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

Das funktioniert schwimmend. CSS ist irgendwie erstaunlich.

Derek
quelle
12
Dies ist ein bisschen wie ein „Kleinigkeitskrämer Ecke“, sondern „liest-child“ ist eigentlich eine pseudo- Klasse , während „vor“ und „nach“ sind Pseudo-Elemente. Der Unterschied besteht darin, dass eine Pseudoklasse eine zusätzliche Einschränkung für ein vorhandenes Element darstellt, während ein Pseudoelement praktisch ein völlig neues Element im Präsentationsbaum ist, das in CSS und nicht in HTML generiert wurde. Sie können diese aus folgendem Grund kombinieren: Das last-childist ein Modifikator für li, und nachdem Sie alle liElemente ausgewählt haben , die die letzten untergeordneten Elemente sind, wählen Sie vor und nach jedem Element ein neues Element aus (und erstellen es implizit).
Martin Atkins
Ich weiß, dass Sie diesen speziellen Thread wahrscheinlich schon lange vergessen haben, aber da Sie erwähnt haben, dass Ihre Listen von variabler Länge sind, sollten Sie darauf hinweisen, dass in den meisten Kontexten eine Liste mit genau zwei Elementen mit einem Komma in Englisch nicht korrekt wäre. Mit anderen Worten, wenn Sie "Brot und Butter" wollten. eher als "Brot und Butter". - Dann wären die meisten der hier angebotenen Lösungen unvollständig. Ich habe mir einen Weg ausgedacht und ihn unten als Antwort gepostet, falls es jemandem hilft, der noch so weit unten im Thread schaut.
Matt Wagner
6

Nur um zu erwähnen, in CSS 3

:nach dem

sollte so verwendet werden

::nach dem

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

Die :: after-Notation wurde in CSS 3 eingeführt, um eine Unterscheidung zwischen Pseudoklassen und Pseudoelementen herzustellen. Browser akzeptieren auch die Notation: nach Einführung in CSS 2.

So sollte es sein:

li { display: inline; list-style-type: none; }
li::after { content: ", "; }
li:last-child::before { content: "and "; }
li:last-child::after { content: "."; }
Wolfgang Blessen
quelle
3
Jeder Browser, der die Doppelpunkt- ::CSS3-Syntax unterstützt , unterstützt auch nur die :Syntax, aber IE 8 unterstützt nur den Einzelpunkt. Daher wird empfohlen, für die beste Browserunterstützung nur den Einzelpunkt zu verwenden. ::ist das neuere Format, das eingerückt wird, um Pseudoinhalte von Pseudoselektoren zu unterscheiden. Wenn Sie keine IE 8-Unterstützung benötigen, können Sie den Doppelpunkt verwenden. Aus diesem Artikel
JohnnyQ
2
IE 8 ist in Bezug auf Browser-Standards kein Player mehr. Wird von Microsoft nicht unterstützt und unterstützt weder HTML5 noch CSS3 (Pseudoelemente, Transformationen usw.). Ich habe bis vor einem Jahr viel an der Abwärtskompatibilität gearbeitet und bin bis zurück zu IE6 / IE7 (via) gegangen Modernizr.) Wir haben einen langen Weg zurückgelegt. Wenn Sie beabsichtigen, dass Ihre Website ihre Online-Identität langfristig präsentiert - ohne dass dies zu einer kurzsichtigen Lösung wird -, sollten Sie einfach die Einnahmen berücksichtigen, die Sie mit jemandem erzielen würden, der IE8 verwendet. Nada. Selbst Senioren, die 20 Jahre hinter der Zeit zurückliegen, verwenden jetzt Tablets und 2-in-1-Laptops.
Steven Ventimiglia
2

Hinzufügen einer weiteren Antwort auf diese Frage, da ich genau das brauchte, wonach @derek gefragt hatte, und bereits ein Stück weiter gekommen war, bevor ich die Antworten hier sah. Insbesondere brauchte ich CSS, das auch den Fall mit genau zwei Listenelementen berücksichtigen konnte , bei denen das Komma NICHT erwünscht ist. Als Beispiel würden einige Autoren-Bylines, die ich produzieren wollte, wie folgt aussehen:

Ein Autor: By Adam Smith.

Zwei Autoren: By Adam Smith and Jane Doe.

Drei Autoren: By Adam Smith, Jane Doe, and Frank Underwood.

Die hier bereits angegebenen Lösungen funktionieren für einen Autor und für drei oder mehr Autoren, berücksichtigen jedoch nicht den Fall mit zwei Autoren, bei dem der "Oxford Comma" -Stil (in einigen Teilen auch als "Harvard Comma" -Stil bekannt) nicht gilt - dh vor der Konjunktion sollte kein Komma stehen.

Nach einem Bastelnachmittag hatte ich mir Folgendes ausgedacht:

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

Es zeigt die Bylines an, wie ich sie oben habe.

Am Ende musste ich auch Leerzeichen zwischen liElementen entfernen , um einen Ärger zu umgehen: Die Inline-Block-Eigenschaft würde sonst vor jedem Komma ein Leerzeichen lassen. Es gibt wahrscheinlich einen alternativen anständigen Hack dafür, aber das ist nicht das Thema dieser Frage, also überlasse ich das jemand anderem, um es zu beantworten.

Geige hier: http://jsfiddle.net/5REP2/

Matt Wagner
quelle
2

Um so etwas wie Eins, Zwei und Drei zu haben , sollten Sie einen weiteren CSS-Stil hinzufügen

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

Dies würde das Komma aus dem vorletzten Element entfernen.

Vollständiger Code

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

Ich verwende dieselbe Technik in einer Medienabfrage, die eine Aufzählungsliste auf kleineren Geräten effektiv in eine Inline-Liste umwandelt, da sie Platz sparen.

Also der Wechsel von:

  • Listenpunkt 1
  • Listenpunkt 2
  • Listenpunkt 3

zu:

Listenpunkt 1; Listenpunkt 2; Listenpunkt 3.

user3064058
quelle
Er versucht dies mit CSS zu tun. Ihre Methode ist fest codiertes HTML. Diese Methode wird normalerweise zur Anzeige der Navigation verwendet.
Sparatan117