Feature queries CSS
Las container queries preguntan qué ancho tiene un padre. Las media queries miran el viewport. Las feature queries plantean otra cosa del todo: ¿entiende este navegador este CSS? Con @supports envías una base fiable y desbloqueas el layout o los selectores modernos solo donde funcionan.
Mejora progresiva, no una apuesta
Una feature query es una puerta de capacidad. No borras los estilos antiguos: mantienes un layout que funciona en todas partes y añades una capa más rica dentro de @supports cuando el motor puede parsear la característica que necesitas (por ejemplo display: grid o gap en flex).
@supports básico
La forma habitual prueba un par propiedad–valor. Si el navegador puede manejar esa declaración, se aplican las reglas anidadas:
.card-list {
display: block;
}
.card-list .card {
margin-bottom: 1rem;
padding: 1rem;
border: 1px solid #e2e8f0;
border-radius: 0.75rem;
background: #fff;
}
@supports (display: grid) {
.card-list {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
gap: 1rem;
}
.card-list .card {
margin-bottom: 0;
}
}
Fuera del bloque, las tarjetas se apilan con un margen sencillo. Dentro de @supports (display: grid), la misma lista pasa a ser una rejilla adaptable: los motores viejos conservan la pila; los modernos obtienen el grid.
Combinar condiciones: and, or, not
Puedes exigir varias características, aceptar alternativas o invertir la prueba:
@supports (display: grid) and (gap: 1rem) {
.toolbar {
display: grid;
grid-auto-flow: column;
gap: 0.75rem;
align-items: center;
}
}
@supports (display: flex) or (display: grid) {
.cluster {
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
}
}
@supports not (display: grid) {
.card-list .card {
max-width: 36rem;
}
}
and estrecha la puerta (tienen que pasar las dos). or la amplía. not estiliza la ruta sin soporte — útil como fallback deliberado, siempre que ese fallback sea honesto y visible.
Probar selectores con selector()
Algunas características son selectores, no propiedades. Envuélvelas en selector() para que la consulta pregunte: «¿puedes parsear este selector?»
.nav a {
color: #0f172a;
text-decoration: none;
}
@supports selector(:has(*)) {
.nav:has(a:focus-visible) {
outline: 2px solid #2563eb;
outline-offset: 4px;
}
.card:has(img) .title {
font-weight: 700;
}
}
Sin selector(), un :has() suelto dentro de @supports no es el patrón fiable. Con él, los navegadores que no tienen :has() simplemente omiten las reglas mejoradas y conservan los estilos base de los enlaces.
¿Quién hace cada pregunta?
📊 Media, container, and feature queries
| Pregunta que planteas | Preferido para | Herramienta habitual |
|---|---|---|
| ¿Qué ancho tiene el viewport / contexto del dispositivo? | Cáscara de página, breakpoints | @media (…) |
| ¿Qué ancho tiene este padre alrededor del componente? | Tarjetas en huecos desiguales | @container (…) tras container-type |
| ¿El navegador soporta este CSS? | Mejora progresiva | @supports (…) / selector(…) |
Estas herramientas se apilan con claridad: media para la página, container para el hueco, @supports para la capacidad. No uses @supports para fingir un breakpoint ni @media para fingir una comprobación de característica.
Primero la base, luego el enhancement
Un patrón práctico deja el aspecto compartido fuera de la puerta y sube el layout dentro:
.feature-panel {
padding: 1.25rem;
border-radius: 0.75rem;
background: #f8fafc;
color: #0f172a;
}
.feature-panel .lead {
margin: 0 0 0.75rem;
font-size: 1.125rem;
line-height: 1.5;
}
.feature-panel .actions {
display: block;
}
.feature-panel .actions a {
display: inline-block;
margin: 0.25rem 0.5rem 0.25rem 0;
padding: 0.5rem 0.875rem;
border-radius: 0.5rem;
background: #e2e8f0;
color: inherit;
text-decoration: none;
}
@supports (display: flex) and (gap: 0.5rem) {
.feature-panel .actions {
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
}
.feature-panel .actions a {
margin: 0;
}
}
Todo navegador recibe padding, tipografía y enlaces pulsables. Flex + gap solo aparecen cuando se entienden ambos — sin un agujero vacío si falta uno.
Nesting junto a @supports
Las piezas de Modern Toolkit se combinan. Nesting organiza selectores; @supports sigue mandando en la puerta de capacidad:
.pricing {
padding: 1rem;
border: 1px solid #e2e8f0;
}
@supports (display: grid) {
.pricing {
display: grid;
gap: 1rem;
& .tier {
padding: 1rem;
background: #fff;
}
& .tier .price {
font-size: 1.5rem;
font-weight: 700;
}
}
}
Si el propio nesting no está soportado, deja un equivalente plano fuera o acepta que la forma anidada forma parte de la ruta mejorada — la misma mentalidad de mejora progresiva.
Pruébalo tú
- Estiliza una lista como pila vertical sencilla y envuelve un layout Grid en
@supports (display: grid). - Exige
gapconandpara que el espaciado de flex/grid no se aplique a medias. - Añade
@supports not (display: grid)con un fallback claro demax-width— confirma que ambas rutas se ven intencionadas. - Cierra una regla
:has()con@supports selector(:has(*)). - Resiste mover todos los estilos visuales dentro de
@supports; deja color de marca y tipografía en la base.
Errores frecuentes
- Meter el único layout usable dentro de
@supportssin base — los navegadores sin soporte ven una página rota - Escribir
@supports (display)sin valor — las feature queries necesitan un par propiedad–valor (oselector(…)) - Usar
@supportsdonde corresponde@media(o al revés) — capacidad ≠ ancho de viewport - Probar una propiedad que la base ya exige — cierra solo el enhancement
- Pilas profundas de
@supportsanidados por ganancias mínimas — preferible una capa mejorada clara
Resumen
@supportscierra CSS según la capacidad del navegador (feature queries)- Prueba con
(property: value), combina conand/or/noty usaselector()para selectores - Mantén una base sólida; mejora cuando exista soporte
- Recuerda el trío:
@media→ viewport,@container→ tamaño del padre,@supports→ capacidad - Modern Toolkit termina aquí — siguiente módulo: Accesibilidad y cierre (
accessibility)
🧠 Pon a Prueba tu Conocimiento
Pon a Prueba tu Conocimiento
Ponte a prueba con este cuestionario interactivo y descubre qué tan bien entiendes el tema
📝 Instrucciones
- Lee cada pregunta cuidadosamente
- Selecciona la mejor respuesta para cada pregunta
- Puedes repetir el quiz tantas veces como quieras
- Tu progreso se mostrará en la parte superior