M02 Técnica + Demo Lección 1.1 ⏱ 45 min

Flexbox:
domina el eje

Flexbox resuelve el 80% del layout cotidiano. Es unidimensional — trabaja en fila o columna. Entenderlo completamente te da superpoderes de distribución de espacio.

El modelo mental de Flexbox

Flexbox opera sobre dos ejes: el eje principal (main axis) y el eje cruzado (cross axis). Todo lo demás es consecuencia de dónde apuntan esos ejes.

Demo interactivo · Flexbox en vivo
A
BB
CCC
D
EE
flex-direction justify-content align-items flex-wrap

Las propiedades esenciales

flexbox-completo.css
/* ── En el CONTENEDOR PADRE ─────────────────── */
.contenedor {
  display: flex;               /* activa flexbox */

  /* Dirección del eje principal */
  flex-direction: row;           /* → fila (default) */
  flex-direction: column;        /* ↓ columna */
  flex-direction: row-reverse;   /* ← fila invertida */

  /* Distribución en el EJE PRINCIPAL */
  justify-content: flex-start;   /* al inicio */
  justify-content: center;       /* centrado */
  justify-content: flex-end;     /* al final */
  justify-content: space-between;/* máximo espacio entre */
  justify-content: space-around; /* espacio igual alrededor */
  justify-content: space-evenly; /* espacio perfectamente igual */

  /* Alineación en el EJE CRUZADO */
  align-items: flex-start;      /* arriba (en row) */
  align-items: center;          /* centrado vertical */
  align-items: flex-end;        /* abajo */
  align-items: stretch;         /* estira para llenar (default) */
  align-items: baseline;        /* alinea líneas base de texto */

  /* Salto de línea */
  flex-wrap: nowrap;            /* no rompe (default) */
  flex-wrap: wrap;             /* los hijos bajan de línea */

  gap: 16px;                 /* espacio entre hijos */
  gap: 16px 24px;           /* row-gap column-gap */
}

/* ── En los HIJOS ───────────────────────────── */
.hijo {
  flex-grow: 1;              /* crece para llenar espacio disponible */
  flex-shrink: 0;            /* no se encoge (0 = rígido) */
  flex-basis: 200px;         /* tamaño base antes de grow/shrink */

  /* Shorthand: grow shrink basis */
  flex: 1 1 200px;           /* grow shrink basis */
  flex: 1;                   /* grow=1, shrink=1, basis=0 (más común) */

  align-self: center;        /* override del align-items del padre */
  order: 2;                  /* cambia el orden visual */
}

Casos de uso reales en portfolios

patrones-flexbox.css
/* ── Navbar: logo izquierda, links derecha ── */
.navbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 16px 40px;
}

/* ── Centrar absolutamente cualquier cosa ── */
.hero {
  display: flex;
  justify-content: center;
  align-items: center;
  min-height: 100vh;        /* pantalla completa */
  flex-direction: column;    /* texto apilado */
  gap: 24px;
}

/* ── Grid de cards que se adaptan ── */
.card-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 20px;
}

.card {
  flex: 1 1 280px;           /* min 280px, crece para llenar */
}

/* ── Footer: tres columnas ── */
.footer {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 40px;
  flex-wrap: wrap;           /* en móvil se apila */
}
💡 truco de flex

Para centrar algo perfectamente en horizontal y vertical: display:flex; justify-content:center; align-items:center. Es la solución más elegante al eterno problema de "¿cómo centro esto?"

Recursos de referencia

Ejercicio 1.1 · Navbar + Hero con Flexbox
⏱ 40 min
  • 1
    En tu portfolio de M01, convierte el <header> en un navbar Flexbox: logo izquierda, nav links derecha, perfectamente alineados verticalmente.
  • 2
    Crea una sección .hero con Flexbox que centre todo su contenido vertical y horizontalmente usando min-height: 100vh.
  • 3
    Convierte tu grilla de proyectos en flex-wrap: wrap con flex: 1 1 280px en cada tarjeta. Reduce la ventana del navegador para ver cómo se adaptan.
  • 4
    Usa el Demo interactivo de arriba para explorar cada propiedad antes de escribirla en tu CSS.
📌 Objetivo: Tu portfolio con navbar y hero completamente funcionales usando solo Flexbox.
M02 Técnica + Demo Lección 1.2 ⏱ 50 min

CSS Grid:
el tablero infinito

Grid es bidimensional: controla filas Y columnas al mismo tiempo. Es el sistema más poderoso que tiene CSS y la razón por la que ya no necesitamos frameworks de layout.

Grid vs Flexbox: cuándo usar cuál

SituaciónUsa FlexboxUsa Grid
Navbar / barra de herramientas✓ Perfecto
Centrar un elemento✓ Más simpleTambién funciona
Galería de imágenes✓ Ideal
Layout de página completo✓ Perfecto
Cards en fila que "wrappean"✓ Con flex-wrap✓ auto-fill/fit
Layouts editoriales complejos✓ Insuperable

