Contadores CSS

CSS Counters: Contando con CSS


Si conocemos los estilos que es posible darle a una lista con CSS es posible que nos interese conocer la posibilidad de crear contadores personalizados con CSS y utilizarlos en nuestras páginas para contar diferentes elementos de la misma, además de crear sistemas de numeración personalizados y adaptados a nuestros criterios.

Propiedades de contador

Para empezar, en CSS podemos crear un contador CSS. Básicamente, lo único que tenemos que hacer es asignarle un id o nombre, que nos permitirá hacer referencia a él posteriormente. Veamos que propiedades podemos utilizar para esto:

PropiedadesValoresDescripción
counter-resetid valor inicial | noneResetea el contador id al valor inicial (0 por defecto).
counter-incrementIncrementa un contador, indicándole su id de referencia.
counter-setid valor inicial | noneSimilar a counter-reset, pero no realiza incremento si existe.

En primer lugar, tenemos las propiedades counter-reset y counter-increment que no hacen otra cosa más que resetear a cero o incrementar un contador CSS, indicándole el nombre o id del mismo.

La función counter()

Sin embargo, necesitamos mostrarlo de alguna forma o sería inútil. Para ello, podemos utilizar la función CSS counter(), que se suele utilizar junto a la propiedad content en pseudoelementos ::before o ::after.

A dicha función, se le debe pasar de forma obligatoria el id del contador, y de forma opcional el tipo de contador que queremos utilizar, que de no hacerlo, tomará por defecto el tipo decimal:

FunciónDescripción
counter(id,type)Usa el contador con id aplicando un estilo type.

Así pues, veamos un ejemplo en acción con lo que hemos visto hasta ahora. El siguiente ejemplo incorpora 3 elementos con clase item que queremos contabilizar, a pesar de no ser una lista y, además, teniendo contenido de por medio.

.item {
  counter-increment: detail-counter;
}

.item::before {
  content: counter(detail-counter) " ";
  font-weight: bold;
  color: red;
}
<div class="content">
  <p>Esto es un ejemplo de varios detalles:</p>

  <div class="item">Detalle A</div>
  <div>Explicación opcional del detalle.</div>
  <div class="item">Detalle B</div>
  <div class="item">Detalle C</div>

  <p>Otro contenido no relevante.</p>
</div>

Para ello, establecemos un incremento en cada elemento con clase .item y además, inmediatamente antes de ese elemento, colocamos visualmente el contador, en rojo y negrita, seguido de un espacio en blanco. Observa que el contador lo hemos llamado detail-counter, aunque se podría llamar de cualquier otra forma.

Aunque no se muestre explícitamente, es como si tuvieramos un counter-reset: detail-counter 0 en el elemento .content, que es el que inicializa todo a 0. El contador se inicializa en 0 pero realiza el primer incremento antes de mostrar el valor, por lo que los números contarán a partir del 1.

En la función counter() no indicamos tipo, por lo tanto usará el tipo decimal por defecto. Si quieres saber que otros tipos existen, echa un vistazo al artículo de Listas CSS.

Creación de contadores

Si necesitamos algún tipo de contador personalizado y no nos bastan con los que incorpora CSS, es posible crearlo y customizarlo a nuestro gusto, mediante la regla @counter-style. Básicamente, te permite crear un tipo de contador, y decirle los símbolos que vamos a utilizar.

ReglaDescripción
@counter-style nombreCrea un tipo de numeración para utilizar en contadores CSS.

Dentro de la regla @counter-style, en la que debemos especificar un nombre para hacer referencia, podemos utilizar varias propiedades. Veamos un ejemplo sencillo, en el que creamos un sistema de numeración llamado spanish que cuenta los números del uno al tres, colocándole a cada uno el sufijo »:

@counter-style spanish {
  system: cyclic;
  symbols: "uno" "dos" "tres";
  suffix: "» ";
}

ul {
  list-style-type: spanish;
}

li::marker {
  color: red;
}
<ul>
  <li>Primer elemento.</li>
  <li>Segundo elemento.</li>
  <li>Tercer elemento.</li>
</ul>

Observa que al establecer un sistema cíclico, una vez terminamos el tres, volvemos a empezar en uno. Además de system, symbols y suffix existen otras propiedades que se pueden utilizar en las reglas @counter-style, echemos un vistazo y expliquemos para que funcionan y que valores pueden tomar:

PropiedadDescripción
systemEstablece el sistema de repetición al terminar los símbolos. El valor por defecto es symbolic.
symbolsIndica los símbolos de nuestro sistema de numeración, separados por espacios.
additive-symbolsIndica los símbolos de nuestro sistema de numeración de forma acumulativa.
suffixIndica un sufijo que aparecerá siempre al final.
prefixIndica un prefijo que aparecerá siempre al principio.
negativeIndica el prefijo y sufijo que tendrían los valores negativos.
rangeLimita el ámbito del contador.
padIndica la longitud y relleno que usará. Por defecto, el valor es 0 ""
fallbackIndica un tipo de contador de fallback, en caso de que no pueda crearse.
speak-asIndica como representará el contador un sintetizador de voz.

Vayamos una por una y veamos que valores pueden tomar.

La propiedad system

Un sistema de numeración puede comportarse de varias formas. Tenemos una propiedad denominada system que permite indicar uno de los siguientes valores y determinar su comportamiento:

