Pseudo-clases y pseudo-elementos

Intermedio
CSS
CSS
Actualizado: 26/08/2025

Pseudo-clases de estado (:hover, :focus, :active)

Las pseudo-clases de estado son selectores especiales que nos permiten aplicar estilos a elementos HTML basándose en su estado actual o en la interacción del usuario con ellos. Estas pseudo-clases se escriben con un dos puntos : seguido del nombre del estado, y son fundamentales para crear interfaces web interactivas y accesibles.

A diferencia de los selectores básicos que vimos anteriormente, las pseudo-clases no se basan en atributos HTML sino en condiciones dinámicas que cambian según el comportamiento del usuario o el estado del elemento.

La pseudo-clase :hover

La pseudo-clase :hover se activa cuando el usuario coloca el cursor del ratón sobre un elemento, sin necesidad de hacer clic. Es especialmente útil para proporcionar retroalimentación visual inmediata.

button:hover {
  background-color: #007bff;
  color: white;
  transform: scale(1.05);
}

También podemos aplicar efectos hover a elementos de texto, como enlaces:

a:hover {
  color: #ff6b35;
  text-decoration: underline;
  transition: color 0.3s ease;
}

Un uso común es cambiar la apariencia de tarjetas o contenedores cuando el usuario los sobrevuela:

.card:hover {
  box-shadow: 0 8px 16px rgba(0, 0, 0, 0.2);
  transform: translateY(-2px);
  transition: all 0.3s ease;
}

La pseudo-clase :focus

La pseudo-clase :focus se activa cuando un elemento recibe el foco, ya sea mediante navegación con teclado (usando Tab) o al hacer clic sobre él. Es especialmente importante para la accesibilidad web.

input:focus {
  outline: 2px solid #007bff;
  border-color: #007bff;
  box-shadow: 0 0 5px rgba(0, 123, 255, 0.3);
}

Para botones, podemos crear un estilo de foco que sea claramente visible:

button:focus {
  outline: 2px solid #ff6b35;
  outline-offset: 2px;
  background-color: #f8f9fa;
}

Es importante nunca eliminar completamente el outline del foco sin proporcionar una alternativa visual clara, ya que esto afecta la navegación por teclado:

/* ❌ Evitar esto sin alternativa */
button:focus {
  outline: none;
}

/* ✅ Mejor proporcionar un estilo alternativo */
button:focus {
  outline: none;
  box-shadow: 0 0 0 3px rgba(0, 123, 255, 0.5);
}

La pseudo-clase :active

La pseudo-clase :active se activa en el momento exacto en que el usuario hace clic sobre un elemento, desde que presiona hasta que suelta el botón del ratón. Proporciona retroalimentación visual instantánea.

button:active {
  background-color: #0056b3;
  transform: scale(0.95);
  box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.2);
}

Para enlaces, podemos crear un efecto sutil de "presión":

a:active {
  color: #d63384;
  transform: translateY(1px);
}

Combinar pseudo-clases de estado

Podemos combinar múltiples pseudo-clases para crear experiencias de usuario más refinadas. El orden de declaración es importante debido a la especificidad CSS:

/* Orden recomendado: LVHA (Link, Visited, Hover, Active) */
a {
  color: #007bff;
  text-decoration: none;
  transition: all 0.2s ease;
}

a:hover {
  color: #0056b3;
  text-decoration: underline;
}

a:focus {
  outline: 2px solid #007bff;
  outline-offset: 2px;
}

a:active {
  color: #003d82;
  transform: translateY(1px);
}

También podemos crear efectos combinados para botones interactivos:

.btn {
  background-color: #28a745;
  color: white;
  padding: 12px 24px;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  transition: all 0.2s ease;
}

.btn:hover {
  background-color: #218838;
  transform: translateY(-1px);
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
}

.btn:focus {
  outline: 2px solid #20c997;
  outline-offset: 2px;
}

.btn:active {
  background-color: #1e7e34;
  transform: translateY(0);
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
}

Mejorar la experiencia con transiciones

Para crear interacciones fluidas, es recomendable usar la propiedad transition junto con las pseudo-clases de estado:

.nav-item {
  padding: 10px 15px;
  background-color: transparent;
  border-radius: 6px;
  transition: background-color 0.3s ease, transform 0.2s ease;
}

.nav-item:hover {
  background-color: #f8f9fa;
  transform: scale(1.02);
}

.nav-item:active {
  background-color: #e9ecef;
  transform: scale(0.98);
}

Las pseudo-clases de estado son esenciales para crear interfaces web modernas que respondan intuitivamente a las acciones del usuario, mejorando tanto la usabilidad como la accesibilidad de nuestras páginas web.

