kb.erickguedes.com
CSS3: Estilização e Layout Moderno

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.