Listas CSS, marcadores y contadores

Publicado: 2022-03-10
Resumen rápido ↬ Aplicar estilos a las listas en CSS es mucho más de lo que piensas. En este artículo, Rachel comienza examinando las listas en CSS y pasa a algunas características interesantes definidas en la especificación de listas CSS: marcadores y contadores.

Las listas en CSS tienen propiedades particulares que nos dan el estilo de lista estándar que esperamos. Una lista desordenada gana una viñeta de lista, del tipo disc , y las listas ordenadas se numeran. Mi interés en explorar listas con más detalle provino de un trabajo que hice para documentar el pseudo-elemento ::marker para MDN. Este pseudoelemento se incluye en Firefox 68 y se lanzará hoy . Con el pseudo elemento ::marker disponible para nosotros, podemos comenzar a hacer algunas cosas interesantes con las listas, y en este artículo explicaré más.

Deconstruir una lista

Es posible que no haya pensado mucho en las listas, aunque las usamos con frecuencia en nuestro marcado. Muchas cosas se pueden marcar lógicamente como una lista. Si bien las instrucciones paso a paso o los elementos clasificados pueden describirse naturalmente mediante una lista ordenada <ol> , muchas cosas en un diseño pueden describirse mediante una lista desordenada <ul> . Un uso muy común del elemento, por ejemplo, es marcar la navegación, ya que es una lista de destinos en el sitio. Para nuestra exploración, comencemos por averiguar exactamente qué es una lista en CSS.

Al igual que con muchas cosas en CSS, las listas tienen algunos valores iniciales que se les aplican. Estos valores los hacen parecer una lista. Estos valores especiales comienzan con la información de que un elemento de lista tiene la propiedad de display con un valor de list-item . Esto crea un cuadro a nivel de bloque, con un cuadro de marcador adicional. El cuadro de marcador es donde se agrega la viñeta o el número de la lista.

¡Más después del salto! Continúe leyendo a continuación ↓

Las listas se definieron desde el principio en CSS, y gran parte de la definición de listas, tal como las usamos hoy en día, proviene de CSS2. La especificación CSS2 describe un elemento de lista de la siguiente manera:

“Un elemento con display: list-item genera un cuadro de bloque principal para el contenido del elemento y, dependiendo de los valores de list-style-type y list-style-image , posiblemente también un cuadro de marcador como indicación visual de que el elemento es un elemento de la lista.”

El cuadro de bloque principal es el cuadro principal del elemento y contiene todos los elementos secundarios, ya que un elemento de lista puede contener otras marcas. El cuadro marcador se coloca entonces con respecto a este cuadro principal. La especificación continúa detallando el hecho de que cualquier color de fondo estará solo detrás de este cuadro principal, y no del marcador. También que el marcador se puede establecer en uno de un rango de valores predefinidos:

  • disc
  • circle
  • square
  • decimal
  • decimal-leading-zero
  • lower-roman
  • upper-roman
  • lower-greek
  • lower-latin
  • upper-latin
  • armenian
  • georgian
  • lower-alpha
  • upper-alpha
  • none
  • inherit

La especificación de visualización de nivel 3 define display: list-item junto con los otros valores posibles para la propiedad de display . Hace referencia a CSS 2.1, al igual que muchas propiedades y valores de CSS que provienen de CSS2, pero describe la palabra clave list-item como "haciendo que el elemento genere un pseudo-elemento de ::marker ".

La especificación de nivel 3 también presenta la capacidad de crear un elemento de lista en línea con la sintaxis de dos valores que se usa display: inline list-item . Esto aún no está implementado por los navegadores.

Creación de cuadros de marcadores en elementos que no están en la lista

Al igual que con otros valores de display , es perfectamente válido dar a cualquier elemento HTML un tipo de visualización de elemento de list-item (si desea generar un pseudoelemento ::marker en el elemento). Esto no hará que el elemento se convierta semánticamente en un elemento de la lista, sino que solo se mostrará visualmente como un elemento de la lista y, por lo tanto, podrá tener un ::marker . Cuando discutamos el pseudo-elemento ::marker a continuación, descubrirá algunos casos en los que display: list-item puede ser útil.