Pseudo-clases estructurales (:first-child, :nth-child)

Las pseudo-clases estructurales nos permiten seleccionar elementos basándose en su posición dentro de la estructura del documento HTML. A diferencia de las pseudo-clases de estado que vimos anteriormente, estas se basan en la relación jerárquica entre elementos hermanos y su posición relativa dentro de su contenedor padre.

Estas pseudo-clases son especialmente útiles para crear patrones de diseño sin necesidad de añadir clases adicionales al HTML, lo que resulta en un código más limpio y mantenible.

La pseudo-clase :first-child

La pseudo-clase :first-child selecciona el primer elemento hijo de su contenedor padre, independientemente del tipo de elemento que sea.

/* Selecciona el primer párrafo dentro de cualquier contenedor */
p:first-child {
  font-weight: bold;
  color: #2c3e50;
  margin-top: 0;
}

Un uso común es eliminar márgenes superiores del primer elemento para lograr un espaciado más consistente:

.content > *:first-child {
  margin-top: 0;
}

También podemos usarla para destacar el primer elemento de una lista:

ul li:first-child {
  background-color: #e8f4fd;
  border-left: 4px solid #007bff;
  padding-left: 16px;
}

La pseudo-clase :last-child

De manera similar, :last-child selecciona el último elemento hijo dentro de su contenedor:

/* Elimina el margen inferior del último párrafo */
.article p:last-child {
  margin-bottom: 0;
}

Es especialmente útil para ajustar espaciados y crear separaciones visuales limpias:

.nav-item:last-child {
  border-right: none;
}

.card:last-child {
  margin-bottom: 0;
}

La pseudo-clase :nth-child()

La pseudo-clase :nth-child() es la más versátil de las pseudo-clases estructurales, ya que nos permite seleccionar elementos específicos usando fórmulas matemáticas.

Selección por número específico:

/* Selecciona el tercer elemento */
li:nth-child(3) {
  background-color: #fff3cd;
  font-weight: bold;
}

Selección de elementos pares e impares:

/* Elementos pares (2, 4, 6, 8...) */
tr:nth-child(even) {
  background-color: #f8f9fa;
}

/* Elementos impares (1, 3, 5, 7...) */
tr:nth-child(odd) {
  background-color: white;
}

Usando fórmulas matemáticas:

/* Cada tercer elemento (3, 6, 9, 12...) */
.grid-item:nth-child(3n) {
  margin-right: 0;
}

/* Cada tercer elemento empezando desde el segundo (2, 5, 8, 11...) */
.card:nth-child(3n+2) {
  transform: scale(1.05);
}

Pseudo-clases por tipo de elemento

Las pseudo-clases :first-of-type y :last-of-type seleccionan elementos basándose en su tipo, no en su posición absoluta:

/* El primer h2 dentro de su contenedor */
h2:first-of-type {
  color: #e74c3c;
  font-size: 2.5rem;
}

/* La última imagen dentro de su contenedor */
img:last-of-type {
  border: 2px solid #3498db;
  border-radius: 8px;
}

La pseudo-clase :nth-of-type() funciona de manera similar a :nth-child() pero considera solo elementos del mismo tipo:

/* Cada segundo párrafo */
p:nth-of-type(2n) {
  font-style: italic;
  padding-left: 20px;
}

/* El tercer artículo específicamente */
article:nth-of-type(3) {
  background-color: #f1f3f4;
  padding: 24px;
}

Pseudo-clases para elementos únicos

Las pseudo-clases :only-child y :only-of-type seleccionan elementos que son únicos en su contexto:

/* Párrafo que es el único hijo de su contenedor */
p:only-child {
  text-align: center;
  font-size: 1.2rem;
}

/* Imagen que es la única de su tipo en el contenedor */
img:only-of-type {
  display: block;
  margin: 0 auto;
  max-width: 100%;
}

Aplicaciones prácticas en diseños reales

Creación de patrones de cebra en tablas:

table {
  width: 100%;
  border-collapse: collapse;
}

tr:nth-child(even) {
  background-color: #f8f9fa;
}

tr:hover {
  background-color: #e3f2fd;
}

Espaciado inteligente en listas de navegación:

.nav {
  display: flex;
  list-style: none;
  padding: 0;
}

.nav li:not(:last-child) {
  margin-right: 24px;
}

.nav li:first-child a {
  font-weight: bold;
}

Diseño de tarjetas con patrones específicos:

.card-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 20px;
}

/* Cada tercera tarjeta tiene un estilo especial */
.card:nth-child(3n) {
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  color: white;
}

/* La primera tarjeta siempre destacada */
.card:first-child {
  grid-column: span 2;
  font-size: 1.1rem;
}

