SCSS
SCSS
CSS con superpoderes: escribe estilos más organizados y potentes.
Imagina que llevas semanas trabajando en tu proyecto. Tu archivo CSS ya tiene 500 líneas. El color principal de tu marca, ese verde vibrante #00ff41, aparece repetido en 47 lugares distintos. Un día tu cliente te llama: “Cambiamos el color corporativo, ahora es azul.”
Y tú tienes que hacer buscar-y-reemplazar en todo el archivo, rezando para no romper nada.
Hay una forma mejor. Se llama SCSS.
1. ¿Qué es SCSS?
Sección titulada «1. ¿Qué es SCSS?»SCSS (que viene de Sassy CSS) es un preprocesador de CSS. Es decir, es CSS con poderes extra que te hacen la vida más fácil.
La idea es sencilla: tú escribes archivos .scss, y una herramienta los compila a archivos .css normales que el navegador entiende perfectamente. El navegador nunca ve el SCSS; solo ve el CSS resultante.
Compilar significa transformar un código de un formato a otro. Es como escribir tus apuntes en taquigrafía (SCSS) y luego pasarlos a limpio para que otros los entiendan (CSS). El resultado final dice exactamente lo mismo, pero el proceso de escribirlo fue mucho más rápido y cómodo.
Sass vs SCSS: ¿cuál es la diferencia?
Sección titulada «Sass vs SCSS: ¿cuál es la diferencia?»Sass es el nombre del preprocesador. Tiene dos sintaxis:
- Sass (sintaxis antigua): usa indentación, sin llaves ni punto y coma. Se parece más a Python.
- SCSS (sintaxis moderna): usa llaves
{}y punto y coma;, igual que CSS normal.
// Sintaxis Sass (antigua) - sin llaves.card padding: 2rem background: #13131f
.title font-size: 1.5rem// Sintaxis SCSS (moderna) - con llaves, como CSS.card { padding: 2rem; background: #13131f;
.title { font-size: 1.5rem; }}Nosotros usaremos SCSS porque se parece a CSS y la curva de aprendizaje es mucho menor. Si ya sabes CSS, ya sabes casi todo el SCSS.
2. Instalación y configuración
Sección titulada «2. Instalación y configuración»Hay varias formas de usar SCSS en tu proyecto. Elige la que mejor se adapte a tu situación:
Esta opción es perfecta si tienes un proyecto HTML/CSS sin frameworks o si quieres experimentar de forma independiente.
# Instalar Sass globalmente en tu sistemanpm install -g sass
# Compilar un archivo concretosass style.scss style.css
# Compilar con watch: recompila automáticamente cada vez que guardassass --watch style.scss:style.css
# Compilar toda una carpeta de una vezsass --watch scss/:css/El modo --watch es el que usarás en el día a día. Lo dejas corriendo en la terminal y cada vez que guardas tu .scss, el .css se actualiza solo.
Tu estructura de proyecto quedaría así:
mi-proyecto/├── index.html├── scss/│ ├── style.scss ← aquí escribes│ └── _variables.scss ← archivos parciales└── css/ └── style.css ← generado automáticamente, no lo toquesEn tu index.html, enlaza el CSS compilado como siempre:
<link rel="stylesheet" href="css/style.css">Si usas Vite (el bundler moderno más popular), la configuración es prácticamente automática. Vite soporta SCSS de forma nativa; solo necesitas instalar el paquete de Sass.
# Crear un proyecto con Vitenpm create vite@latest mi-proyectocd mi-proyectonpm install
# Instalar Sass como dependencia de desarrollonpm install -D sass
# Iniciar el servidor de desarrollonpm run devLuego crea tu archivo .scss e impórtalo en tu main.js:
import './style.scss'O en tu HTML directamente:
<link rel="stylesheet" href="/style.scss">Vite se encarga de compilar el SCSS en el momento. No necesitas configurar nada más.
Si prefieres no tocar la terminal, esta extensión hace todo el trabajo por ti desde el editor.
-
Abre VS Code y ve al panel de extensiones (icono de cuadraditos en la barra lateral, o
Ctrl+Shift+X) -
Busca “Live Sass Compiler” (de Glenn Marks) e instálala
-
Abre tu archivo
.scsso cualquier archivo del proyecto -
En la barra de estado inferior de VS Code verás el botón “Watch Sass”. Haz clic en él.
-
Listo. Cada vez que guardes un archivo
.scss, la extensión compilará el.cssautomáticamente.
3. Variables
Sección titulada «3. Variables»Recuerdas el problema del principio: el color #00ff41 repetido 47 veces. Con CSS puro puedes usar custom properties (--variables), pero SCSS lleva las variables un paso más allá.
El problema
Sección titulada «El problema»/* CSS puro - el color repetido en todas partes */.header { background: #00ff41; }.btn-primary { background: #00ff41; }.link:hover { color: #00ff41; }.badge { border-color: #00ff41; }/* ... 43 veces más */La solución con SCSS
Sección titulada «La solución con SCSS»Con SCSS defines la variable una sola vez y la usas en cualquier lugar:
// Defines tus variables al principio del archivo$color-primary: #00ff41;$color-secondary: #7c3aed;$color-bg: #0a0a0f;$color-text: #e4e4e7;$color-muted: #71717a;
$font-main: 'Inter', sans-serif;$font-mono: 'Fira Code', monospace;
$spacing-xs: 0.5rem;$spacing-sm: 1rem;$spacing-md: 1.5rem;$spacing-lg: 2rem;$spacing-xl: 4rem;
$border-radius-sm: 4px;$border-radius: 8px;$border-radius-lg: 16px;
// Ahora las usas en cualquier lugar.header { background: $color-bg; color: $color-primary;}
.btn { background: $color-primary; font-family: $font-main; padding: $spacing-sm $spacing-lg; border-radius: $border-radius;}
.link:hover { color: $color-primary;}Ahora, si el cliente cambia el color, solo modificas una línea y el cambio se propaga a los 47 lugares automáticamente.
SCSS variables vs CSS custom properties
Sección titulada «SCSS variables vs CSS custom properties»Puede que te preguntes: “¿Y las variables CSS que ya aprendí (--color-primary)? ¿Para qué sirven las de SCSS?”
Son diferentes y no se excluyen; puedes usar las dos:
SCSS $variable |
CSS --variable |
|
|---|---|---|
| Cuándo existe | Solo durante la compilación | En el navegador, en tiempo real |
| Se puede cambiar con JS | No (ya no existe en el CSS) | Sí |
Puede usarse en @media |
Sí | No directamente |
| El navegador la ve | No | Sí |
// Una práctica muy común: usar variables SCSS para definir// las CSS custom properties, lo mejor de ambos mundos
$color-primary: #00ff41;$color-bg: #0a0a0f;
:root { --color-primary: #{$color-primary}; // La #{} convierte el valor de SCSS a texto --color-bg: #{$color-bg};}
// Luego en tu CSS/SCSS usas la que necesites según el caso.btn { background: $color-primary; // SCSS: calculada en compilación color: var(--color-primary); // CSS: cambiable desde JS si necesitas temas}4. Anidamiento (Nesting)
Sección titulada «4. Anidamiento (Nesting)»En CSS, cuando quieres estilizar elementos dentro de una tarjeta, tienes que repetir el selector padre una y otra vez:
/* CSS puro - repetitivo y difícil de leer */.card { padding: 2rem; background: #13131f; }.card .title { font-size: 1.5rem; color: #e4e4e7; }.card .description { color: #71717a; margin-top: 0.5rem; }.card .btn { margin-top: 1.5rem; }.card:hover { border-color: #00ff41; }.card:hover .title { color: #00ff41; }Con SCSS puedes anidar los selectores dentro de su padre, igual que la estructura del HTML:
.card { padding: 2rem; background: #13131f; border: 1px solid transparent; border-radius: $border-radius; transition: border-color 0.3s;
.title { font-size: 1.5rem; color: $color-text; margin-bottom: 0.5rem; }
.description { color: $color-muted; line-height: 1.6; }
.btn { margin-top: 1.5rem; }
// El símbolo & representa el selector padre (.card en este caso) &:hover { border-color: $color-primary;
.title { color: $color-primary; } }}Esto compila exactamente al mismo CSS que el ejemplo anterior, pero es mucho más fácil de leer y mantener.
El símbolo & (selector padre)
Sección titulada «El símbolo & (selector padre)»El & es uno de los elementos más útiles de SCSS. Representa el selector del bloque donde estás:
.btn { padding: 0.75rem 2rem; background: $color-primary;
// &:hover → .btn:hover &:hover { background: darken($color-primary, 10%); }
// &:focus → .btn:focus &:focus { outline: 2px solid $color-primary; outline-offset: 2px; }
// &::before → .btn::before &::before { content: ''; position: absolute; }
// &.active → .btn.active (cuando tiene ambas clases) &.active { background: darken($color-primary, 20%); }
// &--large → .btn--large (notación BEM) &--large { padding: 1rem 3rem; font-size: 1.25rem; }
// &--secondary → .btn--secondary &--secondary { background: transparent; border: 1px solid $color-primary; color: $color-primary; }}El & con BEM (Block, Element, Modifier) es especialmente útil porque puedes escribir toda la variante de un componente en un solo bloque:
.card { // Bloque base padding: 2rem;
// Elemento: .card__icon &__icon { font-size: 2rem; margin-bottom: 1rem; }
// Elemento: .card__title &__title { font-size: 1.5rem; }
// Modificador: .card--featured &--featured { border: 2px solid $color-primary; background: rgba($color-primary, 0.05); }
// Modificador: .card--compact &--compact { padding: 1rem; }}No te pases: el anidamiento máximo es 3 niveles
Sección titulada «No te pases: el anidamiento máximo es 3 niveles»El anidamiento es poderoso pero hay que usarlo con moderación. Si te pasas, el CSS que genera es demasiado específico y difícil de mantener.
// MAL: demasiados niveles de anidamiento.header { .nav { .nav-list { .nav-item { .nav-link { // Ya vamos por 5 niveles &:hover { span { ... } // 7 niveles - esto es un desastre } } } } }}// Genera: .header .nav .nav-list .nav-item .nav-link:hover span// Ese selector es muy difícil de sobrescribir si lo necesitas// BIEN: máximo 3 niveles.header { padding: 1rem;
.nav { display: flex; gap: 1rem; }
.nav-link { color: $color-text;
&:hover { color: $color-primary; } }}5. Partials e imports
Sección titulada «5. Partials e imports»Un archivo CSS de 2000 líneas es una pesadilla. SCSS te permite dividirlo en archivos pequeños y organizados, y luego juntarlos todos en uno solo para el navegador.
Los partials (archivos parciales)
Sección titulada «Los partials (archivos parciales)»Un partial es un archivo SCSS que empieza con guion bajo (_). El guion bajo le dice a Sass: “este archivo no debe compilarse solo, solo se usa cuando alguien lo importa”.
scss/├── style.scss ← archivo principal (sin guion bajo)├── _variables.scss ← partial de variables├── _reset.scss ← partial de reset/normalize├── _typography.scss ← partial de tipografía├── _header.scss ← partial del header├── _footer.scss ← partial del footer├── _cards.scss ← partial de componente tarjetas├── _buttons.scss ← partial de botones└── _utilities.scss ← partial de clases de utilidadCada archivo contiene solo lo que le corresponde. El archivo principal los une todos:
// style.scss - el archivo principal// Primero los partials de configuración@use 'variables';@use 'reset';@use 'typography';
// Luego los componentes@use 'header';@use 'footer';@use 'cards';@use 'buttons';
// Por último las utilidades (para que tengan mayor especificidad)@use 'utilities';Y así quedaría cada archivo:
$color-primary: #00ff41;$color-secondary: #7c3aed;$color-bg: #0a0a0f;$color-text: #e4e4e7;$color-muted: #71717a;
$font-main: 'Inter', sans-serif;$spacing-md: 1.5rem;$border-radius: 8px;*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0;}
body { font-family: $font-main; background: $color-bg; color: $color-text; line-height: 1.6;}.header { padding: 1rem $spacing-md; background: rgba($color-bg, 0.95); backdrop-filter: blur(10px); border-bottom: 1px solid rgba($color-primary, 0.1);
.nav-link { color: $color-text; text-decoration: none;
&:hover { color: $color-primary; } }}@use vs @import: el moderno y el antiguo
Sección titulada «@use vs @import: el moderno y el antiguo»Si buscas tutoriales de SCSS en internet, verás muchos que usan @import. Debes saber que @import está deprecado (en desuso) y será eliminado en versiones futuras de Sass.
La forma moderna es @use:
// Forma antigua (NO uses esto en proyectos nuevos)@import 'variables';@import 'header';
// Forma moderna (usa esta)@use 'variables';@use 'header';La diferencia principal es que con @use, las variables de un archivo no “contaminan” automáticamente los demás. Cada archivo tiene su propio espacio de nombres:
$primary: #00ff41;$bg: #0a0a0f;// header.scss - usando @use@use 'colors'; // Las variables de colors se acceden con colors.$variable
.header { background: colors.$bg; color: colors.$primary;}// También puedes darle un alias@use 'colors' as c;
.header { background: c.$bg;}
// O importar directamente al espacio de nombres actual@use 'colors' as *;
.header { background: $bg; // Sin prefijo}Para proyectos medianos y grandes, organiza tus SCSS con una carpeta por tipo:
scss/├── abstracts/ ← variables, mixins, funciones (no generan CSS)│ ├── _variables.scss│ ├── _mixins.scss│ └── _functions.scss├── base/ ← reset, tipografía base│ ├── _reset.scss│ └── _typography.scss├── components/ ← botones, tarjetas, modales│ ├── _buttons.scss│ └── _cards.scss├── layout/ ← header, footer, grid│ ├── _header.scss│ └── _footer.scss└── style.scss ← archivo principal que une todoEsta estructura se conoce como la arquitectura 7-1 (adaptada) y es muy usada en proyectos profesionales.
6. Mixins
Sección titulada «6. Mixins»Un mixin es como una función en CSS: defines un bloque de estilos con un nombre, y luego lo “llamas” en cualquier lugar que lo necesites.
El problema
Sección titulada «El problema»/* Flexbox centrado: lo escribes en 15 sitios diferentes */.hero { display: flex; justify-content: center; align-items: center; }.modal { display: flex; justify-content: center; align-items: center; }.card-icon { display: flex; justify-content: center; align-items: center; }/* ... */Mixin básico
Sección titulada «Mixin básico»// Defines el mixin con @mixin@mixin flex-center { display: flex; justify-content: center; align-items: center;}
// Lo usas con @include.hero { @include flex-center; min-height: 100vh; background: $color-bg;}
.modal { @include flex-center; position: fixed; inset: 0;}
.card-icon { @include flex-center; width: 4rem; height: 4rem; border-radius: 50%;}Mixins con parámetros
Sección titulada «Mixins con parámetros»Al igual que las funciones, los mixins pueden recibir argumentos:
// Mixin con parámetro requerido@mixin flex-gap($gap) { display: flex; gap: $gap;}
// Mixin con parámetro con valor por defecto@mixin flex-gap($gap: 1rem, $direction: row) { display: flex; flex-direction: $direction; gap: $gap;}
// Mixin para sombras con personalización@mixin shadow($color: #000, $intensity: 0.2) { box-shadow: 0 4px 6px rgba($color, $intensity), 0 1px 3px rgba($color, $intensity * 0.5);}
// Cómo usarlos.nav { @include flex-gap(2rem);}
.sidebar { @include flex-gap(1rem, column);}
.card { @include shadow($color-primary, 0.15);}
.modal { @include shadow(#000, 0.4);}El mixin más útil: breakpoints responsivos
Sección titulada «El mixin más útil: breakpoints responsivos»En el capítulo anterior viste cómo hacer diseño responsive con media queries. Con SCSS puedes crear un mixin que simplifique enormemente la sintaxis:
@mixin responsive($breakpoint) { @if $breakpoint == mobile { @media (min-width: 480px) { @content; } } @else if $breakpoint == tablet { @media (min-width: 768px) { @content; } } @else if $breakpoint == desktop { @media (min-width: 1024px) { @content; } } @else if $breakpoint == wide { @media (min-width: 1280px) { @content; } }}El @content es especial: es el lugar donde se inserta el contenido que escribas dentro del @include. Así se usa:
.hero { // Estilos base (mobile first) padding: 2rem 1rem; text-align: center;
h1 { font-size: 2rem; }
// Estilos para tablet @include responsive(tablet) { padding: 4rem 2rem; text-align: left;
h1 { font-size: 3rem; } }
// Estilos para desktop @include responsive(desktop) { padding: 6rem 4rem;
h1 { font-size: 4rem; } }}Fíjate lo limpio que queda: los estilos responsive van junto al componente al que pertenecen, no dispersos al final del archivo.
// Otro mixin muy útil: truncar texto con puntos suspensivos@mixin text-truncate($lines: 1) { @if $lines == 1 { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } @else { display: -webkit-box; -webkit-line-clamp: $lines; -webkit-box-orient: vertical; overflow: hidden; }}
.card__title { @include text-truncate(2); // Máximo 2 líneas, luego "..."}
.badge { @include text-truncate; // Una sola línea}7. Extend / Herencia
Sección titulada «7. Extend / Herencia»El @extend te permite decir: “este selector hereda todos los estilos de aquel otro”. Es como la herencia en programación orientada a objetos.
Placeholder selectors %
Sección titulada «Placeholder selectors %»La forma más limpia de usar @extend es con placeholder selectors, que empiezan con %. Un placeholder no genera CSS por sí solo; solo existe para ser extendido:
// Este bloque NO genera CSS directamente%btn-base { display: inline-flex; align-items: center; gap: 0.5rem; padding: 0.75rem 2rem; border-radius: $border-radius; font-family: $font-main; font-weight: 600; font-size: 1rem; cursor: pointer; border: none; text-decoration: none; transition: all 0.2s ease;
&:focus-visible { outline: 2px solid $color-primary; outline-offset: 2px; }}
// Estos SÍ generan CSS y heredan todo lo de %btn-base.btn-primary { @extend %btn-base; background: $color-primary; color: $color-bg;
&:hover { background: darken($color-primary, 10%); }}
.btn-secondary { @extend %btn-base; background: transparent; border: 1px solid $color-primary; color: $color-primary;
&:hover { background: rgba($color-primary, 0.1); }}
.btn-ghost { @extend %btn-base; background: transparent; color: $color-text;
&:hover { background: rgba(255, 255, 255, 0.05); }}El CSS que genera agrupa los selectores automáticamente:
/* CSS generado */.btn-primary, .btn-secondary, .btn-ghost { display: inline-flex; align-items: center; /* ... todos los estilos base */}
.btn-primary { background: #00ff41; color: #0a0a0f; }.btn-secondary { background: transparent; border: 1px solid #00ff41; }.btn-ghost { background: transparent; color: #e4e4e7; }¿Cuándo usar @extend y cuándo @mixin?
Sección titulada «¿Cuándo usar @extend y cuándo @mixin?»Esta es una pregunta habitual. Aquí tienes la guía práctica:
| Situación | Usa |
|---|---|
| Grupo de propiedades que siempre van juntas sin variaciones | @extend / %placeholder |
| Necesitas pasar parámetros o valores variables | @mixin |
Quieres envolver contenido con @content (ej: media queries) |
@mixin |
| Estilizas variantes de un mismo componente base | @extend |
| Trabajas dentro de media queries | @mixin (extend no funciona bien con media queries) |
8. Operaciones y funciones
Sección titulada «8. Operaciones y funciones»SCSS puede hacer cálculos matemáticos y tiene funciones integradas muy útiles para trabajar con colores.
Operaciones matemáticas
Sección titulada «Operaciones matemáticas»$columnas: 12;$espaciado: 1rem;
.grid-item { // División width: 100% / $columnas; // 8.333%
// Multiplicación padding: $espaciado * 1.5; // 1.5rem
// Suma y resta width: calc(50% - #{$espaciado}); // Mezclar con calc() de CSS
// Módulo (resto de la división) margin: $espaciado % 3;}Funciones de color
Sección titulada «Funciones de color»Esta es de las características más poderosas de SCSS: manipular colores de forma programática.
$color-primary: #00ff41;$color-danger: #ef4444;
.btn-primary { background: $color-primary;
// darken: oscurece el color X% &:hover { background: darken($color-primary, 10%); }
// lighten: aclara el color X% &:active { background: lighten($color-primary, 5%); }}
// rgba: convierte un color hexadecimal a rgba.overlay { background: rgba($color-primary, 0.1); // Verde muy transparente}
.modal-backdrop { background: rgba(#000, 0.8);}
// saturate / desaturate: más o menos saturado.btn-disabled { background: desaturate($color-primary, 80%); // Casi gris cursor: not-allowed;}
// mix: mezcla dos colores en una proporción$color-mixed: mix($color-primary, $color-secondary, 50%);
// adjust-hue: gira el tono en el círculo cromático$color-analogous: adjust-hue($color-primary, 30deg);
// complement: el color complementario (opuesto en el círculo)$color-complement: complement($color-primary);Ejemplo práctico: generar una paleta de color completa a partir de un solo color:
$base: #00ff41;
$color-50: lighten($base, 45%);$color-100: lighten($base, 35%);$color-200: lighten($base, 25%);$color-300: lighten($base, 15%);$color-400: lighten($base, 5%);$color-500: $base;$color-600: darken($base, 5%);$color-700: darken($base, 15%);$color-800: darken($base, 25%);$color-900: darken($base, 35%);9. Ejemplo práctico completo
Sección titulada «9. Ejemplo práctico completo»Vamos a poner todo junto en un ejemplo real: una tarjeta de proyecto con sus variantes.
// ============================================================// ============================================================$color-primary: #00ff41;$color-bg: #0a0a0f;$color-surface: #13131f;$color-text: #e4e4e7;$color-muted: #71717a;$color-border: #27272a;
$font-main: 'Inter', sans-serif;$font-mono: 'Fira Code', monospace;
$spacing-sm: 1rem;$spacing-md: 1.5rem;$spacing-lg: 2rem;$spacing-xl: 4rem;
$border-radius: 8px;$border-radius-lg: 16px;$transition: all 0.3s ease;// ============================================================// ============================================================@use 'variables' as *;
@mixin flex-center { display: flex; justify-content: center; align-items: center;}
@mixin flex-between { display: flex; justify-content: space-between; align-items: center;}
@mixin responsive($breakpoint) { @if $breakpoint == tablet { @media (min-width: 768px) { @content; } } @else if $breakpoint == desktop { @media (min-width: 1024px) { @content; } }}
@mixin text-truncate($lines: 1) { @if $lines == 1 { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } @else { display: -webkit-box; -webkit-line-clamp: $lines; -webkit-box-orient: vertical; overflow: hidden; }}// ============================================================// ============================================================@use 'variables' as *;@use 'mixins' as *;
.card { background: $color-surface; border: 1px solid $color-border; border-radius: $border-radius-lg; padding: $spacing-lg; transition: $transition;
// Encabezado de la tarjeta &__header { @include flex-between; margin-bottom: $spacing-sm; }
// Icono del proyecto &__icon { @include flex-center; width: 3rem; height: 3rem; background: rgba($color-primary, 0.1); border-radius: $border-radius; font-size: 1.5rem; }
// Badge de estado &__badge { font-size: 0.75rem; font-family: $font-mono; padding: 0.25rem 0.75rem; border-radius: 100px; background: rgba($color-primary, 0.15); color: $color-primary;
&--wip { background: rgba(#f59e0b, 0.15); color: #f59e0b; }
&--archived { background: rgba($color-muted, 0.15); color: $color-muted; } }
// Título de la tarjeta &__title { font-size: 1.25rem; font-weight: 700; color: $color-text; margin-bottom: 0.5rem; @include text-truncate(2); }
// Descripción &__description { color: $color-muted; font-size: 0.9rem; line-height: 1.6; @include text-truncate(3); }
// Tecnologías usadas &__tags { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-top: $spacing-sm; }
&__tag { font-size: 0.75rem; font-family: $font-mono; padding: 0.2rem 0.6rem; background: rgba(255, 255, 255, 0.05); border-radius: 4px; color: $color-muted; }
// Footer de la tarjeta &__footer { @include flex-between; margin-top: $spacing-md; padding-top: $spacing-sm; border-top: 1px solid $color-border; }
// Hover: la magia visual &:hover { border-color: rgba($color-primary, 0.3); transform: translateY(-2px); box-shadow: 0 8px 32px rgba($color-primary, 0.08);
.card__title { color: $color-primary; }
.card__icon { background: rgba($color-primary, 0.2); } }
// Modificador: tarjeta destacada &--featured { border-color: rgba($color-primary, 0.4); background: linear-gradient( 135deg, rgba($color-primary, 0.05) 0%, $color-surface 100% ); }
// Estilos responsive @include responsive(tablet) { padding: $spacing-xl $spacing-lg; }}
// Grid de tarjetas.cards-grid { display: grid; grid-template-columns: 1fr; gap: $spacing-md;
@include responsive(tablet) { grid-template-columns: repeat(2, 1fr); }
@include responsive(desktop) { grid-template-columns: repeat(3, 1fr); }}// ============================================================// style.scss - archivo principal// ============================================================@use 'variables' as *;@use 'mixins' as *;@use 'reset';@use 'cards';// @use 'buttons';// @use 'header';// etc.
body { font-family: $font-main; background: $color-bg; color: $color-text; line-height: 1.6; min-height: 100vh;}
.container { width: min(1200px, 100% - 2rem); margin-inline: auto;}Y en el HTML lo usarías así:
<div class="cards-grid"> <article class="card card--featured"> <div class="card__header"> <div class="card__icon">🚀</div> <span class="card__badge">Activo</span> </div> <h2 class="card__title">Mi Portfolio</h2> <p class="card__description"> Portfolio personal construido con Astro y desplegado en Vercel. </p> <div class="card__tags"> <span class="card__tag">Astro</span> <span class="card__tag">SCSS</span> <span class="card__tag">TypeScript</span> </div> </article>
<article class="card"> <div class="card__header"> <div class="card__icon">⚡</div> <span class="card__badge card__badge--wip">En progreso</span> </div> <h2 class="card__title">App de Tareas</h2> <p class="card__description"> Aplicación de gestión de tareas con React y Firebase. </p> <div class="card__tags"> <span class="card__tag">React</span> <span class="card__tag">Firebase</span> </div> </article></div>Toma el CSS del proyecto final del capítulo 8 y refactorízalo usando SCSS. Sigue estos pasos:
-
Crea la estructura de archivos: organiza tu proyecto con una carpeta
scss/y una carpetacss/para el output. -
Extrae las variables: identifica todos los colores, tamaños de fuente, espaciados y radios de borde que se repiten. Ponlos en un archivo
_variables.scss. -
Anida los selectores: busca grupos de selectores que compartan un prefijo (como
.card .titulo,.card .descripcion) y anidalos en SCSS. -
Crea partials: divide el CSS por secciones (header, hero, cards, footer) y pon cada sección en su propio archivo
_nombre.scss. -
Crea un mixin de breakpoints: sustituye tus
@mediarepetidos por un mixin@include responsive(tablet)y@include responsive(desktop). -
Compila y verifica: configura
sass --watch scss/:css/y comprueba que el resultado visual es idéntico al original.
Bonus: Si tienes botones con variantes de color, refactorízalos usando un %btn-base con @extend.
Resumen
Sección titulada «Resumen»En este capítulo has aprendido a escribir CSS como un profesional con SCSS:
- SCSS es un preprocesador: escribes
.scss, se compila a.cssque el navegador entiende. - Variables (
$): define colores, tamaños y fuentes una vez, usa en todas partes. Cambia en un lugar, cambia en todo. - Anidamiento: escribe selectores hijos dentro del padre, igual que tu HTML. Usa
¶ pseudo-clases, pseudo-elementos y BEM. Máximo 3 niveles. - Partials (
_archivo.scss): divide tu CSS en archivos pequeños y organizados. Usa@use(no@import) para importarlos. - Mixins (
@mixin/@include): bloques de CSS reutilizables. Pueden recibir parámetros y envolver contenido con@content. - Extend (
@extend/%): herencia entre selectores. Ideal para variantes de componentes. No uses dentro de media queries. - Funciones de color:
darken(),lighten(),rgba(),mix()para manipular colores programáticamente.
El código que genera SCSS es exactamente el mismo CSS que escribirías a mano, solo que el proceso de escribirlo es mucho más rápido, organizado y mantenible.
Recursos
Sección titulada «Recursos»- Documentacion oficial de Sass — la referencia completa de todas las funciones y características
- Sass Guidelines — guía de buenas practicas para proyectos SCSS (disponible en español)