Demo interactivo · Grid en vivo

Explora las propiedades de Grid
1
2
3
4
5
6
grid-template-columns gap

Sintaxis completa de Grid

css-grid-completo.css
/* ── CONTENEDOR ─────────────────────────────── */
.grid {
  display: grid;

  /* Columnas: la propiedad más importante */
  grid-template-columns: 200px 1fr 200px;     /* sidebar - main - sidebar */
  grid-template-columns: repeat(3, 1fr);       /* 3 columnas iguales */
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  /*  ↑ El patrón más poderoso: mínimo 280px, máximo 1fr */
  /*    auto-fill crea tantas columnas como quepan */

  /* Filas */
  grid-template-rows: 80px 1fr auto;           /* header - contenido - footer */
  grid-auto-rows: 200px;                      /* filas implícitas (automáticas) */

  /* Espaciado */
  gap: 20px;                                 /* rows y columns */
  row-gap: 16px;
  column-gap: 24px;

  /* Alineación de todos los items */
  justify-items: start | center | end | stretch;
  align-items: start | center | end | stretch;
}

/* ── ITEM: posicionamiento explícito ────────── */
.item-especial {
  /* Columnas: ocupa del 1 al 3 (span 2 columnas) */
  grid-column: 1 / 3;                          /* de línea 1 a línea 3 */
  grid-column: span 2;                          /* ocupa 2 columnas */
  grid-column: 1 / -1;                         /* de inicio a fin (ancho completo) */

  /* Filas */
  grid-row: 1 / 3;                             /* ocupa 2 filas */
}

/* ── TEMPLATE AREAS: layout semántico ──────── */
.pagina {
  display: grid;
  grid-template-areas:
    "header  header  header"
    "sidebar main    main  "
    "footer  footer  footer";
  grid-template-columns: 240px 1fr 1fr;
  grid-template-rows: 80px 1fr 60px;
}

.header  { grid-area: header; }
.sidebar { grid-area: sidebar; }
.main    { grid-area: main; }
.footer  { grid-area: footer; }
🆕 Subgrid (2024) — ya en todos los navegadores

Subgrid permite que un hijo de un grid herede las líneas de columna/fila del padre. Resuelve el problema histórico de alinear contenido anidado con el grid externo. grid-template-columns: subgrid

Inspiración visual: layouts con Grid

Layout editorial
Layout editorial — grid asimétrico
Portfolio grid
Portfolio grid — auto-fill masonry style
Dashboard grid
Dashboard — template-areas

Los mejores sitios creativos usan Grid para layouts que Flexbox no puede hacer. Fuente: Unsplash

Ejercicio 1.2 · Galería de proyectos con Grid
⏱ 45 min
  • 1
    Reemplaza el Flexbox de tu grilla de proyectos por CSS Grid: grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)). Observa cómo se comporta al cambiar el tamaño de la ventana.
  • 2
    Haz que el primer proyecto ocupe el ancho completo: grid-column: 1 / -1. Ajusta su aspect-ratio: 21/9.
  • 3
    Crea el layout completo de tu página usando grid-template-areas: header, main y footer.
  • 4
    Juega en Grid Garden — al menos 15 niveles.
📌 Objetivo: Una galería de proyectos responsive con Grid donde el primer proyecto destaca visualmente sobre el resto.
M02 Técnica Lección 1.3 ⏱ 30 min

Layout combinado:
Grid + Flex

La realidad es que Grid y Flexbox se usan juntos. Grid para la estructura macro de la página, Flex para los componentes internos. Esta es la arquitectura de cualquier sitio moderno.

El patrón de los tres niveles

Piensa en cualquier página web en tres niveles de layout:

layout-arquitectura.css
/* ── NIVEL 1: Macro layout (GRID) ───────────── */
body {
  display: grid;
  grid-template-rows: auto 1fr auto; /* header / main / footer */
  min-height: 100vh;
}

/* ── NIVEL 2: Secciones (GRID) ──────────────── */
.proyectos-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: 20px;
}

/* ── NIVEL 3: Componentes internos (FLEX) ───── */
.proyecto-card {
  display: flex;
  flex-direction: column;      /* imagen arriba, texto abajo */
}

.card-footer {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-top: auto;            /* empuja al fondo de la card */
}

.navbar {
  display: flex;               /* nivel 3: el nav es flex */
  justify-content: space-between;
  align-items: center;
}

/* position: relative/absolute para overlays ── */
.card-imagen-wrap {
  position: relative;
  overflow: hidden;
}

.card-overlay {
  position: absolute;
  inset: 0;               /* top:0 right:0 bottom:0 left:0 */
  background: rgba(0,0,0,.7);
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  transition: opacity .3s;
}