Combinar pseudo-clases estructurales

Podemos combinar múltiples pseudo-clases para crear selecciones más específicas:

/* Primer párrafo que también es el último (párrafo único) */
p:first-child:last-child {
  text-align: center;
  font-size: 1.3rem;
  padding: 20px;
  background-color: #e8f5e8;
}

/* Elementos pares que no sean el último */
li:nth-child(even):not(:last-child) {
  border-bottom: 1px solid #dee2e6;
}

Creación de layouts complejos sin clases adicionales:

/* Galería de imágenes con patrón específico */
.gallery img:nth-child(4n+1) {
  grid-column: span 2;
}

.gallery img:nth-child(4n+2) {
  grid-row: span 2;
}

.gallery img:nth-child(4n+3),
.gallery img:nth-child(4n+4) {
  filter: grayscale(20%);
}

Las pseudo-clases estructurales nos proporcionan un control preciso sobre la selección de elementos basándose en su posición y tipo, permitiendo crear diseños sofisticados y patrones visuales consistentes sin necesidad de modificar el HTML o añadir clases adicionales.

Pseudo-elementos (::before, ::after, ::first-line)

Los pseudo-elementos son selectores especiales que nos permiten estilizar partes específicas de un elemento o insertar contenido adicional sin modificar el HTML. A diferencia de las pseudo-clases que vimos anteriormente, los pseudo-elementos crean elementos virtuales que podemos manipular como si fueran elementos reales del DOM.

La sintaxis moderna utiliza doble dos puntos (::) para distinguirlos claramente de las pseudo-clases, aunque algunos navegadores aún soportan la sintaxis antigua de dos puntos simples por compatibilidad.

Los pseudo-elementos ::before y ::after

Los pseudo-elementos ::before y ::after son los más utilizados y versátiles. Permiten insertar contenido antes o después del contenido de un elemento, creando elementos virtuales que podemos estilizar completamente.

Sintaxis básica y propiedad content:

.elemento::before {
  content: "Contenido insertado";
  color: #007bff;
  font-weight: bold;
}

.elemento::after {
  content: " ✓";
  color: #28a745;
  font-size: 1.2em;
}

La propiedad content es obligatoria para que los pseudo-elementos ::before y ::after sean visibles. Sin ella, no aparecerán en la página:

/* ❌ No funcionará - falta la propiedad content */
.btn::after {
  background-color: red;
  width: 10px;
  height: 10px;
}

/* ✅ Funcionará correctamente */
.btn::after {
  content: "";
  background-color: red;
  width: 10px;
  height: 10px;
  display: inline-block;
}

Casos de uso prácticos con ::before y ::after

Creación de iconos decorativos:

.info::before {
  content: "ℹ️";
  margin-right: 8px;
  color: #17a2b8;
}

.warning::before {
  content: "⚠️";
  margin-right: 8px;
  color: #ffc107;
}

Elementos decorativos y formas geométricas:

.card {
  position: relative;
  padding: 20px;
  background-color: white;
  border-radius: 8px;
}

.card::before {
  content: "";
  position: absolute;
  top: -5px;
  left: 20px;
  width: 0;
  height: 0;
  border-left: 10px solid transparent;
  border-right: 10px solid transparent;
  border-bottom: 10px solid white;
}

Superposiciones y efectos visuales:

.image-overlay {
  position: relative;
  display: inline-block;
}

.image-overlay::after {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: linear-gradient(135deg, rgba(0,0,0,0.3), rgba(0,0,0,0.1));
  opacity: 0;
  transition: opacity 0.3s ease;
}

.image-overlay:hover::after {
  opacity: 1;
}

Creación de contadores y numeración automática

Los pseudo-elementos son especialmente útiles para crear sistemas de numeración automática:

.steps {
  counter-reset: step-counter;
}

.step {
  counter-increment: step-counter;
  position: relative;
  padding-left: 40px;
  margin-bottom: 20px;
}

.step::before {
  content: counter(step-counter);
  position: absolute;
  left: 0;
  top: 0;
  width: 24px;
  height: 24px;
  background-color: #007bff;
  color: white;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: bold;
  font-size: 14px;
}

El pseudo-elemento ::first-line

El pseudo-elemento ::first-line nos permite estilizar específicamente la primera línea de texto de un elemento, sin importar dónde termine esa línea según el ancho del contenedor:

.intro::first-line {
  font-weight: bold;
  color: #2c3e50;
  font-size: 1.1em;
  text-transform: uppercase;
  letter-spacing: 1px;
}

Es importante tener en cuenta que ::first-line solo acepta ciertas propiedades CSS:

