Combinando pseudoelementos CSS, ": después" el ": último hijo"

122

Quiero hacer listas "gramaticalmente correctas" usando CSS. Esto es lo que tengo hasta ahora:

Las <li>etiquetas se muestran horizontalmente con comas después de ellas.

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

li:after { content: ", "; }

Eso funciona, pero quiero que el "último hijo" tenga un punto en lugar de una coma. Y, si es posible, me gustaría poner "y" antes del "último hijo" también. Las listas que estoy diseñando se generan dinámicamente, por lo que no puedo dar una clase a los "últimos hijos". No se pueden combinar pseudoelementos, pero ese es básicamente el efecto que quiero lograr.

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

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

¿Cómo hago para que esto funcione?

Derek
fuente
44
Realmente no deberías estar usando CSS para esto.
Funky Dude
2
Debo estar un poco de acuerdo con Funky Dude. Sería mejor hacer esto en HTML (o código subyacente si es más que HTML simple). CSS es para formatear :)
Zyphrax
16
Yo ... personalmente, tiendo a argumentar que, en una lista, el formato es un detalle, no una necesidad. Siendo ese el caso, el uso de CSS permite adiciones o eliminaciones más simples de la lista, que el uso de html o codificación del lado del servidor. Pero soy extraño así, a veces, y, sinceramente, mmm, etc ... =)
David dice que reinstale a Mónica
9
¡Y +1 por usar la coma de Oxford! :)
Brandon Rhodes
55
+1 para "+1 para la coma de Oxford". Nunca escuché sobre eso (no soy nativo). Pero la búsqueda rápida de wiki dice que es natural, porque no se usa en muchos idiomas. Es curioso lo que uno puede aprender problemas de CSS de google de pila;)
jakub.g

Respuestas:

168

Esto funciona :) (espero que sea multi-navegador, a Firefox le gusta)

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
fuente
2
Un problema similar es el caso en el que está separando elementos de menú con caracteres de canalización. La misma solución funciona. Pero, el atributo de contenido final debe establecerse en {content: none;} para eliminar el carácter final de canalización.
aridlehoover
2
El orden también es importante. li:last-child:afterfunciona pero li:after:last-childno funciona.
Richard Ayotte
1
Tenga en cuenta que :last-childno pertenece a la especificación CSS3, por lo que no es compatible con IE8 y versiones anteriores.
Cthulhu
23

Me gusta esto para elementos de lista en elementos <menu>. Considere el siguiente marcado:

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

Lo estilo con el siguiente CSS:

menu > li {
  display: inline;
}

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

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

Esto mostrará:

Profile | Options | Logout

Y esto es posible debido a lo que Martin Atkins explicó en su comentario

Tenga en cuenta que en CSS 2 usaría :after, no ::after. Si usa CSS 3, use ::after(dos semi-columnas) porque ::afteres un pseudo-elemento (una sola semi-columna es para pseudo-clases).

Gabriel Hautclocq
fuente
16

Un viejo hilo, sin embargo, alguien puede beneficiarse de esto:

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

Esto debería funcionar en CSS3 y CSS2 [no probado].

usuario5341733
fuente
11

Usted puede combinar los pseudo-elementos! Lo siento chicos, me di cuenta de esto poco después de publicar la pregunta. Tal vez se usa con menos frecuencia debido a problemas de compatibilidad.

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

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

Esto funciona a la perfección. CSS es algo sorprendente.

Derek
fuente
12
Esto es un poco de "esquina de tiquismiquis" una, pero "last-child" es en realidad una pseudo- clase , mientras que "antes" y "después" son pseudo-elementos. La diferencia es que una pseudo-clase es una restricción adicional sobre un elemento existente, mientras que un pseudo-elemento es efectivamente un elemento completamente nuevo en el árbol de presentación que se generó en CSS en lugar de en HTML. Puede combinar estos por este motivo: last-childes un modificador en el li, y luego, después de haber seleccionado todos los lielementos que son los últimos hijos, selecciona (y crea implícitamente) un nuevo elemento antes y después de cada uno.
Martin Atkins el
Sé que probablemente olvidó este hilo en particular, pero dado que mencionó que sus listas eran de longitud variable, vale la pena señalar que, en la mayoría de los contextos, una lista con exactamente dos elementos no sería correcta con una coma en inglés. En otras palabras, si querías "pan y mantequilla". en lugar de "pan y mantequilla". - entonces la mayoría de las soluciones proporcionadas aquí serían incompletas. Se me ocurrió una forma de evitarlo, y lo publiqué a continuación como respuesta, en caso de que ayude a alguien que todavía esté mirando tan lejos en el hilo.
Matt Wagner
6

