CSS/SASS Style Guide
Guia completo de estilos, arquitetura e boas práticas para desenvolvimento CSS/Sass no projeto.
Versão: 2.0
Última atualização: 04/2026
Metodologia: ITCSS + BEM + Utility-First
📋 Índice
- Princípios do CSS no Projeto
- Arquitetura e Estrutura
- Design Tokens
- Mixins e Utilitários
- Breakpoints e Responsividade
- Grid System e Utilities
- Componentes (BEM)
- Tipografia
- Animações e Transições
- Performance
- Acessibilidade
- Checklist para Pull Requests
Princípios do CSS no Projeto
Nossos princípios orientam todas as decisões de estilização:
| Princípio | Descrição |
|---|---|
| Mobile-First | Estilos base para mobile, progressão via media queries |
| DRY | Não se repita — use mixins, variáveis e utilities |
| Semântica | Nomes de classes descrevem função, não aparência |
| Composição | Components pequenos e reutilizáveis > CSS monolítico |
| Acessibilidade | CSS inclusivo por padrão (focus, reduced-motion, etc.) |
| Performance | Animações GPU-accelerated, mínimo de repaints |
Camadas ITCSS
O projeto segue ITCSS (Inverted Triangle CSS), organizando estilos do genérico ao específico:
┌─────────────────────────────────────┐
│ 1. Abstracts (Configurações) │ → Variáveis, mixins, breakpoints
│ └─ Não gera CSS direto │
├─────────────────────────────────────┤
│ 2. Core (Fundação) │ → Reset, tipografia, grid, utilities
│ └─ Estilos globais de baixo nível│
├─────────────────────────────────────┤
│ 3. Components (Interface) │ → Componentes específicos (BEM)
│ └─ Estilos scoped por componente │
└─────────────────────────────────────┘
Arquitetura e Estrutura
Estrutura de Diretórios
src/styles/
├── global.sass # Arquivo principal de entrada
├── abstract/ # Configurações e ferramentas (não gera CSS)
│ ├── index.sass # Barrel file (@forward)
│ ├── _tokens.sass # Design tokens (cores, spacing, etc.)
│ ├── _mixins.sass # Mixins e funções utilitárias
│ └── _breakpoints.sass # Definição de breakpoints e mixins
├── core/ # Estilos base e fundação
│ ├── _reset.sass # Normalize/reset de browser
│ ├── _general.sass # Estilos globais do body/html
│ ├── _typography.sass # Sistema tipográfico completo
│ └── _grid.sass # Grid system e utility classes
└── components/ # Componentes de interface (BEM)
├── index.sass # Barrel file de componentes
├── _buttons.sass # Botões e variações
├── _content.sass # Conteúdo de artigos
└── _post-content.sass # Conteúdo específico de posts
Arquivo Principal (global.sass)
// global.sass
// 1. Configurações (Não gera CSS — apenas disponibiliza variáveis/mixins)
@use 'abstract' as *
// 2. Fundação (Camadas baixas do ITCSS)
@use 'core/reset'
@use 'core/general'
@use 'core/typography'
@use 'core/grid'
// 3. Interface (Componentes específicos)
@use 'components'
Convenções de Nomenclatura de Arquivos
| Tipo | Prefixo | Exemplo | Propósito |
|---|---|---|---|
| Partial | _ | _tokens.sass | Arquivo importado, não compilado isoladamente |
| Barrel | index | index.sass | Agrega e exporta múltiplos partials com @forward |
| Componente | _ | _buttons.sass | Stylescope de um componente específico |
Design Tokens
Design tokens são as unidades atômicas do sistema de design. Definidos em abstract/_tokens.sass.
Cores
Paleta Neutra (Cores Puras)
// abstract/_tokens.sass
$neutral-900: hsl(180, 4%, 4.9%) // Preto base
$neutral-800: hsl(216, 4.3%, 22.9%) // Grafite
$neutral-500: hsl(218.2, 4.3%, 50%) // Cinza médio
$neutral-300: hsl(214.3, 4.3%, 68%) // Cinza claro
$neutral-100: hsl(220, 4.2%, 86.1%) // Quase branco
$neutral-000: hsl(0, 0%, 100%) // Branco puro
Tokens Semânticos (Use estes!)
// abstract/_tokens.sass
// Text colors
$text-primary: $neutral-300 // pale-slate - Texto principal
$text-secondary: $neutral-100 // alabaster-grey - Texto de destaque/títulos
$text-inverse: $neutral-900 // black - Texto em fundo claro
$text-muted: $neutral-500 // dim-grey - Texto secundário/desativado
$text-white: $neutral-000 // white - Texto branco explícito
// Background colors
$bg-primary: $neutral-900 // black - Fundo principal da página
$bg-secondary: $neutral-800 // graphite - Fundo de cards/seções
$bg-tertiary: $neutral-500 // dim-grey - Fundo terciário
$bg-light: $neutral-100 // alabaster-grey - Fundo claro
$bg-white: $neutral-000 // white - Fundo branco
// UI Elements
$ui-border: $neutral-500 // dim-grey - Bordas
$ui-divider: $neutral-300 // pale-slate - Linhas divisórias
$ui-surface: $neutral-000 // white - Superfícies/cards
$ui-card-bg: $neutral-800 // graphite - Background de cards
// Status colors
$status-success: hsl(127.4, 55.3%, 42.9%)
$status-warning: hsl(46, 90.7%, 53.5%)
$status-error: hsl(351.9, 100%, 69.4%)
$status-info: hsl(186, 67.1%, 46.5%)
$status-success-light: hsl(71.5, 88.7%, 89.6%)
$status-warning-light: hsl(52, 95.7%, 90.8%)
$status-error-light: hsl(15, 100%, 93.7%)
$status-info-light: hsl(101.7, 93.7%, 87.6%)
Como Usar Cores
@use '../abstract' as *
// ✅ CORRETO: Use a função color() com tokens semânticos
.card
background-color: color('bg-secondary')
color: color('text-primary')
border: 1px solid color('ui-border')
// ❌ ERRADO: Evite usar variáveis diretas de cor
.card
background-color: $neutral-800 // Não faz isso
color: $neutral-300 // Perde semântica
Status Colors
$status-success: hsl(145, 63%, 42%) // Verde
$status-warning: hsl(38, 92%, 50%) // Amarelo/Laranja
$status-error: hsl(0, 84%, 60%) // Vermelho
$status-info: hsl(200, 100%, 50%) // Azul
Spacing (Base 8px)
Sistema de espaçamento baseado em rem, com escala consistente.
// abstract/_tokens.sass
$spacing: (
'none': 0,
'xs': 0.5rem, // 8px
'sm': 1rem, // 16px
'md': 1.5rem, // 24px
'lg': 2.5rem, // 40px
'xl': 3rem, // 48px
'2xl': 4rem, // 64px
'3xl': 6rem, // 96px
)
// Variáveis individuais para acesso direto
$spacing-none: map.get($spacing, 'none')
$spacing-xs: map.get($spacing, 'xs')
$spacing-sm: map.get($spacing, 'sm')
$spacing-md: map.get($spacing, 'md')
$spacing-lg: map.get($spacing, 'lg')
$spacing-xl: map.get($spacing, 'xl')
$spacing-2xl: map.get($spacing, '2xl')
$spacing-3xl: map.get($spacing, '3xl')
Como usar:
@use '../abstract' as *
.card
padding: spacing('md')
margin-bottom: spacing('lg')
@include up('md')
padding: spacing('lg')
Border Radius
$radii: (
'none': 0,
'sm': 0.25rem, // 4px
'md': 0.375rem, // 6px
'lg': 0.5rem, // 8px
'xl': 0.75rem, // 12px
'2xl': 1rem, // 16px
'full': 9999px, // Circular
)
Como usar:
@use '../abstract' as *
.button
border-radius: radius('md')
.avatar
border-radius: radius('full')
.card--rounded
border-radius: radius('xl')
Shadows (Sistema de Elevação)
// abstract/_tokens.sass
$shadows: (
'sm': (0 1px 2px 0 hsla(180, 11%, 2%, 0.05)),
'md': (0 4px 6px -1px hsla(180, 11%, 2%, 0.1), 0 2px 4px -1px hsla(180, 11%, 2%, 0.06)),
'lg': (0 10px 15px -3px hsla(180, 11%, 2%, 0.1), 0 4px 6px -2px hsla(180, 11%, 2%, 0.05)),
'xl': (0 20px 25px -5px hsla(180, 11%, 2%, 0.1), 0 10px 10px -5px hsla(180, 11%, 2%, 0.04)),
)
// Variáveis individuais
$shadow-sm: map.get($shadows, 'sm')
$shadow-md: map.get($shadows, 'md')
$shadow-lg: map.get($shadows, 'lg')
$shadow-xl: map.get($shadows, 'xl')
Como usar:
@use '../abstract' as *
.card
@include shadow('lg')
&:hover
@include shadow('xl')
Text Shadows (Elevação Tipográfica)
// abstract/_tokens.sass
$text-shadows: (
'sm': 0 1px 2px hsla(180, 11%, 2%, 0.2),
'md': 0 2px 4px hsla(180, 11%, 2%, 0.3),
'lg': 0 4px 8px hsla(180, 11%, 2%, 0.4),
'xl': 0 6px 12px hsla(180, 11%, 2%, 0.5),
'glow': 0 0 10px hsla(0, 0%, 100%, 0.25),
'inverse': 0 1px 3px rgba(255, 255, 255, 0.35)
)
// Uso com mixin
.glowing-text
@include text-shadow('glow')
Z-Index Scale
$z-index: (
'negative': -1,
'base': 0,
'elevation-1': 10,
'elevation-2': 20,
'elevation-3': 30,
'dropdown': 1000,
'sticky': 1020,
'fixed': 1030,
'modal-backdrop': 1040,
'modal': 1050,
'popover': 1060,
'tooltip': 1070,
)
Como usar:
@use '../abstract' as *
.modal
z-index: z('modal')
.dropdown
z-index: z('dropdown')
Gradientes
// abstract/_tokens.sass
$gradient-nav: linear-gradient(to right, rgba(0,0,0,0.95) 0%, rgba(0,0,0,0.65) 90%, rgba(0,0,0,0) 100%)
$gradient-hero: linear-gradient(to top, $bg-primary 0%, transparent 70%)
$gradient-card: linear-gradient(to top, rgba(0,0,0,0.5) 0%, rgba(0,0,0,0.8) 100%)
$gradient-dark-diagonal: linear-gradient(135deg, $bg-primary, $bg-secondary, $bg-tertiary)
// Mixin para gradiente do hero
@mixin gradient-hero($direction: to top, $start-color: $bg-primary, $transparent-at: 70%)
background: linear-gradient($direction, $start-color 0%, transparent $transparent-at)
Tipografia
// abstract/_tokens.sass
// Fontes
$font-primary: 'Azeret Mono', monospace
$font-heading: 'Belgant', sans-serif
$font-primary-fallback: 'Courier New', Courier, monospace
$font-heading-fallback: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif
// Pesos disponíveis
$font-weights: (
'light': 300,
'regular': 400,
'medium': 500,
'semibold': 600,
'bold': 700,
'extrabold': 800,
'black': 900,
)
// Variáveis individuais
$font-light: map.get($font-weights, 'light')
$font-regular: map.get($font-weights, 'regular')
$font-medium: map.get($font-weights, 'medium')
$font-semibold: map.get($font-weights, 'semibold')
$font-bold: map.get($font-weights, 'bold')
$font-extrabold: map.get($font-weights, 'extrabold')
$font-black: map.get($font-weights, 'black')
Transições
$transition-durations: (
'fast': 150ms,
'base': 300ms,
'slow': 500ms,
'ultra-slow': 700ms,
)
$easings: (
'linear': linear,
'ease': ease,
'ease-in': ease-in,
'ease-out': ease-out,
'ease-in-out': ease-in-out,
'smooth': cubic-bezier(0.4, 0, 0.2, 1),
'gentle': cubic-bezier(0.25, 0.1, 0.25, 1),
'snappy': cubic-bezier(0.2, 0, 0, 1),
'slide-up': cubic-bezier(0.16, 1, 0.3, 1),
)
Mixins e Utilitários
Layout Mixins
@use '../abstract' as *
// Flexbox layouts
@include flex-between // justify-content: space-between; align-items: center;
@include flex-center // justify-content: center; align-items: center;
@include flex-column // flex-direction: column;
@include flex-row // flex-direction: row;
@include grid-layout // display: grid;
Exemplo:
.nav
@include flex-between
.hero
@include flex-column
@include flex-center
Acessibilidade
@use '../abstract' as *
// Esconder visualmente mas manter acessível para screen readers
.sr-only
@include visually-hidden
// Focus visible customizado
.button
@include focus-visible($offset: 2px, $color: color('text-primary'))
Tipografia
@use '../abstract' as *
// Fonte responsiva fluida (usa clamp())
.heading
@include responsive-font($min-size: 1.5rem, $max-size: 3rem)
// Truncar texto com ellipsis
.card__title
@include text-truncate
// Text balance para títulos (evita viúvas)
h1, h2, h3
@include text-balance
// Text shadow
.glowing-text
@include text-shadow($level: glow) // sm, md, lg, xl, glow, inverse
Interação e Animação
@use '../abstract' as *
// Respeitar preferência por movimento reduzido
.animated-element
@include prefers-reduced-motion
transition: none
animation: none
// Fade in
.fade-in
@include fade-in($duration: base, $easing: ease-out)
&.is-visible
opacity: 1
// Slide up
.slide-up
@include slide-up($distance: 2rem, $duration: base, $easing: slide-up)
&.is-visible
opacity: 1
transform: translateY(0)
// Scale in
.scale-in
@include scale-in($scale: 0.95, $duration: base)
// Hover lift (efeito de elevação no hover)
.card
@include hover-lift($distance: 4px, $duration: fast)
// Transição suave de cor
.button
@include transition-color($duration: fast)
Efeitos Visuais
@use '../abstract' as *
.card
@include shadow('lg')
@include radius('md')
@include gradient('hero')
Mídia e Assets
@use '../abstract' as *
// Imagem cover (object-fit)
.hero__image
@include cover-image
// Aspect ratio
.video-container
@include aspect-ratio(16, 9)
Funções Helper
@use '../abstract' as *
.element
margin: spacing('md') // Retorna valor do mapa de spacing
border-radius: radius('lg') // Retorna valor do mapa de radii
box-shadow: shadow('xl') // Retorna valor do mapa de shadows
z-index: z('modal') // Retorna valor do mapa de z-index
color: color('text-primary') // Retorna valor do mapa de colors
Breakpoints e Responsividade
Mapa de Breakpoints (Mobile-First)
$breakpoints: (
'xs': 0, // Mobile Portrait (BASE)
'sm': 576px, // Smartphones Landscape / Phablets
'md': 768px, // Tablets Portrait (iPad)
'lg': 992px, // Tablets Landscape / Laptops pequenos
'xl': 1200px, // Desktops Padrão (Full HD)
'xxl': 1440px, // Monitores Grandes / Hi-Res
)
Mixins de Media Query
@use '../abstract' as *
// ✅ RECOMENDADO: Mínimo (Mobile First)
.component
// Mobile styles (base)
padding: spacing('sm')
@include up('md')
// Tablet styles
padding: spacing('md')
@include up('lg')
// Desktop styles
padding: spacing('lg')
// Máximo (Legado / Casos específicos)
.legacy-component
@include down('sm')
// Apenas para telas menores que sm
// Entre dois breakpoints
.responsive-element
@include between('md', 'lg')
// Estilos aplicados apenas entre md e lg
Aliases de Conveniência
@use '../abstract' as *
.component
@include mobile // Equivalente a @include down('md')
// Estilos apenas para mobile
@include tablet // Equivalente a @include between('md', 'lg')
// Estilos apenas para tablet
@include desktop // Equivalente a @include up('lg')
// Estilos para desktop e acima
Boas Práticas de Responsividade
@use '../abstract' as *
// ✅ CORRETO: Progressão mobile-first
.card
// Base (mobile)
padding: spacing('sm')
font-size: var(--font-size-sm)
@include up('md')
padding: spacing('md')
font-size: var(--font-size-base)
@include up('lg')
padding: spacing('lg')
font-size: var(--font-size-md)
// ❌ ERRADO: Desktop-first com override para mobile
.card
@include down('sm')
padding: spacing('sm') // Override desnecessário
// Desktop styles na base
padding: spacing('lg')
Grid System e Utilities
Container
.container
width: 100%
max-width: 1400px
margin-inline: auto
padding-inline: spacing('lg')
// Container fluido (100% width)
.container--fluid
Grid
// Grid base
.grid
display: grid
gap: spacing('md')
// Grid auto-fit responsivo automático
.grid-auto-fit
display: grid
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr))
gap: spacing('md')
Exemplo HTML:
<div class="grid-auto-fit">
<!-- Colunas criadas automaticamente com minmax(250px, 1fr) -->
</div>
Colunas (1-12)
.cols-1 through .cols-12 // Define número de colunas do grid
.span-1 through .span-12 // Span de colunas
.row-span-1 through .row-span-12
Exemplo HTML:
<div class="grid md:cols-12">
<div class="md:span-8">Ocupa 8 colunas</div>
<div class="md:span-4">Ocupa 4 colunas</div>
</div>
Gap Utilities
.gap-none, .gap-sm, .gap-md, .gap-lg, .gap-xl, .gap-2xl
Display Utilities
.flex, .inline-flex
.block, .inline-block
.grid-display
.hidden
Flex Utilities
// Direction
.flex-row, .flex-col
// Wrap
.flex-wrap, .flex-nowrap
// Align Items
.items-start, .items-center, .items-end, .items-stretch, .items-baseline
// Justify Content
.justify-start, .justify-center, .justify-end, .justify-between, .justify-around, .justify-evenly
// Align Self
.self-start, .self-center, .self-end, .self-stretch, .self-baseline
// Grow/Shrink
.flex-1, .flex-auto, .flex-none
Spacing Utilities (Logical Properties)
// Margins
.m-xs, .m-sm, .m-md, .m-lg, .m-xl, .m-2xl, .m-3xl
.mt-{size}, .mb-{size}, .ms-{size}, .me-{size}
.mx-{size}, .my-{size}
// Paddings
.p-xs, .p-sm, .p-md, .p-lg, .p-xl, .p-2xl, .p-3xl
.pt-{size}, .pb-{size}, .ps-{size}, .pe-{size}
.px-{size}, .py-{size}
// Auto margins
.mx-auto, .my-auto, .mt-auto, .mb-auto, .ms-auto, .me-auto, .m-auto
Responsive Utilities
Sintaxe: {breakpoint}\:{classe}
md:flex, lg:cols-4, xl:gap-lg
Exemplo HTML:
<div class="grid cols-1 md:cols-2 lg:cols-4 gap-md">
<div class="span-6 lg:span-4">Conteúdo</div>
</div>
Componentes BEM
Nomenclatura BEM
Block__Element--Modifier
- Block: Componente principal (
.nav) - Element: Parte do bloco (
.nav__link) - Modifier: Variação do bloco/elemento (
.btn--primary)
Exemplo: Botões
// Base
.btn
display: inline-block
padding: spacing('sm') spacing('lg')
border-radius: radius('md')
@include transition-color(fast)
@include hover-lift(2px, fast)
// Modifiers
.btn--primary
background: color('bg-primary')
color: color('text-inverse')
.btn--secondary
background: color('bg-tertiary')
color: color('text-inverse')
.btn--uppercase
text-transform: uppercase
Uso:
<button class="btn btn--primary">Primário</button>
<button class="btn btn--secondary btn--uppercase">Secundário</button>
Exemplo: Navegação
.nav
// Base styles
&__menu
// Menu container
&__logo
// Logo area
&__links
// Lista de links
&__link
// Link individual
&--with-children
// Link com submenu
&.is-active
// Link ativo
&__sublinks
// Submenu
&.is-expanded
// Submenu expandido
&__social
// Redes sociais
Exemplo: Post Card
.post-card
display: flex
flex-direction: column
background-image: $gradient-card, var(--card-bg-image)
border-radius: radius('md')
box-shadow: shadow('xl')
&:hover
transform: scale(1.02)
&__content
display: contents
&__title
font-family: $font-heading
font-size: var(--font-size-h5)
&__summary
font-size: var(--font-size-xs)
Tipografia
CSS Custom Properties (Fluid Typography)
:root {
--font-size-base: clamp(0.875rem, 2vw, 1.125rem);
--font-size-h1: clamp(2rem, 6vw, 3.75rem);
--font-size-h2: clamp(1.5rem, 5vw, 2.5rem);
--line-height-tight: 1.2;
--line-height-normal: 1.5;
--line-height-relaxed: 1.75;
}
Headings
h1, h2, h3, h4, h5, h6
font-family: $font-heading, $font-heading-fallback
font-weight: $font-bold
line-height: var(--line-height-tight)
color: color('text-secondary')
@include text-balance
Utilities Tipográficas
// Font sizes
.text-xs, .text-sm, .text-base, .text-lg, .text-xl
.text-2xl, .text-3xl, .text-4xl, .text-5xl, .text-6xl
// Font weights
.font-light, .font-regular, .font-medium
.font-semibold, .font-bold, .font-extrabold
// Text alignment
.text-left, .text-center, .text-right, .text-justify
// Text transform
.uppercase, .lowercase, .capitalize, .normal-case
// Line height
.leading-tight, .leading-normal, .leading-relaxed, .leading-loose
// Letter spacing
.tracking-tight, .tracking-normal, .tracking-wide, .tracking-wider
// Semantic colors
.text-primary, .text-secondary, .text-white, .text-dark
// Utilities
.truncate, .break-words, .break-all
Boas Práticas
1. Use @use em vez de @import
// ✅ Correto
@use '../abstract' as *
@use 'sass:map'
@use 'sass:color'
// ❌ Evitar
@import '../abstract/tokens'
2. Prefira Variáveis Semânticas
// ✅ Correto
background-color: color('bg-primary')
color: color('text-primary')
// ❌ Evitar
background-color: $color-black
color: $color-pale-slate
3. Mobile-First Sempre
// ✅ Correto
.component
// Mobile styles (base)
padding: spacing('sm')
@include up('md')
// Tablet styles
padding: spacing('md')
// ❌ Evitar
.component
@include down('sm')
// Mobile override
4. Use Utilities para Layout
<!-- ✅ Preferível -->
<div class="flex items-center justify-between gap-md p-lg">
<!-- ❌ Evitar criar classes novas para layouts simples -->
<div class="my-custom-flex-container"></div>
</div>
5. Nomenclatura BEM Consistente
// ✅ Correto
.card
&__header
&--featured
// ❌ Evitar
.card-header-featured
.cardHeaderFeatured
6. Acessibilidade
- Use
@include visually-hiddenpara conteúdo apenas para screen readers - Sempre inclua estados
:focus-visible - Respeite
prefers-reduced-motion
.button
&:focus-visible
outline: 2px solid color('text-primary')
outline-offset: 2px
@include prefers-reduced-motion
transition: none
7. Performance
- Use
transformeopacitypara animações (GPU-accelerated) - Evite animações de propriedades como
width,height,top,left - Use
will-changecom moderação
// ✅ Performático
.card
transition: transform $transition-base, opacity $transition-base
// ❌ Evitar
.card
transition: width $transition-base, height $transition-base
Grid System e Utilities
O sistema de grid e utilities está definido em core/_grid.sass.
Container
// Container centralizado com largura máxima
.container
width: 100%
max-width: 1400px
margin-inline: auto
padding-inline: spacing('lg')
// Container fluido (100% width)
.container--fluid
max-width: 100%
Grid Base
// Grid container base
.grid
display: grid
gap: spacing('md')
// Grid auto-fit responsivo automático
.grid-auto-fit
display: grid
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr))
gap: spacing('md')
Colunas (1-12)
// Classes de colunas do grid
.cols-1 through .cols-12 // Define número de colunas do grid
.span-1 through .span-12 // Span de colunas
.row-span-1 through .row-span-12
Exemplo:
<div class="grid cols-1 md:cols-2 lg:cols-4 gap-md">
<div class="span-6 lg:span-4">Conteúdo</div>
</div>
Gap Utilities
.gap-none, .gap-sm, .gap-md, .gap-lg, .gap-xl, .gap-2xl
Display Utilities
.flex, .inline-flex
.block, .inline-block
.grid-display
.hidden
Flex Utilities
// Direction
.flex-row, .flex-col
// Wrap
.flex-wrap, .flex-nowrap
// Align Items
.items-start, .items-center, .items-end, .items-stretch, .items-baseline
// Justify Content
.justify-start, .justify-center, .justify-end, .justify-between, .justify-around, .justify-evenly
// Align Self
.self-start, .self-center, .self-end, .self-stretch, .self-baseline
// Grow/Shrink
.flex-1, .flex-auto, .flex-none
Spacing Utilities (Logical Properties)
Usando propriedades lógicas para melhor suporte a internacionalização:
// Margins
.m-xs, .m-sm, .m-md, .m-lg, .m-xl, .m-2xl, .m-3xl
.mt-{size}, .mb-{size}, .ms-{size}, .me-{size}
.mx-{size}, .my-{size}
// Paddings
.p-xs, .p-sm, .p-md, .p-lg, .p-xl, .p-2xl, .p-3xl
.pt-{size}, .pb-{size}, .ps-{size}, .pe-{size}
.px-{size}, .py-{size}
// Auto margins
.mx-auto, .my-auto, .mt-auto, .mb-auto, .ms-auto, .me-auto, .m-auto
Responsive Utilities
Sintaxe: {breakpoint}\:{classe}
md:flex, lg:cols-4, xl:gap-lg
Exemplo HTML:
<div class="grid cols-1 md:cols-2 lg:cols-4 gap-md">
<div class="span-6 lg:span-4">Conteúdo</div>
</div>
Componentes (BEM)
Nomenclatura BEM
Block__Element--Modifier
| Parte | Descrição | Exemplo |
|---|---|---|
| Block | Componente principal independente | .nav, .card, .btn |
| Element | Parte interna do bloco | .nav__link, .card__title |
| Modifier | Variação/estado do bloco ou elemento | .btn--primary, .nav__link.is-active |
Exemplo: Botões
@use '../abstract' as *
// Block base
.btn
display: inline-block
padding: spacing('sm') spacing('lg')
border-radius: radius('md')
@include transition-color(fast)
@include hover-lift(2px, fast)
// Modifiers de variante
.btn--primary
background: color('bg-primary')
color: color('text-inverse')
.btn--secondary
background: color('bg-tertiary')
color: color('text-inverse')
// Modifier de estilo
.btn--uppercase
text-transform: uppercase
Uso no HTML:
<button class="btn btn--primary">Primário</button>
<button class="btn btn--secondary btn--uppercase">Secundário</button>
Exemplo: Navegação
@use '../abstract' as *
.nav
@include flex-between
&__menu
// Menu container
&__logo
// Logo area
&__links
// Lista de links
@include flex-row
&__link
// Link individual
@include transition-color(fast)
&--with-children
// Link com submenu
&.is-active
// Link ativo (estado)
&__sublinks
// Submenu
&.is-expanded
// Submenu expandido (estado)
&__social
// Redes sociais
Exemplo: Post Card
@use '../abstract' as *
.post-card
display: flex
flex-direction: column
background-image: $gradient-card, var(--card-bg-image)
border-radius: radius('md')
@include shadow('xl')
&:hover
transform: scale(1.02)
&__content
display: contents
&__title
font-family: $font-heading
font-size: var(--font-size-h5)
&__summary
font-size: var(--font-size-xs)
color: color('text-muted')
Estados vs Modifiers
// ✅ CORRETO: Modifier para variações estruturais
.btn--large
.btn--small
// ✅ CORRETO: Estado com prefixo is- para estados dinâmicos
.is-active
.is-expanded
.is-hidden
.is-loading
// ❌ ERRADO: Misturar estado com modifier
.btn--active // Não faça isso
.btn--is-loading // Não faça isso
Tipografia
CSS Custom Properties (Fluid Typography)
Definido em core/_typography.sass:
:root {
/* Font sizes - Fluid clamp system */
--font-size-base: clamp(0.875rem, 2vw, 1.125rem);
--font-size-h1: clamp(2rem, 6vw, 3.75rem);
--font-size-h2: clamp(1.5rem, 5vw, 2.5rem);
--font-size-h3: clamp(1.25rem, 4vw, 2rem);
--font-size-h4: clamp(1.125rem, 3vw, 1.75rem);
--font-size-h5: clamp(1rem, 2.5vw, 1.5rem);
--font-size-h6: clamp(0.875rem, 2vw, 1.25rem);
/* Line heights */
--line-height-tight: 1.2;
--line-height-normal: 1.5;
--line-height-relaxed: 1.75;
--line-height-loose: 2;
}
Headings
@use '../abstract' as *
h1, h2, h3, h4, h5, h6
font-family: $font-heading, $font-heading-fallback
font-weight: $font-bold
line-height: var(--line-height-tight)
color: color('text-secondary')
@include text-balance
Utilities Tipográficas
// Font families
.font-primary
font-family: $font-primary, $font-primary-fallback
.font-heading
font-family: $font-heading, $font-heading-fallback
// Font sizes
.text-xs, .text-sm, .text-base, .text-lg, .text-xl
.text-2xl, .text-3xl, .text-4xl, .text-5xl, .text-6xl
// Font weights
.font-light, .font-regular, .font-medium
.font-semibold, .font-bold, .font-extrabold
// Text alignment
.text-left, .text-center, .text-right, .text-justify
// Text transform
.uppercase, .lowercase, .capitalize, .normal-case
// Line height
.leading-tight, .leading-normal, .leading-relaxed, .leading-loose
// Letter spacing
.tracking-tight, .tracking-normal, .tracking-wide, .tracking-wider
// Semantic colors
.text-primary, .text-secondary, .text-white, .text-dark
// Utilities
.truncate, .break-words, .break-all
Animações e Transições
Quando Usar Animações
| Caso | Recomendação |
|---|---|
| Feedback de interação | ✅ Sim (hover, focus, click) |
| Transições de estado | ✅ Sim (expandir, colapsar) |
| Entrada de elementos | ✅ Sim (fade-in, slide-up) |
| Loading states | ✅ Sim (skeleton, spinner) |
| Decorativo puro | ⚠️ Com moderação |
| Movimento contínuo | ❌ Evite (causa náusea) |
Propriedades Performáticas
Use apenas estas propriedades para animações suaves (GPU-accelerated):
// ✅ PERFORMÁTICO (compositor-only)
.card
transition: transform 300ms ease-out, opacity 300ms ease-out
// ❌ EVITAR (causa layout/paint)
.card
transition: width 300ms, height 300ms, top 300ms, left 300ms
Padrões de Animação
@use '../abstract' as *
// Fade in genérico
.fade-in
opacity: 0
@include fade-in($duration: base, $easing: ease-out)
&.is-visible
opacity: 1
// Slide up (entrada de baixo para cima)
.slide-up
opacity: 0
@include slide-up($distance: 2rem, $duration: base)
&.is-visible
opacity: 1
transform: translateY(0)
// Scale in (zoom suave)
.scale-in
opacity: 0
@include scale-in($scale: 0.95, $duration: base)
&.is-visible
opacity: 1
transform: scale(1)
// Hover lift (elevação no hover)
.card
@include hover-lift($distance: 4px, $duration: fast)
Respeitando Preferências do Usuário
Sempre inclua suporte a prefers-reduced-motion:
@use '../abstract' as *
.animated-component
@include slide-up(2rem, base)
@include prefers-reduced-motion
transition: none
animation: none
opacity: 1
transform: none
Performance
Boas Práticas de Performance CSS
1. Use Transform e Opacity para Animações
// ✅ PERFORMÁTICO (GPU-accelerated)
.card
transition: transform 300ms ease-out, opacity 300ms ease-out
&:hover
transform: translateY(-4px)
opacity: 0.9
// ❌ LENTO (causa reflow/repaint)
.card
transition: margin 300ms, width 300ms
&:hover
margin-top: -4px
width: 105%
2. Evite Seletor Universal e Aninhamento Excessivo
// ❌ LENTO
* { box-sizing: border-box }
div ul li a span { color: red }
// ✅ RÁPIDO
.card__link { color: red }
3. Use will-change com Moderação
// ✅ Use apenas quando necessário
.hero-image
will-change: transform
// Remova após animação completar via JS
// ❌ Não use em tudo
* { will-change: transform } // Pior que não usar
4. Contain para Isolamento de Layout
// Isole componentes complexos
.post-grid
contain: layout style
5. Evite @import em CSS
// ✅ CORRETO (Sass modules)
@use 'abstract' as *
@use 'components/nav'
// ❌ ERRADO (CSS imports bloqueiam render)
@import url('https://fonts.googleapis.com/...');
Otimização de Assets
// Use imagens modernas com fallback
.picture
@include aspect-ratio(16, 9)
img
@include cover-image
// Prefira WebP/AVIF com fallback
Acessibilidade
Focus Visible
Sempre estilize estados de foco:
@use '../abstract' as *
.button
@include focus-visible($offset: 2px, $color: color('text-primary'))
a
&:focus-visible
outline: 2px solid color('text-primary')
outline-offset: 2px
Conteúdo Apenas para Screen Readers
@use '../abstract' as *
// Esconde visualmente mas mantém acessível
.sr-only
@include visually-hidden
// Uso:
<button>
<svg aria-hidden="true">...</svg>
<span class="sr-only">Abrir menu</span>
</button>
Reduced Motion
Respeite preferências de movimento reduzido:
@use '../abstract' as *
.animated-element
@include slide-up(2rem, base)
@include prefers-reduced-motion
transition: none
animation: none
opacity: 1
transform: none
Contraste de Cores
Use tokens semânticos que garantem contraste adequado:
@use '../abstract' as *
// ✅ Bom contraste
.text-on-dark
color: color('text-secondary') // Claro sobre escuro
.text-on-light
color: color('text-inverse') // Escuro sobre claro
Links e Botões
// Diferencie links de texto comum
a
color: color('text-secondary')
&:hover
text-decoration: underline // Indicador visual adicional
&:focus-visible
outline: 2px solid color('text-primary')
outline-offset: 2px
// Botões devem parecer clicáveis
.btn
cursor: pointer
&:disabled
cursor: not-allowed
opacity: 0.5
Checklist para Pull Requests
Antes de submeter um PR com mudanças CSS/Sass, verifique:
Estrutura e Organização
- O código segue a estrutura ITCSS (Abstracts → Core → Components)?
- Arquivos partials começam com
_? - Barrel files usam
@forwardcorretamente? - O componente foi colocado na pasta correta?
Nomenclatura
- Classes seguem BEM (Block__Element—Modifier)?
- Modificadores usam
--(duplo hífen)? - Elementos usam
__(duplo underscore)? - Estados usam prefixo
is-ouhas-? - Nomes descrevem função, não aparência?
Design Tokens
- Cores usam
color('token')em vez de valores hard-coded? - Spacing usa
spacing('token')? - Radius usa
radius('token')? - Shadows usam
shadow('token')ou@include shadow()?
Responsividade
- Estilos base são mobile-first?
- Media queries usam mixins (
@include up(), etc.)? - Breakpoints seguem o mapa definido?
Acessibilidade
- Estados de foco estão estilizados (
:focus-visible)? - Animações respeitam
prefers-reduced-motion? - Contraste de cores é adequado?
- Conteúdo decorativo está oculto para screen readers quando necessário?
Performance
- Animações usam apenas
transformeopacity? - Evitou animações de
width,height,top,left? - Seletores são específicos mas não excessivamente aninhados?
- Não há CSS duplicado ou desnecessário?
Boas Práticas Gerais
- Usa
@useem vez de@import? - Mixins e funções são reutilizáveis?
- Comentários explicam “porquê”, não “o quê”?
- Código foi testado em múltiplos viewports?
Referências Rápidas
Atalhos de Spacing
| Token | Valor | Pixel (base 16px) |
|---|---|---|
| none | 0 | 0px |
| xs | 0.5rem | 8px |
| sm | 1rem | 16px |
| md | 1.5rem | 24px |
| lg | 2rem | 32px |
| xl | 3rem | 48px |
| 2xl | 4rem | 64px |
| 3xl | 6rem | 96px |
Breakpoints
| Token | Valor | Dispositivo |
|---|---|---|
| xs | 0 | Mobile Portrait (base) |
| sm | 576px | Smartphone Landscape |
| md | 768px | Tablet Portrait |
| lg | 992px | Tablet Landscape / Laptop |
| xl | 1200px | Desktop |
| xxl | 1440px | Monitores Grandes |
Cores Semânticas
| Token | Uso |
|---|---|
| bg-primary | Fundo principal |
| bg-secondary | Fundo secundário |
| bg-tertiary | Fundo terciário |
| text-primary | Texto primário |
| text-secondary | Texto secundário/de destaque |
| text-inverse | Texto em fundo claro |
| text-muted | Texto desativado/secundário |
| ui-border | Bordas de UI |
| ui-divider | Divisórias |
Easings
| Token | Valor | Uso |
|---|---|---|
| ease | ease | Padrão |
| ease-out | ease-out | Saída (entradas) |
| ease-in | ease-in | Entrada (saídas) |
| smooth | cubic-bezier(0.4, 0, 0.2, 1) | Movimentos premium |
| slide-up | cubic-bezier(0.16, 1, 0.3, 1) | Slide para cima |
| snappy | cubic-bezier(0.2, 0, 0, 1) | Resposta rápida |
Este guia é vivo e deve ser atualizado conforme a evolução do design system do projeto.
Contribuidores: Time de Front-end
Revisão: Semestral ou quando mudanças significativas ocorrerem