.card-imagen-wrap:hover .card-overlay {
  opacity: 1;
}
💡 regla práctica

Usa Grid cuando piensas en filas Y columnas al mismo tiempo. Usa Flex cuando piensas en una sola dirección (fila o columna). En la duda, usa Grid — siempre es más flexible.

Ejercicio 1.3 · Arquitectura completa de tu portfolio
⏱ 30 min
  • 1
    Diagrama en papel la arquitectura de tu portfolio: ¿qué es Grid macro? ¿Qué secciones usan Grid? ¿Qué componentes usan Flex?
  • 2
    Implementa el layout con la estructura de tres niveles. El body como Grid, las secciones como Grid o Flex según corresponda.
  • 3
    Añade el efecto overlay hover a tus tarjetas de proyecto usando position: relative/absolute.
M02 Teoría Lección 2.1 ⏱ 25 min

Mobile-first:
el principio

Diseñar para móvil primero no es una restricción — es una disciplina que te obliga a priorizar lo esencial. El 60%+ del tráfico web global viene de dispositivos móviles.

¿Por qué mobile-first?

El enfoque tradicional era diseñar para desktop y luego "reducir" para móvil. El problema: cuando empiezas grande y reduces, sueles ocultar cosas en lugar de repensar la experiencia. Mobile-first invierte esto: empieza con el contexto más restringido y enriquece hacia pantallas grandes.

EnfoqueDesktop-firstMobile-first ✓
Punto de partidaPantalla grandePantalla pequeña
Direcciónmax-width en media queriesmin-width en media queries
ComportamientoOcultar para móvilAgregar para desktop
PerformanceCSS pesado en móvilCSS ligero en móvil
UXPensado para mousePensado para touch
mobile-first-approach.css
/* ── MOBILE FIRST: el CSS base es para móvil ── */

/* Base (móvil, ~320px-767px): una columna */
.proyectos {
  display: grid;
  grid-template-columns: 1fr;  /* 1 columna */
  gap: 16px;
}

.navbar {
  flex-direction: column;    /* links apilados en móvil */
  align-items: flex-start;
}

/* Tablet (≥768px): dos columnas */
@media (min-width: 768px) {
  .proyectos {
    grid-template-columns: repeat(2, 1fr);
    gap: 20px;
  }
  .navbar {
    flex-direction: row;     /* horizontal en tablet+ */
  }
}

/* Desktop (≥1200px): tres columnas */
@media (min-width: 1200px) {
  .proyectos {
    grid-template-columns: repeat(3, 1fr);
    gap: 28px;
  }
}
Ejercicio 2.1 · Convierte tu portfolio a mobile-first
⏱ 30 min
  • 1
    Abre DevTools → Device Toolbar (ícono de móvil) → selecciona iPhone 12. Tu portfolio debe verse bien ahí.
  • 2
    Reescribe tu CSS empezando por móvil: una columna, texto más grande, padding suficiente para dedos.
  • 3
    Añade breakpoints con min-width para tablet (768px) y desktop (1200px). Nunca uses max-width para esto.
📌 Objetivo: Tu portfolio funcional y bonito en móvil, tablet y desktop.
M02 Técnica Lección 2.2 ⏱ 35 min

Media Queries:
puntos de quiebre

Las media queries son el mecanismo que permite a CSS responder al contexto del usuario: tamaño de pantalla, preferencias de movimiento, tema oscuro, resolución. Son condiciones lógicas.

Sintaxis y tipos

media-queries-completo.css
/* ── POR ANCHO (las más usadas) ─────────────── */
@media (min-width: 768px) { /* tablet y desktop */ }
@media (min-width: 1024px) { /* desktop */ }
@media (min-width: 1440px) { /* pantallas grandes */ }

/* Rango: solo para un tamaño específico */
@media (min-width: 768px) and (max-width: 1023px) { /* solo tablet */ }

/* ── POR PREFERENCIAS DEL USUARIO ───────────── */

