---
name: css-moderno
description: CSS moderno 2024+. Cubre Container Queries, CSS Layers (@layer), Nesting nativo, Custom Properties avanzadas, funciones min/max/clamp/color-mix, propiedades lógicas (block/inline), View Transitions API, animaciones performantes solo-compositor, dark mode patterns y anti-patrones críticos.
version: "1.0.0"
herramientasPermitidas: [Read, Grep]
exclusiones:
  - "No cargar para Tailwind CSS (clases utilitarias, @theme, cva, responsive) — para Tailwind cargar `tailwind-experto`."
  - "No cargar para accesibilidad visual (contraste, foco, ARIA) — para accesibilidad cargar `accesibilidad-a11y`."
  - "No cargar para animaciones JavaScript (GSAP, Framer Motion) — este skill cubre solo animaciones CSS nativas."
  - "No cargar para CSS-in-JS (styled-components, Emotion) — son patrones de componentes JavaScript, no CSS nativo."
evolvable: true  # default para skill estandar
---
# CSS Moderno — 2024+

## Cuándo NO cargar

- La tarea usa Tailwind CSS: clases utilitarias, `@theme`, `cva`, breakpoints responsivos — cargar `tailwind-experto`.
- El tema es accesibilidad: contraste WCAG, anillo de foco visible, ARIA — cargar `accesibilidad-a11y`.
- Las animaciones son con JavaScript: GSAP, Framer Motion, Web Animations API — este skill cubre solo animaciones CSS nativas (`transition`, `animation`, `@keyframes`).
- El contexto es CSS-in-JS (styled-components, Emotion, vanilla-extract) — son patrones de componentes JavaScript, no CSS nativo.

## Filosofía

CSS moderno elimina la necesidad de preprocesadores para la mayoría de los casos.
Las características nativas del 2023-2024 cubren lo que antes requería Sass/Less,
con mejor rendimiento y sin dependencias de build.

---

## Reglas Obligatorias

1. **SIEMPRE usar `@layer`** para controlar especificidad — NUNCA `!important`.
2. **SIEMPRE usar propiedades lógicas** (`margin-inline`, `padding-block`) en lugar de físicas para soporte de internacionalización.
3. **SOLO animar `transform` y `opacity`** — son las únicas propiedades que corren en el compositor (GPU) sin triggear layout ni paint.
4. **NUNCA usar `will-change`** salvo que haya un problema de rendimiento medido.
5. **SIEMPRE usar `rem`** para tipografía — nunca `px` fijos que ignoran preferencias de zoom del usuario.
6. **Container Queries sobre media queries** cuando el componente vive en contextos de tamaño variable.

---

## Container Queries — Resumen

Los componentes responden al tamaño de su contenedor padre, no al viewport:

```css
.card-wrapper {
  container-type: inline-size;
  container-name: tarjeta;
}

@container tarjeta (min-width: 400px) {
  .card { grid-template-columns: auto 1fr; }
}
```

---

## CSS Layers (@layer) — Resumen

Declara el orden de capas: la última tiene mayor prioridad.

```css
@layer reset, base, componentes, utilidades, overrides;

@layer utilidades {
  .mt-4 { margin-top: 1rem; }
}
/* Las utilidades siempre ganan sobre componentes, sin !important */
```

---

## CSS Nesting Nativo — Resumen

```css
.nav {
  display: flex;
  gap: 1rem;

  & a {
    text-decoration: none;
    &:hover { color: var(--color-primario); }
  }

  @media (max-width: 768px) { flex-direction: column; }
}
```

---

## Funciones Matemáticas

```css
/* Tipografía fluida — sin media queries */
h1 { font-size: clamp(1.5rem, 4vw, 3rem); }

/* Contenedor con limites */
.tarjeta { width: clamp(300px, 50%, 600px); }

/* Padding adaptativo */
.seccion { padding-inline: max(1rem, (100% - 1200px) / 2); }
```

---

## Animaciones Performantes (Solo-compositor)

```css
/* BIEN: solo compositor */
.boton {
  transition: transform 0.2s ease, opacity 0.2s ease;
}
.boton:hover {
  transform: translateY(-2px) scale(1.02);
  opacity: 0.9;
}

/* MAL: trigerea layout (costoso) */
.boton:hover {
  margin-top: -2px;   /* layout thrashing */
  width: 102%;        /* layout thrashing */
}
```

---

## Anti-patrones Críticos

### !important — nunca

```css
/* MAL */
.titulo { color: red !important; }

/* BIEN: usar @layer para controlar especificidad */
@layer overrides { .titulo { color: red; } }
```

### Z-index wars

```css
/* MAL: z-index arbitrarios */
.modal { z-index: 9999; }

/* BIEN: sistema de capas con custom properties */
:root {
  --z-base: 1;
  --z-dropdown: 100;
  --z-modal: 300;
  --z-tooltip: 400;
}
```

---

Para ejemplos completos de Container Queries, CSS Layers, Nesting, Custom Properties avanzadas, @property tipadas, color-mix(), propiedades logicas, View Transitions API, dark mode patterns y anti-patrones extendidos, ver [recursos/ejemplos-y-patrones-completos.md](recursos/ejemplos-y-patrones-completos.md).

## Gotchas / Errores comunes no obvios

**CSS Nesting nativo con `& ` en selectores de clase hermana no funciona igual que Sass**: `& .hijo` selecciona descendientes, pero `.hermano & ` (con el padre al final) invierte el contexto — el comportamiento con pseudo-clases es diferente al de Sass. Además, en Chrome <112 y Firefox <117 el nesting nativo no estaba disponible. Causa: la especificación de CSS Nesting tiene semántica propia distinta de Sass. Fix: verificar soporte con `@supports selector(& a { })` o usar PostCSS `postcss-nesting` como fallback; preferir selectores directos sobre selectores contextuales complejos con nesting.

**`@layer` invierte la intuición de especificidad — una clase en `@layer base` siempre pierde contra una clase sin layer aunque tenga más selectores**: una regla fuera de cualquier `@layer` tiene mayor prioridad que cualquier regla dentro de un layer, independientemente de la especificidad. Causa: las reglas sin layer forman implícitamente una capa de mayor prioridad. Fix: si se integra una librería de terceros (Bootstrap, MaterialUI CSS) sin layers, todas las personalizaciones deben estar también fuera de layers o en un `@layer` declarado después de los de la librería.

**`container-type: inline-size` en un elemento con `position: absolute/fixed` puede no funcionar como contenedor de queries en algunos navegadores**: el contenedor crea un nuevo stacking context y en ciertos casos la query no se propaga correctamente a hijos con posicionamiento absoluto en Safari <17. Causa: bug de implementación en Safari relacionado con contenedores posicionados. Fix: en elementos con posicionamiento absoluto dentro de container queries, probar en Safari y usar un wrapper div sin posicionamiento como contenedor si hay problemas.

**`clamp()` con `vw` en la función intermedia no escala correctamente en pantallas muy anchas si no se acota con `max()`**: `font-size: clamp(1rem, 2vw, 2rem)` en un monitor de 2560px da `2vw = 51.2px`, que es mayor que el máximo de `2rem = 32px` — el clamp lo atrapa pero el cálculo puede ser confuso al depurar. Causa: el valor de `vw` crece sin límite. Fix: entender que `clamp(min, preferido, max)` garantiza que el resultado siempre está entre min y max — el valor preferido puede ser cualquier expresión, incluso mayor que max, y el clamp simplemente retorna max en ese caso. Verificar los tres valores en los tamaños de viewport objetivo.
