css-pseudo-elementos-before-after

Pseudo-elementos before y after en CSS

  • 4 min

Un pseudo-elemento en CSS es una parte virtual de un elemento que podemos estilizar sin añadir una etiqueta real al HTML.

Si las pseudo-clases (:hover, :focus, :nth-child) sirven para seleccionar un elemento según su estado o posición, los pseudo-elementos sirven para apuntar a fragmentos concretos o piezas generadas por CSS.

El símbolo ! lo ha puesto css

Los reconoceréis porque se escriben con doble dos puntos (::). En esta entrada nos vamos a centrar en los dos más usados: ::before y ::after.

::before y ::after

::before crea contenido virtual antes del contenido real del elemento. ::after lo crea después del contenido real.

<p class="mensaje">Hola mundo</p>
Copied!
.mensaje::before {
    content: "👉 ";
}

.mensaje::after {
    content: " ✅";
}
Copied!

Visualmente, el navegador mostrará algo parecido a:

👉 Hola mundo ✅

En el HTML, esos dos emojis no existen. Los ha generando CSS en el momento de pintar la página.

Durante años veréis ejemplos con un solo : (:before, :after). Hoy lo correcto es usar ::before y ::after, porque estamos hablando de pseudo-elementos, no de pseudo-clases.

La propiedad content

Para que ::before y ::after existan, necesitan la propiedad content. Puede contener texto, una cadena vacía o incluso valores sacados de atributos.

blockquote::before {
    content: "«";
    font-size: 2rem;
    color: #94a3b8;
}

blockquote::after {
    content: "»";
    font-size: 2rem;
    color: #94a3b8;
}
Copied!

Si el pseudo-elemento es puramente decorativo, usamos content: "".

h2::after {
    content: "";
    display: block;
    width: 48px;
    height: 4px;
    margin-top: 0.5rem;
    background: #2563eb;
}
Copied!

Sin content, ::before y ::after no aparecen (vale content “vacio”)

Podéis tener width, height, background, position y una tesis doctoral escrita dentro, que si falta content, el pseudo-elemento no se dibuja.

Ejemplo completo: aviso con icono

Vamos a crear una caja de aviso con un icono generado por CSS, como el que hemos visto al principio del artículo

El texto importante sigue estando en HTML, y el icono es solo apoyo visual.

<p class="aviso">Revisa los campos obligatorios antes de enviar.</p>
Copied!
.aviso {
    position: relative;
    padding: 1rem 1rem 1rem 3rem;
    border-left: 4px solid #f59e0b;
    background: #fffbeb;
}

.aviso::before {
    content: "!";
    position: absolute;
    left: 1rem;
    top: 50%;
    width: 1.4rem;
    height: 1.4rem;
    border-radius: 50%;
    background: #f59e0b;
    color: white;
    font-weight: bold;
    text-align: center;
    line-height: 1.4rem;
    transform: translateY(-50%);
}
Copied!

Este patrón se repite muchísimo en interfaces: iconos, líneas decorativas, badges, flechas, separadores… pequeñas piezas visuales que no merecen una etiqueta propia.