CSS Moderno 2025 Potente

Selector :has() El "Selector Padre" de CSS

El selector :has() permite aplicar estilos a elementos padre basándose en sus elementos hijos. Es como tener lógica condicional directamente en CSS, sin necesidad de JavaScript para estados dinámicos.

🧠
Lógica Condicional if/else puro en CSS
🎯
Parent Selector Estilos padre según hijos
Sin JavaScript Estados dinámicos nativos

Formulario Inteligente Observa cómo el formulario cambia según su contenido

1

Escribe en los campos para ver cómo el formulario detecta automáticamente el contenido

2

Haz click en "Validar" para simular errores y ver la magia del :has()

3

Observa los cambios automáticos en colores, bordes y mensajes

Registro de Usuario

Este formulario usa :has() para cambiar automáticamente según su estado

Ingresa tu contraseña
Completa el formulario para continuar

¿Qué está pasando aquí?

🎯
form:has(.error) El formulario detecta si tiene inputs con errores
form:has(:valid) Cambia de color cuando todos los campos son válidos
🎨
form:has(:focus) Se ilumina cuando algún campo tiene focus

Código del Formulario Inteligente Ejemplos prácticos del selector :has()

1. Detectar Errores en el Formulario

CSS
/* Formulario normal */
.smart-form {
  border: 2px solid var(--border-color);
  background: var(--surface);
}

/* ¡MAGIA! Si el formulario TIENE inputs con errores */
.smart-form:has(.form-input.error) {
  border-color: var(--error);
  background: color-mix(in srgb, var(--error) 5%, var(--surface));
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--error) 10%, transparent);
}

/* Si el formulario TIENE campos válidos */
.smart-form:has(.form-input:valid):not(:has(.error)) {
  border-color: var(--success);
  background: color-mix(in srgb, var(--success) 3%, var(--surface));
}

2. Labels Inteligentes

CSS
/* Label normal */
.form-label {
  color: var(--text-primary);
}

/* Si el grupo TIENE un input con error */
.form-group:has(.form-input.error) .form-label {
  color: var(--error);
}

/* Si el grupo TIENE un input enfocado */
.form-group:has(.form-input:focus) .form-label {
  color: var(--primary-color);
  transform: scale(1.02);
}

/* Si el grupo TIENE un input válido */
.form-group:has(.form-input:valid):not(:has(.error)) .form-label {
  color: var(--success);
}

3. Botones que Reaccionan

CSS
/* Botón submit deshabilitado por defecto */
.form-button--submit {
  opacity: 0.5;
  cursor: not-allowed;
}

/* Si el form TIENE todos los campos requeridos válidos */
.smart-form:has(#name:valid):has(#email:valid):has(#password:valid):has(#terms:checked) .form-button--submit {
  opacity: 1;
  cursor: pointer;
  background: linear-gradient(45deg, var(--success), var(--primary-color));
}

/* Si el form TIENE errores, botón validar cambia */
.smart-form:has(.error) .form-button--validate {
  background: var(--warning);
  animation: pulse 2s infinite;
}

4. Combinaciones Avanzadas

CSS
/* Si el form TIENE password field Y está enfocado */
.smart-form:has(input[type="password"]:focus) {
  --form-accent: var(--warning);
}

/* Si el form TIENE checkboxes marcados */
.smart-form:has(input[type="checkbox"]:checked) .form-status {
  background: color-mix(in srgb, var(--success) 10%, transparent);
}

/* Si el form NO TIENE errores Y TIENE campos válidos */
.smart-form:not(:has(.error)):has(:valid) {
  background: linear-gradient(135deg, 
    color-mix(in srgb, var(--success) 3%, var(--surface)),
    color-mix(in srgb, var(--primary-color) 2%, var(--surface))
  );
}

Casos de Uso del :has() Más allá de los formularios

📝

Formularios Dinámicos

Validación visual instantánea, campos que se adaptan según el contenido, estados de carga sin JavaScript.

form:has(.error) { /* estilos */ }
🛒

E-commerce

Carrito que cambia según productos, productos que muestran badges según stock, categorías que se destacan.

.cart:has(.item) { /* mostrar total */ }
📊

Dashboards

Paneles que cambian según datos, gráficos que se adaptan según contenido, alertas automáticas.

.dashboard:has(.alert) { /* modo emergencia */ }
🎨

Interfaces Adaptativas

Layouts que se reorganizan según contenido, modales que se ajustan, navegación contextual.

.sidebar:has(.submenu) { /* expandir */ }

Soporte de Navegadores :has() en producción

🌐
Chrome 105+ ✅
🦊
Firefox 121+ ✅
🧭
Safari 15.4+ ✅
🔷
Edge 105+ ✅

Graceful degradation:

@supports not selector(:has(*)) {
  /* Estilos fallback para navegadores sin :has() */
  .smart-form.has-error { /* clase añadida via JS */ }
  .form-group.field-error .form-label { color: var(--error); }
}