/* Dark mode (lo vimos en M01) */
@media (prefers-color-scheme: dark) {
  :root { --color-bg: #0a0a0f; }
}

/* Reducir movimiento (accesibilidad CRÍTICA) */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

/* Alta resolución (Retina) para imágenes 2x */
@media (min-resolution: 2dppx) {
  .logo { background-image: url('logo@2x.png'); }
}

/* ── CONTAINER QUERIES (2024, nuevo!) ────────── */
/* En vez de pantalla, responde al contenedor padre */
.card-container { container-type: inline-size; }

@container (min-width: 400px) {
  .card {
    display: grid;
    grid-template-columns: 120px 1fr; /* imagen lateral cuando hay espacio */
  }
}
🆕 Container Queries — el cambio más grande en responsive en 10 años

Las Media Queries responden al viewport (pantalla). Las Container Queries responden al contenedor padre. Un componente puede ahora adaptarse según el espacio que ocupa, no según el tamaño de pantalla. Soportado en todos los navegadores modernos desde 2023.

Breakpoints recomendados

NombreValorDispositivos típicos
Base (móvil)0px — 767pxiPhone, Android pequeños/medianos
sm (tablet)768px+iPad, tablets, móviles grandes
md (desktop pequeño)1024px+Laptops, iPads landscape
lg (desktop)1280px+Monitores, MacBooks
xl (pantalla grande)1536px+Monitores 27"+
M02 Técnica Lección 2.3 ⏱ 30 min

Unidades fluidas
y clamp()

Las unidades relativas y las funciones matemáticas de CSS permiten crear layouts y tipografías que se adaptan fluidamente sin media queries. El futuro del responsive design.

El universo de unidades CSS

UnidadRelativa aCuándo usarla
pxPíxeles físicosBordes, sombras, valores fijos pequeños
remfont-size del <html> (16px default)Tipografía, espaciado — la más recomendada
emfont-size del elemento padrePadding/margin relativos al texto
%El contenedor padreAnchos fluidos, aspect ratios
vwAncho del viewportTipografía grande, secciones full-width
vhAlto del viewportSecciones full-screen (min-height: 100vh)
dvhViewport dinámico (con barras de navegación)Móvil: reemplaza vh para evitar saltos
frFracción del espacio disponible en GridSolo en Grid
chAncho del carácter "0"Ancho de línea de texto (60-75ch ideal)
clamp-y-funciones.css
/* ── clamp(min, ideal, max) ──────────────────── */
/* El valor más poderoso del CSS moderno */

h1 {
  /* No menos de 32px, idealmente 5vw, no más de 80px */
  font-size: clamp(32px, 5vw, 80px);
  /* Se adapta fluidamente sin media queries */
}

h2 { font-size: clamp(24px, 3.5vw, 48px); }
p  { font-size: clamp(15px, 1.2vw, 18px); }

/* ── min() y max() ───────────────────────────── */
.container {
  /* El menor de los dos: 100% o 1200px */
  width: min(100%, 1200px);
  margin: 0 auto;
}

.hero-title {
  /* Al menos 48px (aunque la pantalla sea pequeña) */
  font-size: max(48px, 8vw);
}

/* ── Espaciado fluido ────────────────────────── */
.section {
  padding: clamp(48px, 8vw, 120px) clamp(20px, 5vw, 80px);
  /* Padding que escala con la pantalla, sin media queries */
}

/* ── Ancho máximo de lectura ─────────────────── */
.text-content {
  max-width: 65ch;  /* 65 caracteres = legibilidad óptima */
  margin: 0 auto;
}

/* ── dvh: el vh que funciona en móvil ───────── */
.hero {
  min-height: 100dvh;  /* dinámico: respeta barra del navegador */
  /* fallback para navegadores viejos: */
  min-height: 100vh;
  min-height: 100dvh;
}
💡 la calculadora de clamp

Calcular los valores de clamp puede ser complicado. Usa clamp.font-size.app — introduces el tamaño en móvil y desktop y te da el valor clamp exacto.

M02 Técnica + Visual Lección 3.1 ⏱ 40 min

Tipografía web:
el diseño invisible

El 95% del diseño web es tipografía. Una fuente elegida con intención y configurada correctamente puede transformar completamente la personalidad de un proyecto.

Cómo cargar fuentes en web

fuentes.css
/* ── OPCIÓN 1: Google Fonts (link en HTML) ──── */
<!-- En el <head> de tu HTML -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?
  family=Bricolage+Grotesque:opsz,wght@12..96,300;12..96,800
  &family=Playfair+Display:ital,wght@1,300
  &display=swap" rel="stylesheet">

/* ── OPCIÓN 2: @font-face local (más control) ─ */
@font-face {
  font-family: 'MiFuente';
  src: url('fonts/mifuente.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;  /* muestra fallback mientras carga */
}

/* ── PROPIEDADES tipográficas ─────────────────── */
body {
  font-family: 'Bricolage Grotesque', sans-serif;
  font-size: 16px;           /* base */
  line-height: 1.7;           /* sin unidad: relativo al font-size */
  letter-spacing: -0.01em;   /* tracking ligeramente condensado */
  font-weight: 400;           /* regular */
  font-optical-sizing: auto; /* para variable fonts */
}

h1, h2, h3 {
  font-family: 'Bricolage Grotesque', sans-serif;
  font-weight: 800;
  line-height: 1.0;           /* más ajustado en títulos grandes */
  letter-spacing: -0.03em;   /* tracking negativo en display type */
}

/* ── VARIABLE FONTS: una fuente, infinitos pesos ─ */
h2 {
  font-variation-settings:
    'wght' 750,              /* peso variable (entre 100-900) */
    'wdth' 110;              /* ancho variable */
}

/* Animar el peso en hover con variable fonts */
a:hover {
  font-variation-settings: 'wght' 800;
  transition: font-variation-settings 0.3s;
}

Escala tipográfica perfecta

Una escala tipográfica es una progresión de tamaños armoniosa. Las más usadas siguen razones matemáticas como la proporción áurea (1.618) o la quinta mayor (1.5).

escala-tipografica.css
/* Escala perfecta × 1.25 (Major Third) */
:root {
  --text-xs:   0.64rem;   /* ~10px */
  --text-sm:   0.8rem;    /* ~13px */
  --text-base: 1rem;      /* 16px — base */
  --text-lg:   1.25rem;   /* ~20px */
  --text-xl:   1.563rem;  /* ~25px */
  --text-2xl:  1.953rem;  /* ~31px */
  --text-3xl:  2.441rem;  /* ~39px */
  --text-4xl:  3.052rem;  /* ~49px */
  /* Con clamp para que sea fluida: */
  --text-hero: clamp(3rem, 8vw, 8rem);
}

/* Genera la tuya: typescale.com */

Fuentes recomendadas para proyectos creativos

Ejercicio 3.1 · Sistema tipográfico para tu portfolio
⏱ 35 min
  • 1
    Ve a Google Fonts. Elige 2 fuentes: una display (para títulos) y una para cuerpo. Descárgalas o genera el <link>.
  • 2
    En Typescale.com, configura tu escala tipográfica. Exporta las variables CSS y agrégalas a tu :root.
  • 3
    Usa clamp() para que los títulos principales sean fluidos entre móvil y desktop.
  • 4
    Ajusta line-height, letter-spacing y max-width: 65ch en párrafos para máxima legibilidad.
M02 Técnica + Visual Lección 3.2 ⏱ 40 min

Color y gradientes:
atmósfera visual

El color en CSS va mucho más allá de los hexadecimales. Gradientes, mezclas, transparencias y el nuevo espacio oklch te dan control total sobre la paleta.

Sistemas de color en CSS

sistemas-color.css
/* ── FORMATOS DE COLOR ────────────────────────── */
color: #c84b2f;                  /* Hex: compacto, más usado */
color: rgb(200, 75, 47);          /* RGB: útil con variables */
color: rgba(200, 75, 47, 0.5);    /* RGBA: con transparencia */
color: hsl(12, 62%, 48%);        /* HSL: más intuitivo (matiz, sat, light) */
color: hsl(12 62% 48% / 0.5);   /* HSL con alpha (sintaxis moderna) */

/* ── oklch: el futuro del color en CSS ──────── */
/* Perceptualmente uniforme: L=lightness, C=chroma, H=hue */
color: oklch(0.65 0.18 30);      /* rojo cálido */
color: oklch(0.80 0.14 160);     /* verde menta */
/* oklch garantiza que el 50% de lightness es visualmente igual en todos los colores */

/* ── GRADIENTES ──────────────────────────────── */
background: linear-gradient(
  135deg,
  #0a0a14 0%,
  #1a0a2e 100%
);

background: radial-gradient(
  ellipse at 80% 50%,
  rgba(110, 231, 183, 0.3) 0%,
  transparent 60%
);

/* Gradiente cónico (para círculos de color) */
background: conic-gradient(
  from 0deg,
  #6ee7b7, #818cf8, #fb923c, #6ee7b7
);

/* Múltiples gradientes apilados */
background:
  radial-gradient(circle at 20% 80%, rgba(129,140,248,.3) 0%, transparent 50%),
  radial-gradient(circle at 80% 20%, rgba(110,231,183,.2) 0%, transparent 50%),
  #0c0c10;

/* ── MIX-BLEND-MODE: para efectos creativos ─── */
.overlay {
  mix-blend-mode: screen;      /* mezcla con lo que hay debajo */
  mix-blend-mode: multiply;    /* multiplica colores */
  mix-blend-mode: overlay;     /* contraste dramático */
}

Paletas de color: recursos

M02 Técnica + Visual Lección 3.3 ⏱ 40 min

Efectos visuales
con CSS puro

CSS moderno tiene superpoderes visuales que muchos no conocen: clip-path, backdrop-filter, mask-image y más. Estos efectos son los que hacen que un sitio parezca obra de arte.

efectos-css-avanzados.css
/* ── clip-path: formas creativas ─────────────── */
.hero-diagonal {
  clip-path: polygon(0 0, 100% 0, 100% 85%, 0 100%);
  /* Diagonal en el fondo: top izq, top der, bottom der, bottom izq */
}

.hexagono {
  clip-path: polygon(50% 0%, 100% 25%, 100% 75%, 50% 100%, 0% 75%, 0% 25%);
}

/* Animable! */
.btn:hover {
  clip-path: polygon(0 0, 100% 0, 100% 100%, 0 100%);
  transition: clip-path .5s cubic-bezier(.77,0,.175,1);
}

/* ── backdrop-filter: vidrio difuminado ──────── */
.glass-card {
  background: rgba(255, 255, 255, 0.08);
  backdrop-filter: blur(20px) saturate(180%);
  -webkit-backdrop-filter: blur(20px);
  border: 1px solid rgba(255,255,255,.15);
  border-radius: 16px;
}

/* ── filter: efectos de imagen ───────────────── */
.img-project {
  filter: grayscale(100%);         /* blanco y negro */
  transition: filter .4s;
}
.img-project:hover {
  filter: grayscale(0%) saturate(130%); /* full color al hover */
}

/* ── mask-image: desenmascarar ───────────────── */
.fade-bottom {
  mask-image: linear-gradient(to bottom, black 60%, transparent 100%);
  -webkit-mask-image: linear-gradient(to bottom, black 60%, transparent);
}

/* ── text-stroke: texto con borde ────────────── */
.outline-text {
  -webkit-text-stroke: 1px var(--accent);
  color: transparent;
}

/* ── aspect-ratio: proporciones perfectas ────── */
.project-thumb { aspect-ratio: 16 / 9; }
.avatar         { aspect-ratio: 1; border-radius: 50%; }
.card-tall      { aspect-ratio: 3 / 4; }

/* ── scroll-snap: scroll cinematográfico ─────── */
.scroll-container {
  overflow-y: scroll;
  scroll-snap-type: y mandatory;
  height: 100vh;
}
.section {
  scroll-snap-align: start;
  height: 100vh;
}

Generadores de efectos CSS

Ejercicio 3.3 · Tarjetas con efectos visuales CSS
⏱ 40 min
  • 1
    En tus tarjetas de proyecto: aplica filter: grayscale(100%) a las imágenes. En hover, anima de vuelta a color.
  • 2
    Crea un efecto glassmorphism en la card de contacto usando backdrop-filter: blur().
  • 3
    Usa Clippy para crear un clip-path diagonal en tu sección hero.
  • 4
    Aplica -webkit-text-stroke a tu nombre o título principal para crear texto solo con contorno.
M02 Técnica + Demo Lección 4.1 ⏱ 35 min

Transitions:
suavidad intencional

Una transition es la diferencia entre un cambio abrupto y una transición fluida. Son la forma más simple de añadir vida a una interfaz — y las más usadas en el día a día.

transitions-completo.css
/* ── Sintaxis ─────────────────────────────────── */
/* transition: propiedad duración timing-function delay */
.btn {
  transition: background .25s ease;
  /* o múltiples propiedades: */
  transition: background .25s ease, transform .3s cubic-bezier(.34,1.56,.64,1);
  /* o todo a la vez (usa con cuidado, puede ser costoso): */
  transition: all .25s ease;
}

/* ── Timing functions: la personalidad de la animación ── */
transition-timing-function: ease;            /* rápido al inicio, lento al final */
transition-timing-function: linear;          /* velocidad constante */
transition-timing-function: ease-in;         /* lento al inicio */
transition-timing-function: ease-out;        /* lento al final (más natural) */
transition-timing-function: ease-in-out;     /* lento en ambos extremos */

/* cubic-bezier: control total de la curva */
transition-timing-function: cubic-bezier(.34, 1.56, .64, 1); /* spring/rebote */
transition-timing-function: cubic-bezier(.77, 0, .175, 1);  /* exponential */
transition-timing-function: cubic-bezier(.16, 1, .3, 1);    /* ease out expo */

/* ── Propiedades animables (y performantes) ───── */
/* Usar solo estas — son renderizadas por la GPU: */
transform: translateX(0) translateY(0) scale(1) rotate(0deg);
opacity: 01;

/* Evitar animar (fuerzan reflow, son lentas): */
/* width, height, top, left, margin, padding, font-size */

/* ── Patrones de hover comunes ────────────────── */
.card:hover {
  transform: translateY(-8px);
  box-shadow: 0 20px 60px rgba(0,0,0,.3);
}

.btn:hover {
  transform: scale(1.04);
}

.link:hover {
  transform: translateX(4px);  /* desplazamiento lateral */
}

/* ── will-change: hint para la GPU ───────────── */
.animated-element {
  will-change: transform, opacity;  /* prepara el elemento para animación */
  /* Úsalo solo cuando la animación ya ocurre, no siempre */
}
💡 la curva de bezier perfecta

Ve a cubic-bezier.com para crear curvas de animación personalizadas visualmente. El valor cubic-bezier(.34, 1.56, .64, 1) da un efecto de "spring" muy satisfactorio.

M02 Demo en vivo Lección 4.2 ⏱ 45 min

@keyframes:
coreografía CSS

Con @keyframes defines secuencias de animación completas — no solo de A a B, sino de A a B a C a D. Son el equivalente de los fotogramas clave de un motion designer.

Animaciones en vivo

Ejemplos de @keyframes — CSS puro
morph + rotate
pulse glow
slide ease-out
Aa
variable font weight

Sintaxis completa

keyframes-completo.css
/* ── Definir la animación ─────────────────────── */
@keyframes fadeInUp {
  from {
    opacity: 0;
    transform: translateY(30px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

/* Múltiples puntos (%) */
@keyframes morphing {
  0%   { border-radius: 8px; transform: scale(1); }
  50%  { border-radius: 50%; transform: scale(1.2); }
  100% { border-radius: 8px; transform: scale(1); }
}

/* ── Aplicar la animación ─────────────────────── */
.hero-title {
  animation: fadeInUp 1.2s cubic-bezier(.16,1,.3,1) both;

  /* Propiedades individuales: */
  animation-name: fadeInUp;
  animation-duration: 1.2s;
  animation-timing-function: ease-out;
  animation-delay: 0.3s;
  animation-iteration-count: 1;     /* o infinite */
  animation-direction: normal;      /* o alternate (va y vuelve) */
  animation-fill-mode: both;        /* aplica desde el inicio y se queda al final */
  animation-play-state: running;    /* o paused — controlable con JS */
}

/* ── Efecto de entrada escalonada ─────────────── */
.nav-item:nth-child(1) { animation-delay: 0.1s; }
.nav-item:nth-child(2) { animation-delay: 0.2s; }
.nav-item:nth-child(3) { animation-delay: 0.3s; }
.nav-item:nth-child(4) { animation-delay: 0.4s; }

/* ── Reducir movimiento para accesibilidad ───── */
@media (prefers-reduced-motion: reduce) {
  .hero-title {
    animation: none;
    opacity: 1;
  }
}

Clip-path animado: el efecto "revelar"

reveal-animation.css
/* ── Texto que se revela con clip-path ────────── */
@keyframes textReveal {
  from {
    clip-path: inset(0 100% 0 0);  /* oculto desde la derecha */
    opacity: 0;
  }
  to {
    clip-path: inset(0 0% 0 0);   /* completamente visible */
    opacity: 1;
  }
}

.reveal {
  animation: textReveal 1s cubic-bezier(.77,0,.175,1) forwards;
  opacity: 0; /* empieza invisible */
}

/* ── Imagen que aparece con clip-path ─────────── */
@keyframes imageReveal {
  from { clip-path: inset(100% 0 0 0); } /* desde abajo */
  to   { clip-path: inset(0 0 0 0); }
}

.project-image {
  animation: imageReveal 1.2s cubic-bezier(.16,1,.3,1) both;
}
Ejercicio 4.2 · Animaciones de entrada para tu portfolio
⏱ 45 min
  • 1
    Crea el @keyframe fadeInUp y aplícalo al título principal, subtítulo y botón del hero con animation-delay escalonado (0.1s, 0.3s, 0.5s).
  • 2
    Aplica la animación textReveal con clip-path a tu nombre en el hero. Es el efecto más impactante de una primera impresión.
  • 3
    Añade el @media prefers-reduced-motion: reduce para deshabilitar animaciones en usuarios que lo soliciten.
  • 4
    Explora Animista y añade una animación diferente a las tarjetas de proyecto.
📌 Objetivo: Tu portfolio con animaciones de entrada fluidas, escalonadas y accesibles.
M02 Técnica + Nuevo Lección 4.3 ⏱ 40 min

Scroll animations:
CSS puro 2024

Animaciones vinculadas al scroll — sin JavaScript. La CSS Scroll-Driven Animations API es la novedad más emocionante de CSS en años y ya está disponible en todos los navegadores modernos.

🆕 CSS Scroll-Driven Animations (2024)

Hasta 2023, cualquier animación basada en scroll requería JavaScript (GSAP, Intersection Observer). Ahora CSS puede hacerlo solo con animation-timeline y animation-range. Soporte: Chrome 115+, Firefox 110+, Safari 18+.

scroll-animations.css
/* ── Barra de progreso de lectura ────────────── */
.progress-bar {
  position: fixed;
  top: 0; left: 0;
  width: 100%; height: 3px;
  background: var(--accent);
  transform-origin: left;
  animation: progress-grow linear;
  animation-timeline: scroll();       /* vinculada al scroll del documento */
  animation-range: entry 0% exit 100%;
}

@keyframes progress-grow {
  from { transform: scaleX(0); }
  to   { transform: scaleX(1); }
}

/* ── Elemento que aparece al entrar al viewport ─ */
.section {
  view-timeline-name: --section-reveal;
}

.section-content {
  animation: fadeInUp 0.8s ease both;
  animation-timeline: view();          /* vinculada a visibilidad del elemento */
  animation-range: entry 0% entry 40%; /* se anima mientras entra */
}

/* ── Parallax con scroll ──────────────────────── */
.parallax-bg {
  animation: parallax-move linear;
  animation-timeline: scroll();
}

@keyframes parallax-move {
  from { transform: translateY(-100px); }
  to   { transform: translateY(100px); }
}

/* ── Fallback para Intersection Observer (clásico) ─ */
/* Para navegadores sin soporte a scroll-driven: */
.reveal {
  opacity: 0;
  transform: translateY(30px);
  transition: opacity .8s, transform .8s;
}
.reveal.visible {
  opacity: 1;
  transform: translateY(0);
}
intersection-observer.js — fallback JS
// IntersectionObserver: detecta cuándo un elemento entra al viewport
// Funciona en TODOS los navegadores. Úsalo como fallback o complemento.

const observer = new IntersectionObserver((entries) => {
  entries.forEach(entry => {
    // Si el elemento está entrando en la vista:
    if (entry.isIntersecting) {
      entry.target.classList.add('visible');
      // Opcional: dejar de observar una vez que ya se vio
      observer.unobserve(entry.target);
    }
  });
}, {
  threshold: 0.15,     // 15% del elemento debe ser visible para activar
  rootMargin: '-50px' // margen negativo: activa un poco después
});

// Observar todos los elementos con clase .reveal
document.querySelectorAll('.reveal').forEach(el => {
  observer.observe(el);
});
Ejercicio 4.3 · Scroll reveal en tu portfolio
⏱ 40 min
  • 1
    Añade la barra de progreso de lectura con animation-timeline: scroll() al header de tu portfolio.
  • 2
    Añade la clase .reveal a cada tarjeta de proyecto y sección con opacity: 0; transform: translateY(30px).
  • 3
    Crea el IntersectionObserver en script.js para añadir la clase .visible cuando entren al viewport.
  • 4
    Intenta reemplazar el JS por animation-timeline: view() en Chrome y observa la diferencia.
📌 Objetivo: Portfolio con elementos que aparecen fluidamente al hacer scroll, tanto con CSS puro como con JS de fallback.
M02 Proyecto Final Entrega M02 ⏱ 5–8 horas

Portfolio responsive
con animaciones

Integra todo el módulo: Grid, Flexbox, responsive, tipografía fluida, efectos CSS, transitions y animaciones. Tu portfolio completo, vivo, en producción.

🎯 Objetivo del proyecto

Una web portfolio de una página completamente responsive (móvil → tablet → desktop), con sistema tipográfico y de color propio, efectos visuales CSS creativos y animaciones de entrada y scroll. Publicada en Vercel o GitHub Pages.

Checklist técnico de entrega

ÁreaRequisitoPuntos
LayoutGrid para estructura macro, Flex para componentes15
ResponsiveMobile-first, mínimo 2 breakpoints, sin overflow horizontal20
Tipografía2 fuentes pares, escala, clamp() en títulos, 65ch en párrafos15
ColorSistema CSS variables, gradientes, dark mode10
Efectos CSSclip-path, backdrop-filter o filter en elementos clave10
TransitionsHover states en cards, links y botones con cubic-bezier10
AnimacionesEntrada hero con @keyframes, scroll reveal en secciones15
Accesibilidadprefers-reduced-motion, alt en imágenes, contraste adecuado5

Estructura de archivos recomendada

estructura del proyecto
mi-portfolio/
├── index.html
├── styles/
│   ├── reset.css          ← normalize y * {}
│   ├── tokens.css         ← :root con variables
│   ├── layout.css         ← Grid y Flex estructura
│   ├── components.css     ← cards, nav, footer
│   ├── typography.css     ← fuentes y escala
│   └── animations.css     ← @keyframes y transitions
├── js/
│   └── scroll-reveal.js   ← IntersectionObserver
├── assets/
│   ├── images/
│   └── fonts/             ← si usas fuentes locales
└── README.md
💡 cómo publicar en Vercel (aún más fácil que GitHub Pages)

Ve a vercel.comNew Project → importa tu repositorio de GitHub. Vercel lo despliega automáticamente. Cada git push actualiza el sitio en producción en segundos.

Inspiración para el proyecto final

Portfolio diseño
Portfolios con grid asimétrico
Portfolio dark
Dark mode con glassmorphism
Typography web
Tipografía como elemento visual

✓ Módulo 02 completado

Al finalizar este módulo puedes hacer desde cero:

  • Crear cualquier layout con Flexbox y CSS Grid
  • Diseñar mobile-first con media queries y unidades fluidas
  • Configurar un sistema tipográfico con clamp() y escala
  • Usar gradientes, clip-path y efectos CSS avanzados
  • Crear transitions y @keyframes expresivas con cubic-bezier
  • Implementar scroll animations con CSS y JavaScript
  • Publicar en Vercel con deploy automático

→ Módulo 03: Interactividad & JavaScript

DOM manipulation · Eventos · requestAnimationFrame · GSAP · p5.js · Tu diseño cobra vida