El CSS enumera la especificación de nivel 3: ::marker y contadores

La especificación display amplía y aclara la definición de listas que encontramos en CSS2, sin embargo, también hay una especificación que define el comportamiento de la lista en detalle: la Especificación de listas CSS Nivel 3. Como el comportamiento básico de los elementos de la lista se define en display , este la especificación detalla el cuadro de marcador generado cuando algo tiene display: list-item junto con los contadores que se usan de forma predeterminada cada vez que crea una lista ordenada. Hay algunas funciones potencialmente útiles a las que se accede a través de estas funciones.

El ::marker Pseudo-Elemento

El pseudoelemento ::marker le permite apuntar al marcador de la lista, independientemente del contenido del elemento de la lista. Esto no era posible en versiones anteriores de CSS, por lo tanto, si cambiaba el color o el tamaño de fuente de ul o li , también cambiaría el color y el tamaño de fuente de los marcadores. Para hacer algo tan aparentemente simple como tener viñetas de lista de diferentes colores que el texto, implicaría envolver el contenido del elemento de la lista en un lapso (o usar una imagen para el marcador).

 ul { color: #00b7a8; } ul span { color #333; }

Con el pseudo elemento ::marker , lo más simple que puede intentar es tener una viñeta diferente al color del texto, lo que significa que en lugar del código en el ejemplo anterior, puede usar:

 ul { color: #333; } ul ::marker { color: #00b7a8; }

También es posible que desee utilizar un tamaño y font-family diferentes para la numeración en una lista ordenada.

 ol ::marker { font-size: 200%; color: #00b7a8; font-family: "Comic Sans MS", cursive, sans-serif; }

Puede ver todo esto en un navegador compatible usando mi ejemplo de CodePen:

Vea el Bolígrafo [Viñetas de colores con y sin marcador](https://codepen.io/rachelandrew/penVJQyoR) de Rachel Andrew.

Vea las viñetas Pen Coloured con y sin rotulador de Rachel Andrew.

Puede usar el pseudoelemento ::marker en elementos que no son de lista. En el siguiente código, he establecido un encabezado para display: list-item . Esto le da una viñeta y, por lo tanto, un cuadro de ::marker para apuntar.

He cambiado la viñeta para usar un emoji:

 h1 { display: list-item; } h1::marker { content: ""; } 
Rumbo con un emoji de gato a la izquierda
En Firefox, puedes ver el emoji utilizado como marcador.

Vea el Pen [Título y marcador](https://codepen.io/rachelandrew/pen/wLyyMG) de Rachel Andrew.

Vea el Encabezado y el rotulador de Rachel Andrew.

En el ejemplo anterior, he usado contenido generado en las reglas para el marcador. Solo un pequeño subconjunto de propiedades CSS está disponible para usar en ::marker . Estos incluyen propiedades de fuente y color, sin embargo, también incluyen la propiedad de content , para incluir contenido generado.

La adición de content como propiedad permitida para ::marker es reciente, sin embargo, está incluida en la implementación de Firefox. La inclusión significa que puede hacer cosas como incluir una cadena de texto en un ::marker . También plantea posibilidades adicionales para el formato de marcadores cuando combina el uso de contadores con ::marker .

Compatibilidad con navegadores y respaldos

Para los navegadores que no admiten el pseudoelemento ::marker , el respaldo es el marcador normal que se habría mostrado de todos modos. Desafortunadamente, actualmente no podemos usar Consultas de funciones para detectar la compatibilidad con selectores como este pseudoelemento en este momento, aunque ha surgido un problema sobre agregar esto a la especificación. Esto significa que no puede bifurcar su código para hacer una cosa cuando tiene soporte y otra cosa si no lo tiene. En la mayoría de los casos, volver al marcador regular será una solución razonable.

Contadores

Las listas ordenadas tienen numeración de lista, algo que se logra mediante un contador CSS. Por lo tanto, la especificación de listas CSS también describe estos contadores. Podemos acceder y crear contadores nosotros mismos que, combinados con el pseudo-elemento ::marker , pueden brindarnos algunas funciones útiles. Estos contadores también se pueden usar en contenido generado normal (sin ::marker ).

Si tengo una lista numerada de pasos (y me gustaría escribir "Paso 1", "Paso 2", etc.), puedo hacerlo usando el contenido generado en mi marcador y agregando el contador list-item , esto representa el contador integrado:

 ::marker { content: "Step " counter(list-item) ": "; } 
Una lista ordenada con el Paso 1, el Paso 2, etc., antes de cada elemento de la lista
En Firefox, verá el contador con el prefijo "Paso".

Vea el Pen [Contadores y marcador](https://codepen.io/rachelandrew/pen/BgRaoz) de Rachel Andrew.

Vea los contadores de bolígrafos y el marcador de Rachel Andrew.

Contadores anidados

Si tiene listas anidadas, una forma común de numerarlas es tener el elemento de nivel superior como un número entero, (1), luego los elementos secundarios como (1.1, 1.2) y sus elementos secundarios (1.1.1, 1.1.2), y así. Puede lograr esto utilizando más funciones de contadores.

Cuando anida listas HTML, terminará con varios contadores del mismo nombre, anidados unos dentro de otros. Se puede acceder al nido de contadores usando la función counters() .

En el código a continuación, estoy usando counters() para formatear mis marcadores de lista como se describe arriba. El primer argumento para counters() es el nombre del contador a usar. Estoy usando el contador list-item incorporado. El segundo argumento es una cadena; esto es lo que se concatenará entre los contadores de salida (estoy usando un . ). Finalmente, agrego un : fuera de la función de contador pero dentro del valor del content para que la salida de mi contador esté separada del contenido por dos puntos.

 ::marker { content: counters(list-item,'.') ':'; color: #00b7a8; font-weight: bold; }

Esto me da la salida como en la imagen. Si está utilizando un navegador que admite ::marker y contadores, puede verlo funcionando en el ejemplo de CodePen: intente cambiar la cadena de un archivo . a otra cosa para ver cómo eso cambia la salida.

Un conjunto de listas anidadas
En Firefox, verá la numeración de listas anidadas separadas por puntos.

Consulte el Pen [Contadores anidados] (https://codepen.io/rachelandrew/pen/VJbwxL) de Rachel Andrew.

Vea los contadores Pen Nested de Rachel Andrew.

¿Cuál es la diferencia entre counter() y counters() ?

La función counter() que usamos en el primer ejemplo para escribir nuestros pasos usa solo el contador más interno. Por lo tanto, en la situación en la que tiene un conjunto de listas anidadas, escribirá el contador relacionado con el nivel en el que se encuentra actualmente.

La función counters() esencialmente escribe toda la rama y le brinda la oportunidad de concatenar una cadena entre contadores en la rama. Entonces, si tiene un elemento de lista con un contador de 2 (que es parte de una lista anidada dentro de un elemento de lista con un contador de 4 ), entonces la rama contiene:

  • 4
  • 2

Puede generar esto como 4.2 en el marcador usando:

 ::marker { content: counters(list-item,'.'); }

Contadores en otros elementos

Los contadores se pueden usar en cosas que no son listas, ya sea para generar un marcador, en cuyo caso el elemento deberá tener display: list-item , o para generar contenido generado regularmente. Los contadores se utilizan ampliamente en la producción de libros, para permitir que la numeración de capítulos y figuras sume otras cosas. No hay razón para no adoptar un enfoque similar en la web, en particular para artículos más largos.

Las propiedades CSS definidas en la especificación de Listas CSS que tratan con estos contadores son:

  • counter-set
  • counter-reset
  • counter-increment

Para ver cómo funcionan fuera de las listas, podemos ver un ejemplo del uso de contadores para numerar los encabezados de un documento.

Lo primero que debo hacer es crear un contador para los encabezados en el elemento del cuerpo, listo para usar. Estoy usando la propiedad counter-reset para hacer esto. Las propiedades counter-reset y counter-set son muy similares. La propiedad counter-reset creará un nuevo contador si aún no existe un contador con el nombre especificado, pero también creará contadores anidados como se describe anteriormente si existe un contador con ese nombre. La propiedad counter-set solo creará un nuevo contador si no hay ningún contador con ese nombre. Para esto, usar cualquier propiedad funcionaría bien, sin embargo, counter-set no tiene un soporte de navegador tan bueno como counter-reset , así que estoy tomando la ruta práctica:

 body { counter-reset: heading-counter; }

Ahora que tengo un contador, puedo usar la propiedad counter-increment en el selector para los encabezados; esto debería incrementar el contador cada vez que el selector coincida.

 h2 { counter-increment: heading-counter; }

Para ver el valor, necesito enviarlo al documento. Puedo hacer esto usando Contenido generado y agregándolo before del encabezado como se muestra en el siguiente ejemplo de CodePen:

 h2::before { content: counter(heading-counter) ": "; color: #00b7a8; font-weight: bold; } 

Consulte el Pen [Títulos y contadores] (https://codepen.io/rachelandrew/pen/gNGjxq) de Rachel Andrew.

Vea los encabezados y contadores de Pen por Rachel Andrew.

Alternativamente, podría convertir el elemento h2 en un elemento list-item y luego usar ::marker , como se muestra a continuación. Como ya se detalló, el uso del elemento ::marker tiene un soporte de navegador limitado. En Firefox, debería ver el contador utilizado como marcador para el encabezado, mientras que otros navegadores mostrarán la viñeta predeterminada.

 h2 { display: list-item; } h2::marker { content: counter(heading-counter) ": "; color: #00b7a8; font-weight: bold; } 

Consulte el Pen [Títulos, marcadores y contadores](https://codepen.io/rachelandrew/pen/pXWZay) de Rachel Andrew.

Vea los encabezados de pluma, marcadores y contadores de Rachel Andrew.

Contadores en elementos de formulario

También hay un poco de interactividad que puede lograr usando CSS Counters, algo que podría pensar que necesita JavaScript para hacer.

Tengo un formulario que tiene varios campos obligatorios. El estado obligatorio se puede seleccionar en CSS con una :required , y el hecho de que un campo no se ha completado se puede detectar mediante la :invalid . Esto significa que podemos verificar los campos que son obligatorios y no válidos, e incrementar un contador. Luego, envíelo como contenido generado.

Consulte el Pen [Recuento de campos de formulario obligatorios] (https://codepen.io/rachelandrew/pen/vqpJdM) de Rachel Andrew.

Consulte los campos de formulario requeridos para el conteo de bolígrafos por Rachel Andrew.

Cuán útil es esto en realidad es discutible, dado que realmente no podemos hacer nada con ese valor más que incluirlo en el contenido generado. También existen preocupaciones con respecto a que el contenido generado sea inaccesible para ciertos lectores de pantalla, por lo tanto, cualquier uso que sea más que decorativo debería garantizar otras formas de acceder a esa información. Lea, "Soporte de accesibilidad para contenido generado CSS" y la información más reciente, "Compatibilidad del lector de pantalla de propiedades de contenido CSS" para obtener más detalles sobre la accesibilidad y el contenido generado.

Sin embargo, demuestra que los contadores pueden lograr cosas más útiles que simplemente enumerar listas. Puede ser que algún día ese conocimiento sí te sirva para solucionar algún problema en el que estés trabajando.

Saber más

Este artículo terminó bastante lejos de diseñar listas, a pesar de que todo lo que he descrito se encuentra en la especificación de Listas CSS. Puede encontrar más información sobre las cosas descritas en los enlaces a continuación. Si ha encontrado un uso interesante para los contadores CSS, o puede pensar en cosas para las que podría usar ::marker , agregue una nota en los comentarios.

  • ::marker
  • counter-set
  • counter-reset
  • counter-increment
  • "Uso de contadores CSS", documentos web de MDN
  • "Contar con contadores CSS y cuadrícula CSS", CSS-Tricks