CSS ha evolucionado más en los últimos 5 años que en los 15 anteriores. Si aprendiste CSS hace tiempo o estás empezando ahora, hay un conjunto de funcionalidades modernas que cambian completamente la forma de maquetar webs — sin necesidad de frameworks externos ni JavaScript. En este artículo te explico las más importantes con ejemplos prácticos y casos de uso reales.

Todas las funcionalidades de este artículo están soportadas por todos los navegadores modernos en 2026. No necesitas prefijos, polyfills ni librerías externas.

En este artículo:

1. Variables CSS (Custom Properties)

Las variables CSS son una de las funcionalidades más útiles del CSS moderno. Te permiten definir valores reutilizables en toda tu hoja de estilos y, a diferencia de las variables de preprocesadores como Sass, funcionan en tiempo real en el navegador — puedes modificarlas con JavaScript o según el contexto.

:root {
  /* Colores */
  --color-primario: #6ee7b7;
  --color-secundario: #3b82f6;
  --color-fondo: #0b0c0e;
  --color-texto: #f1f5f9;

  /* Tipografía */
  --fuente-principal: 'Inter', sans-serif;
  --fuente-codigo: 'Fira Code', monospace;
  --tamaño-base: 1rem;

  /* Espaciado */
  --espaciado-xs: 0.25rem;
  --espaciado-sm: 0.5rem;
  --espaciado-md: 1rem;
  --espaciado-lg: 2rem;
  --espaciado-xl: 4rem;

  /* Bordes */
  --radio-sm: 4px;
  --radio-md: 8px;
  --radio-lg: 16px;
}

.boton {
  background-color: var(--color-primario);
  font-family: var(--fuente-principal);
  padding: var(--espaciado-sm) var(--espaciado-md);
  border-radius: var(--radio-md);
}

Una ventaja enorme es el theming dinámico. Para implementar un modo oscuro/claro solo necesitas redefinir las variables:

/* Modo claro por defecto */
:root {
  --color-fondo: #ffffff;
  --color-texto: #1a1a1a;
}

/* Modo oscuro automático según preferencia del sistema */
@media (prefers-color-scheme: dark) {
  :root {
    --color-fondo: #0b0c0e;
    --color-texto: #f1f5f9;
  }
}

/* O modo oscuro activado por clase en el HTML */
[data-theme="dark"] {
  --color-fondo: #0b0c0e;
  --color-texto: #f1f5f9;
}

También puedes usar variables con valores de fallback en caso de que no estén definidas:

