Variáveis CSS e Design System
Aula 7 de 7
Variáveis CSS (Custom Properties)
Variáveis CSS permitem valores reutilizáveis e dinâmicos, com escopo e herança.
Declaração e Uso
:root {
/* Cores */
--color-primary: #3498db;
--color-primary-hover: #2980b9;
--color-secondary: #2ecc71;
--color-danger: #e74c3c;
--color-bg: #ffffff;
--color-text: #2c3e50;
--color-text-light: #7f8c8d;
/* Tipografia */
--font-sans: 'Inter', system-ui, -apple-system, sans-serif;
--font-mono: 'JetBrains Mono', 'Fira Code', monospace;
--font-size-xs: 0.75rem;
--font-size-sm: 0.875rem;
--font-size-base: 1rem;
--font-size-lg: 1.125rem;
--font-size-xl: 1.5rem;
--font-size-2xl: 2rem;
--font-size-3xl: 3rem;
/* Espaçamento */
--space-1: 0.25rem;
--space-2: 0.5rem;
--space-3: 0.75rem;
--space-4: 1rem;
--space-6: 1.5rem;
--space-8: 2rem;
--space-12: 3rem;
--space-16: 4rem;
/* Border */
--radius-sm: 4px;
--radius-md: 8px;
--radius-lg: 12px;
--radius-xl: 16px;
--radius-full: 9999px;
/* Sombra */
--shadow-sm: 0 1px 3px rgba(0,0,0,0.1);
--shadow-md: 0 4px 12px rgba(0,0,0,0.1);
--shadow-lg: 0 8px 30px rgba(0,0,0,0.12);
}
body {
font-family: var(--font-sans);
color: var(--color-text);
background: var(--color-bg);
}
Fallback e Dinamismo
/* Fallback */
.card {
background: var(--color-primary, #3498db);
padding: var(--space-6, 24px);
}
/* Variável com fallback encadeado */
.card-title {
color: var(--color-card-title, var(--color-text, #333));
}
/* Mudança dinâmica com JS */
const root = document.documentElement;
root.style.setProperty('--color-primary', '#e74c3c');
root.style.setProperty('--color-bg', '#1a1a2e');
// Ler variável
const primary = getComputedStyle(root).getPropertyValue('--color-primary');
Escopo Contextual
/* Escopo em componentes */
.alert {
--alert-bg: #f8d7da;
--alert-border: #f5c6cb;
--alert-text: #721c24;
background: var(--alert-bg);
border: 1px solid var(--alert-border);
color: var(--alert-text);
}
.alert-success {
--alert-bg: #d4edda;
--alert-border: #c3e6cb;
--alert-text: #155724;
}
Design Tokens
:root {
/* Core Tokens */
--token-color-brand: #3498db;
--token-color-neutral-100: #f8f9fa;
--token-color-neutral-900: #212529;
--token-font-heading: 'Inter', sans-serif;
--token-font-body: 'Inter', sans-serif;
--token-size-4: 4px;
--token-size-8: 8px;
--token-size-16: 16px;
/* Semantic Tokens (mapeiam core tokens para contextos) */
--color-surface: var(--token-color-neutral-100);
--color-text-primary: var(--token-color-neutral-900);
--color-action-primary: var(--token-color-brand);
}
BEM Metodologia
/* Block__Element--Modifier */
.card {
/* Block */
}
.card__title {
/* Element */
}
.card__image {
/* Element */
}
.card--featured {
/* Modifier */
}
.card--dark {
/* Modifier */
}
<div class="card card--featured">
<img class="card__image" src="foto.jpg" alt="">
<h2 class="card__title">Título do Card</h2>
<p class="card__description">Descrição do card em destaque.</p>
</div>
CSS Layers
/* Controlar a ordem da cascata com @layer */
@layer reset, base, components, utilities;
@layer reset {
* { margin: 0; padding: 0; box-sizing: border-box; }
}
@layer base {
body {
font-family: var(--font-sans);
line-height: 1.6;
}
}
@layer components {
.card {
padding: var(--space-6);
border-radius: var(--radius-md);
background: white;
}
}
@layer utilities {
.text-center { text-align: center; }
.mt-4 { margin-top: var(--space-4); }
}
/* Dentro de @layer, a especificidade normal se aplica */
/* Mas layers posteriores sempre vencem layers anteriores */
CSS Futuro (Já Suportado)
/* CSS Nesting (nativo, sem pré-processador) */
.card {
background: white;
& .title {
font-size: 1.5rem;
}
&:hover {
box-shadow: 0 4px 12px rgba(0,0,0,0.1);
}
@media (width >= 768px) {
padding: 2rem;
}
}
/* :has() - suporte amplo */
.form:has(:invalid) .submit-btn {
opacity: 0.5;
pointer-events: none;
}
/* scroll-timeline (experimental) */
@keyframes fade-in {
from { opacity: 0; }
to { opacity: 1; }
}
.element {
animation: fade-in linear;
animation-timeline: view();
}
Lab: Design System Minimalista
Crie uma página com variáveis CSS, tokens de design e BEM. Implemente temas claro/escuro com prefers-color-scheme.
# Verifique suporte a @layer e :has()
# https://caniuse.com/
Um design system não é um framework — é uma linguagem compartilhada entre design e desenvolvimento. Comece com tokens, evolua para componentes.