/* ✅ Propiedades permitidas con ::first-line */
p::first-line {
  font-family: 'Georgia', serif;
  font-size: 1.2em;
  font-weight: bold;
  color: #e74c3c;
  text-decoration: underline;
  letter-spacing: 0.5px;
  line-height: 1.4;
}

/* ❌ Estas propiedades no funcionarán con ::first-line */
p::first-line {
  padding: 10px; /* No permitido */
  margin: 5px;   /* No permitido */
  border: 1px solid red; /* No permitido */
}

El pseudo-elemento ::first-letter

Similar a ::first-line, el pseudo-elemento ::first-letter permite estilizar la primera letra de un elemento, creando efectos de capitular:

.article::first-letter {
  font-size: 3em;
  font-weight: bold;
  color: #8b4513;
  float: left;
  line-height: 0.8;
  padding-right: 8px;
  padding-top: 4px;
  font-family: 'Times New Roman', serif;
}

Pseudo-elementos para formularios

Los pseudo-elementos son especialmente útiles para mejorar la apariencia de elementos de formulario:

.input-group {
  position: relative;
}

.input-group input {
  padding-left: 40px;
  border: 2px solid #e9ecef;
  border-radius: 6px;
}

.input-group.email::before {
  content: "✉";
  position: absolute;
  left: 12px;
  top: 50%;
  transform: translateY(-50%);
  color: #6c757d;
  font-size: 18px;
}

.input-group.phone::before {
  content: "📞";
  position: absolute;
  left: 12px;
  top: 50%;
  transform: translateY(-50%);
  color: #6c757d;
  font-size: 16px;
}

Técnicas avanzadas con pseudo-elementos

Creación de tooltips personalizados:

.tooltip {
  position: relative;
  cursor: help;
}

.tooltip::after {
  content: attr(data-tooltip);
  position: absolute;
  bottom: 125%;
  left: 50%;
  transform: translateX(-50%);
  background-color: #333;
  color: white;
  padding: 8px 12px;
  border-radius: 4px;
  font-size: 14px;
  white-space: nowrap;
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.3s, visibility 0.3s;
}

.tooltip::before {
  content: "";
  position: absolute;
  bottom: 115%;
  left: 50%;
  transform: translateX(-50%);
  width: 0;
  height: 0;
  border-left: 5px solid transparent;
  border-right: 5px solid transparent;
  border-top: 5px solid #333;
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.3s, visibility 0.3s;
}

.tooltip:hover::after,
.tooltip:hover::before {
  opacity: 1;
  visibility: visible;
}

Efectos de carga y animaciones:

.loading {
  position: relative;
  color: transparent;
}

.loading::after {
  content: "Cargando...";
  position: absolute;
  top: 0;
  left: 0;
  color: #007bff;
  animation: loading-dots 1.5s infinite;
}

@keyframes loading-dots {
  0%, 20% { content: "Cargando."; }
  40% { content: "Cargando.."; }
  60%, 80% { content: "Cargando..."; }
}

Consideraciones importantes

Los pseudo-elementos ::before y ::after se comportan como elementos inline por defecto, por lo que frecuentemente necesitarás cambiar su display:

.elemento::before {
  content: "";
  display: block; /* o inline-block, flex, etc. */
  width: 100px;
  height: 50px;
  background-color: #f8f9fa;
}

Además, estos pseudo-elementos no funcionan con elementos que no pueden contener contenido, como <img>, <input>, <br>, o elementos de auto-cierre.

Fuentes y referencias

Documentación oficial y recursos externos para profundizar en CSS

Documentación oficial de CSS
Alan Sastre - Autor del tutorial

Alan Sastre

Ingeniero de Software y formador, CEO en CertiDevs

Ingeniero de software especializado en Full Stack y en Inteligencia Artificial. Como CEO de CertiDevs, CSS es una de sus áreas de expertise. Con más de 15 años programando, 6K seguidores en LinkedIn y experiencia como formador, Alan se dedica a crear contenido educativo de calidad para desarrolladores de todos los niveles.

Más tutoriales de CSS

Explora más contenido relacionado con CSS y continúa aprendiendo con nuestros tutoriales gratuitos.

Aprendizajes de esta lección

  • Comprender qué son y cómo funcionan las pseudo-clases de estado como :hover, :focus y :active.
  • Aprender a utilizar pseudo-clases estructurales para seleccionar elementos según su posición en el DOM.
  • Conocer la sintaxis y aplicaciones prácticas de los pseudo-elementos ::before, ::after, ::first-line y ::first-letter.
  • Aplicar transiciones y combinaciones de pseudo-clases para mejorar la experiencia de usuario.
  • Explorar técnicas avanzadas con pseudo-elementos para crear efectos visuales y funcionales sin modificar el HTML.