.elemento {
  color: var(--color-acento, #6ee7b7); /* usa #6ee7b7 si --color-acento no existe */
}

2. Flexbox

Flexbox es el sistema de diseño unidimensional de CSS — trabaja en una sola dirección (fila o columna). Es perfecto para alinear elementos dentro de un contenedor, crear barras de navegación, centrar contenido y distribuir espacio entre elementos.

/* Barra de navegación típica */
.navbar {
  display: flex;
  justify-content: space-between; /* logo a la izquierda, links a la derecha */
  align-items: center;
  padding: 0 var(--espaciado-lg);
  height: 64px;
}

/* Centrar un elemento perfectamente en pantalla */
.centrado-perfecto {
  display: flex;
  justify-content: center;
  align-items: center;
  min-height: 100vh;
}

/* Tarjetas con altura igual aunque el contenido varía */
.tarjetas {
  display: flex;
  gap: 24px;
}

.tarjeta {
  display: flex;
  flex-direction: column;
  flex: 1; /* todas las tarjetas ocupan el mismo ancho */
}

.tarjeta-contenido {
  flex: 1; /* empuja el footer de la tarjeta hacia abajo */
}

/* Wrap automático cuando no caben los elementos */
.chips {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

La propiedad gap en Flexbox es uno de los cambios más útiles — antes había que usar márgenes en los hijos, lo que generaba problemas con el primer y último elemento.

3. CSS Grid

CSS Grid es el sistema bidimensional — trabaja con filas y columnas al mismo tiempo. Es ideal para layouts completos de página y para galerías de elementos.

/* Grid responsive sin una sola media query */
.grid-responsive {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 24px;
}

/* Layout completo de página */
.layout-pagina {
  display: grid;
  grid-template-areas:
    "header header"
    "sidebar main"
    "footer footer";
  grid-template-columns: 280px 1fr;
  grid-template-rows: auto 1fr auto;
  min-height: 100vh;
}

.header  { grid-area: header; }
.sidebar { grid-area: sidebar; }
.main    { grid-area: main; }
.footer  { grid-area: footer; }

/* Layout masonry aproximado */
.masonry {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-auto-rows: 10px;
  gap: 16px;
}

/* Elemento que ocupa varias columnas */
.elemento-destacado {
  grid-column: span 2;
  grid-row: span 3;
}

La combinación de auto-fit y minmax() es una de las técnicas más potentes del CSS moderno — crea un grid completamente responsive sin necesidad de media queries.

4. La función clamp() y otras funciones matemáticas

clamp(mínimo, preferido, máximo) permite definir un valor que se adapta fluidamente entre un mínimo y un máximo. Es perfecta para tipografía fluida y contenedores responsive.

/* Tipografía fluida: mínimo 20px, máximo 48px, fluido entre medias */
h1 {
  font-size: clamp(1.25rem, 4vw + 1rem, 3rem);
}

h2 {
  font-size: clamp(1.1rem, 3vw + 0.5rem, 2rem);
}

/* Contenedor con máximo ancho centrado */
.contenedor {
  width: clamp(320px, 90%, 1200px);
  margin: 0 auto;
  padding: 0 var(--espaciado-md);
}

/* Espaciado fluido */
.seccion {
  padding: clamp(2rem, 5vw, 6rem) 0;
}

CSS moderno también incluye otras funciones matemáticas muy útiles:

/* min() y max() */
.elemento {
  width: min(100%, 600px); /* nunca más ancho que su contenedor ni que 600px */
  padding: max(1rem, 3vw);  /* mínimo 1rem, crece con el viewport */
}

/* calc() para cálculos */
.sidebar {
  width: calc(100% - 280px - 2rem); /* ancho total menos sidebar menos gap */
}

/* Variables en calc() */
:root { --sidebar-width: 280px; }

.main {
  width: calc(100% - var(--sidebar-width));
}

5. Selectores modernos: :is(), :has(), :where()

Estos selectores modernos eliminan la necesidad de JavaScript para muchos casos de uso y simplifican enormemente el CSS.

/* :is() agrupa selectores, reduciendo repetición */
/* Antes: */
h1 a, h2 a, h3 a, h4 a { color: var(--color-primario); }

/* Ahora: */
:is(h1, h2, h3, h4) a {
  color: var(--color-primario);
}

/* :where() es igual que :is() pero con especificidad 0 */
:where(h1, h2, h3) {
  line-height: 1.2; /* fácil de sobreescribir */
}

/* :has() — el selector padre, antes imposible en CSS puro */

/* Tarjeta sin imagen: padding normal */
.card { padding: 1.5rem; }

/* Tarjeta con imagen: sin padding en la imagen */
.card:has(img) {
  padding: 0;
}
.card:has(img) .card-content {
  padding: 1.5rem;
}

/* Input con error */
.form-group:has(input:invalid) label {
  color: red;
}

/* Menú con submenú abierto */
.nav-item:has(.submenu:hover) > .nav-link {
  color: var(--color-primario);
}

/* :not() excluye elementos */
li:not(:last-child) {
  border-bottom: 1px solid var(--color-borde);
}

/* :nth-child() avanzado */
/* Selecciona los 3 primeros elementos */
li:nth-child(-n+3) {
  font-weight: bold;
}

/* Filas pares de una tabla */
tr:nth-child(even) {
  background: rgba(255,255,255,0.05);
}

6. Container Queries

Las Container Queries son una de las novedades más revolucionarias del CSS moderno. Permiten aplicar estilos basados en el tamaño del contenedor padre, no del viewport. Esto soluciona un problema enorme: un componente reutilizable que se adapta a cualquier contexto donde se coloque.

/* Definir el contenedor */
.card-wrapper {
  container-type: inline-size;
  container-name: card; /* nombre opcional */
}

/* Estilos según el tamaño del contenedor */
@container card (min-width: 400px) {
  .card {
    display: grid;
    grid-template-columns: 200px 1fr;
  }
}

@container card (min-width: 600px) {
  .card {
    grid-template-columns: 300px 1fr;
  }

  .card-titulo {
    font-size: 1.5rem;
  }
}

/* Unidades de contenedor */
.card-titulo {
  font-size: clamp(1rem, 5cqi, 1.5rem); /* cqi = container query inline */
}

El caso de uso más común: una tarjeta de producto que se muestra en 3 columnas en el catálogo principal y en 1 columna en el sidebar. Con media queries era imposible estilizar el mismo componente de forma diferente según el contexto. Con Container Queries es trivial.

7. Animaciones y transiciones

CSS moderno tiene herramientas muy potentes para animar sin JavaScript:

/* Transición suave en hover */
.boton {
  background-color: var(--color-primario);
  transition: background-color 0.2s ease, transform 0.2s ease, box-shadow 0.2s ease;
}

.boton:hover {
  background-color: var(--color-secundario);
  transform: translateY(-2px);
  box-shadow: 0 4px 12px rgba(0,0,0,0.2);
}

/* Animación de entrada */
@keyframes aparecer {
  from {
    opacity: 0;
    transform: translateY(20px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.elemento {
  animation: aparecer 0.5s ease forwards;
}

/* Stagger: cada elemento aparece con retraso */
.lista-item:nth-child(1) { animation-delay: 0ms; }
.lista-item:nth-child(2) { animation-delay: 100ms; }
.lista-item:nth-child(3) { animation-delay: 200ms; }
.lista-item:nth-child(4) { animation-delay: 300ms; }

/* View Transitions API: animación entre páginas */
@view-transition {
  navigation: auto;
}

/* Siempre respeta las preferencias de accesibilidad */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}

8. Aspect Ratio

Mantener proporciones de elementos sin trucos de padding era un dolor de cabeza histórico en CSS. Ahora es una línea:

/* Video 16:9 responsive */
.video-wrapper {
  aspect-ratio: 16 / 9;
  width: 100%;
}

/* Imagen cuadrada que no se deforma */
.avatar {
  aspect-ratio: 1;
  width: 48px;
  object-fit: cover;
  border-radius: 50%;
}

/* Tarjeta con proporción fija */
.card-imagen {
  aspect-ratio: 4 / 3;
  object-fit: cover;
  width: 100%;
}

/* Thumbnail de video */
.thumbnail {
  aspect-ratio: 16 / 9;
  background: var(--color-fondo);
  overflow: hidden;
}

9. Scroll Snap

Crea carruseles con scroll que se «engancha» a cada elemento — completamente sin JavaScript:

/* Carrusel horizontal */
.carrusel {
  display: flex;
  overflow-x: scroll;
  scroll-snap-type: x mandatory;
  gap: 16px;
  padding: 16px;
  scrollbar-width: none; /* oculta el scrollbar en Firefox */
}

.carrusel::-webkit-scrollbar {
  display: none; /* oculta el scrollbar en Chrome/Safari */
}

.carrusel-item {
  flex-shrink: 0;
  width: 80%;
  scroll-snap-align: start;
}

/* Scroll snapping de página completa */
.paginas {
  height: 100vh;
  overflow-y: scroll;
  scroll-snap-type: y mandatory;
}

.pagina {
  height: 100vh;
  scroll-snap-align: start;
}

10. Cascade Layers

Cascade Layers es una de las funcionalidades más recientes y menos conocidas. Permite organizar el CSS en capas con una jerarquía de especificidad controlada — muy útil en proyectos grandes para evitar guerras de especificidad:

/* Definir el orden de las capas */
@layer reset, base, componentes, utilidades;

/* Estilos de reset — menor prioridad */
@layer reset {
  * { margin: 0; padding: 0; box-sizing: border-box; }
}

/* Estilos base */
@layer base {
  body {
    font-family: var(--fuente-principal);
    background: var(--color-fondo);
    color: var(--color-texto);
  }
}

/* Componentes */
@layer componentes {
  .boton { /* ... */ }
  .card { /* ... */ }
}

/* Utilidades — mayor prioridad */
@layer utilidades {
  .hidden { display: none !important; }
  .sr-only { /* accesibilidad */ }
}

Errores comunes al usar CSS moderno

❌ Usar Flexbox para layouts de página completos

Flexbox es unidimensional. Para layouts con filas Y columnas usa Grid. El error más típico es intentar hacer el layout completo de una página solo con Flexbox anidados.

❌ Olvidar prefers-reduced-motion en animaciones

Algunos usuarios tienen configurado el sistema para reducir animaciones por motivos de accesibilidad o rendimiento. Siempre añade el media query prefers-reduced-motion cuando uses animaciones.

❌ Variables CSS sin fallback en valores críticos

Si una variable no está definida, la propiedad queda sin valor. Usa siempre fallback en propiedades críticas: var(--color, #000).

❌ Especificidad innecesaria

Con selectores modernos como :is() y :where() puedes simplificar enormemente tu CSS. :where() tiene especificidad 0, lo que lo hace ideal para estilos base fáciles de sobreescribir.

Por dónde empezar

No necesitas dominarlos todos desde el principio. Este es el orden que recomiendo según tu nivel:

Si estás empezando: Variables CSS → Flexbox → CSS Grid. Con esos tres puedes maquetar cualquier diseño moderno.

Nivel intermedio: clamp() y funciones matemáticas → Selectores modernos → Animaciones con prefers-reduced-motion.

Nivel avanzado: Container Queries → Cascade Layers → View Transitions API.

El mejor consejo es ir incorporando cada funcionalidad en proyectos reales a medida que la necesites. Si estás aprendiendo desarrollo frontend con Angular o construyendo tu primera web, empieza por variables CSS y Flexbox — verás la diferencia inmediatamente en la calidad y mantenibilidad de tu código.