Solo para mencionar, en CSS 3

:después

debería usarse así

::después

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

La notación :: after se introdujo en CSS 3 para establecer una discriminación entre pseudo-clases y pseudo-elementos. Los navegadores también aceptan la notación: después de introducirse en CSS 2.

Entonces debería ser:

li { display: inline; list-style-type: none; }
li::after { content: ", "; }
li:last-child::before { content: "and "; }
li:last-child::after { content: "."; }
Wolfgang Blessen
fuente
3
Todos los navegadores que admiten la ::sintaxis CSS3 de dos puntos también admiten solo la :sintaxis, pero IE 8 solo admite los dos puntos, por lo que, por ahora, se recomienda usar solo dos puntos para obtener el mejor soporte del navegador. ::es el formato más nuevo sangrado para distinguir el pseudo contenido de los pseudo selectores. Si no necesita soporte para IE 8, no dude en usar los dos puntos dobles. De este artículo
JohnnyQ
2
IE 8 ya no es un jugador en términos de estándares del navegador. No es compatible con Microsoft y no es compatible con HTML5 o CSS3 (pseudo elementos, transformaciones, etc.) Solía ​​hacer mucho trabajo sobre compatibilidad con versiones anteriores, hasta hace un año, volviendo a IE6 / IE7 (a través de Modernizr.) Hemos recorrido un largo camino, y si tiene la intención de que su sitio presente su identidad en línea a largo plazo, sin que se convierta en una solución miope, simplemente considere los ingresos que obtendría de alguien que usa IE8. Nada Incluso las personas mayores, con 20 años de retraso, están usando tabletas y computadoras portátiles 2 en 1 ahora.
Steven Ventimiglia
2

Agregué otra respuesta a esta pregunta porque necesitaba precisamente lo que @derek estaba pidiendo y ya había avanzado un poco antes de ver las respuestas aquí. Específicamente, necesitaba CSS que pudiera también explicar el caso con exactamente dos elementos de la lista, donde NO se desea la coma. Como ejemplo, algunas líneas de autoría que quería producir se verían así:

Un autor: By Adam Smith.

Dos autores: By Adam Smith and Jane Doe.

Tres autores: By Adam Smith, Jane Doe, and Frank Underwood.

Las soluciones ya dadas aquí funcionan para un autor y para 3 o más autores, pero no tienen en cuenta el caso de dos autores, donde el estilo "Oxford Comma" (también conocido como estilo "Harvard Comma" en algunas partes) no se aplica - es decir, no debe haber una coma antes de la conjunción.

Después de una tarde de retoques, se me ocurrió lo siguiente:

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

Muestra los bylines como los tengo arriba.

Al final, también tuve que deshacerme de cualquier espacio en blanco entre los lielementos, para evitar una molestia: la propiedad de bloque en línea dejaría un espacio antes de cada coma. Probablemente haya un hack alternativo decente, pero ese no es el tema de esta pregunta, así que lo dejaré para que alguien más lo responda.

Violín aquí: http://jsfiddle.net/5REP2/

Matt Wagner
fuente
2

Para tener algo como Uno, dos y tres , debe agregar un estilo CSS más

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

Esto eliminaría la coma del segundo último elemento.

Código completo

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

Estoy usando la misma técnica en una consulta de medios que efectivamente convierte una lista de viñetas en una lista en línea en dispositivos más pequeños a medida que ahorran espacio.

Entonces el cambio de:

  • Listar elemento 1
  • Listar elemento 2
  • Lista elemento 3

a:

Artículo de la lista 1; Artículo de la lista 2; Artículo de la lista 3.

usuario3064058
fuente
Él está tratando de hacer esto con CSS. Su método es HTML codificado. Este método se usa normalmente para mostrar la navegación.
Sparatan117