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.
! lo ha puesto cssLos 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>
.mensaje::before {
content: "👉 ";
}
.mensaje::after {
content: " ✅";
}
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;
}
Si el pseudo-elemento es puramente decorativo, usamos content: "".
h2::after {
content: "";
display: block;
width: 48px;
height: 4px;
margin-top: 0.5rem;
background: #2563eb;
}
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>
.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%);
}
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.