ValorDescripciónEjemplo
cyclicEstablece un comportamiento cíclico.A B C -> A, B, C, A, B, C, A...
fixedEstablece una numeración de un número finito de elementos.A B C -> A, B, C, 4, 5, 6...
symbolicEstable un patrón repetible y acumulable.A B C -> A, B, C, AA, BB, CC, AAA...
alphabeticEstable un patrón alfabético repetible y acumulable.A B C -> A, B, C, AA, AB, AC, BA, BB, BC, CA...
numericEstablece un patrón numérico repetible con cero.A B C -> B, C, BA, BB, BC, CA, CB, CC, BAA, BAB...
additiveEstablece un patrón añadiendo símbolos asociados y acumulables.⚀, ⚁, ⚂, ⚃, ⚄, ⚅, ⚅⚀, ⚅⚁, ⚅⚂, ⚅⚃, ⚅⚄, ⚅⚅, ⚅⚅⚀...
extendsSimplemente extiende un sistema con un sufijo o prefijo.") " -> 1), 2), 3), 4), 5), 6), 7), 8), 9)...

A continuación, observa la combinación de un system: additive junto a la propiedad additive-symbols para crear combinaciones de símbolos, ya que es ligeramente diferente a las anteriores:

@counter-style dice {
  system: additive;
  additive-symbols: 6 ⚅, 5 ⚄, 4 ⚃, 3 ⚂, 2 ⚁, 1 ⚀;
  suffix: " ";
}

ul {
  list-style-type: dice;
  font-size: 2rem;
}

li::marker {
  color: red;
}
<ul>
  <li>Primer elemento.</li>
  <li>Segundo elemento.</li>
  <li>Tercer elemento.</li>
  <li>Cuarto elemento.</li>
  <li>Quinto elemento.</li>
  <li>Sexto elemento.</li>
</ul>

La propiedad symbols

Mediante la propiedad symbols, o la propiedad additive-symbols, podemos establecer una lista de símbolos para crear nuestro sistema de numeración. Además de establecer una lista de símbolos, también es posible añadir una lista de imágenes, mediante la función url(imagen.png), por ejemplo.

La propiedad negative

La propiedad negative espera dos parámetros. El primero de esos parámetros será el que se añadirá justo ante de un símbolo negativo. Por otro lado, el segundo parámetro será el que se añadirá justo después de un símbolo negativo. Veamos dos ejemplos:

/* (2), (1), 0, 1, 2, 3, 4, 5, 6, 7, 8... */
@counter-style negative-paren {
  system: numeric;
  symbols: "0" "1" "2" "3" "4" "5" "6" "7" "8" "9";
  negative: "(-" ")";
}

/* -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8... */
@counter-style negative-minus {
  system: numeric;
  symbols: "0" "1" "2" "3" "4" "5" "6" "7" "8" "9";
  negative: "-" "";
}

ol {
  list-style-type: negative-paren;
}
<ol start="2" reversed>
  <li>Elemento dos.</li>
  <li>Elemento uno.</li>
  <li>Elemento cero.</li>
  <li>Elemento menos uno.</li>
  <li>Elemento menos dos.</li>
  <li>Elemento menos tres.</li>
</ol>

La propiedad range

Con la propiedad range podemos utilizar el valor auto o uno personalizado. De indicar el valor auto, se establecerá un rango dependiendo del valor indicado en la propiedad system. Por lo tanto:

  • Para sistemas cyclic, numeric o fixed, el rango va desde -∞ a .
  • Para sistemas alphabetic o symbolic, el rango va desde 1 a .
  • Para sistemas additive, el rango va desde 0 a .
  • Para sistemas extends, se adapta al estilo extendido.

La propiedad pad

Mediante la propiedad pad se puede rellenar con ceros (o con otros carácteres) el sistema de numeración que queramos utilizar. Por ejemplo, para extender el sistema decimal y obtener los siguientes valores: 001, 002, 003, 004, 005, 006, etc... necesitaremos hacer lo siguiente:

@counter-style decimal-zeropad {
  system: extends decimal;
  pad: 3 "0";
}

ul {
  list-style-type: decimal-zeropad;
}
<ul>
  <li>Primer elemento.</li>
  <li>Segundo elemento.</li>
  <li>Tercer elemento.</li>
  <li>Cuarto elemento.</li>
  <li>Quinto elemento.</li>
  <li>Sexto elemento.</li>
</ul>

Ten en cuenta que la propiedad pad permite definir un primer parámetro que será el número de dígitos que debe tener el número del contador, mientras que el segundo parámetro será el relleno que utilizará a la izquierda hasta llegar a ese número de dígitos indicado anteriormente.

La propiedad fallback

La propiedad fallback simplemente determina el tipo de sistema que va a utilizarse en el caso de que no se pueda usar algún otro que haya sido indicado. Por defecto, si no se especifica, utilizará decimal.

La propiedad speak-as

La propiedad speak-as intenta garantizar que los contadores se puedan no solo ver visualmente a través de un navegador, sino reproducir a través de sintetizadores de voz y sistemas equivalentes. Con esta propiedad puedes determinar como se comportará al leerlo, indicando uno de los siguientes valores:

ValorDescripción
autoSi system es alphabetic, usa spell-out. Si es cyclic, usa bullets. En otro caso, usa numbers.
bulletsLee la lista como si fuera una lista sin orden.
numbersLee la lista como si fuera una lista numerada.
wordsLee la lista como un valor textual. Si contiene imágenes, las lee como numbers.
spell-outLee la lista como un valor textual, letra a letra. Si no reconoce símbolos, los lee como numbers.
nombreLee la lista como se declara, sino actua como auto.

Esto proporcionará una mejor accesibilidad a nuestras listas o contadores de cara a sintentizadores de voz o lectores de accesibilidad.

¿Quién soy yo?

Soy Manz, vivo en Tenerife (España) y soy streamer partner en Twitch y profesor. Me apasiona el universo de la programación web, el diseño y desarrollo web y la tecnología en general. Aunque soy full-stack, mi pasión es el front-end, la terminal y crear cosas divertidas y locas.

Puedes encontrar más sobre mi en Manz.dev