Cheatsheet Tailwind CSS
Framework CSS utility-first
Tailwind CSS
Instalação e Configuração
Instalação (Vite + v4)
npm install -D tailwindcss @tailwindcss/vite
// vite.config.js
import tailwindcss from '@tailwindcss/vite'
export default {
plugins: [tailwindcss()]
}
/* input.css */
@import "tailwindcss";
/* Build: npm run dev / npm run build */No Tailwind v4, instale @tailwindcss/vite e adicione ao array plugins. O CSS usa apenas @import "tailwindcss" (substitui as 3 diretivas @tailwind base/components/utilities do v3). O Vite processa tudo automaticamente sem necessidade de postcss.config.js ou tailwind.config.js.
Escala de espaçamento
/* 1 unidade = 0.25rem (4px) */ p-1 = 0.25rem (4px) p-2 = 0.5rem (8px) p-4 = 1rem (16px) p-8 = 2rem (32px) p-16 = 4rem (64px) /* Valores disponíveis: */ 0, 0.5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60, 64, 72, 80, 96 /* Mesma escala para: p, m, w, h, gap, size, space */
A escala é consistente em todo o framework: cada unidade = 0.25rem (4px). p-4 = 16px, m-8 = 32px, w-16 = 64px. A mesma escala aplica-se a padding, margin, width, height, gap, size e space. Valores maiores (72, 80, 96) são para layouts e secções. Use [valor] para valores arbitrários fora da escala.
Plugins oficiais
// tailwind.config.js (v3)
module.exports = {
plugins: [
require('@tailwindcss/forms'),
require('@tailwindcss/typography'),
require('@tailwindcss/aspect-ratio'),
require('@tailwindcss/container-queries'),
]
}
/* v4: importar no CSS */
@plugin "@tailwindcss/forms";
@plugin "@tailwindcss/typography";Plugins oficiais estendem o Tailwind: @tailwindcss/forms estiliza inputs com reset consistente. typography adiciona a classe prose para conteúdo HTML rico (markdown, CMS). aspect-ratio para proporções (vídeos). container-queries para estilos baseados no contentor. No v4, use @plugin no CSS em vez de require().
Laravel + Blade + Vite
/* 1. Instalar */
npm install -D tailwindcss @tailwindcss/vite
/* 2. resources/css/app.css */
@import "tailwindcss";
/* 3. vite.config.js */
import tailwindcss from '@tailwindcss/vite'
export default {
plugins: [laravel({ input: ['resources/css/app.css',
'resources/js/app.js'], refresh: true }),
tailwindcss()]
}
/* 4. Blade: */
@vite(['resources/css/app.css', 'resources/js/app.js'])Integração com Laravel: instale o Tailwind + plugin Vite, importe no app.css, configure o vite.config.js com os plugins laravel() e tailwindcss(). No Blade, use @vite() para incluir os assets. O refresh: true recarrega a página quando ficheiros Blade mudam. O content deve incluir ./resources/views/**/*.blade.php.
Instalação (PostCSS / v3)
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p
// tailwind.config.js
module.exports = {
content: ["./src/**/*.{html,js,vue,blade.php}"],
theme: { extend: {} },
plugins: [],
}
/* input.css */
@tailwind base;
@tailwind components;
@tailwind utilities;No v3, use postcss + autoprefixer. O campo content define os ficheiros que o Tailwind analisa para gerar apenas o CSS usado (tree-shaking). As 3 diretivas @tailwind importam as camadas: base (reset/preflight), components e utilities. O init -p cria também o postcss.config.js.
Personalizar tema (v3 config)
// tailwind.config.js
module.exports = {
theme: {
extend: {
colors: {
marca: '#1fb6ff',
'marca-dark': '#009eeb',
},
fontFamily: {
sans: ['Inter', 'sans-serif'],
display: ['Clash Display', 'sans-serif'],
},
spacing: { '128': '32rem' },
borderRadius: { '4xl': '2rem' },
}
}
}theme.extend adiciona valores sem substituir os padrões do Tailwind. colors cria cores custom utilizáveis como bg-marca, text-marca. fontFamily define fontes (font-sans, font-display). spacing adiciona valores à escala (p-128). Sem extend, substitui TUDO — use sempre extend para não perder os padrões.
Prettier (ordem de classes)
npm install -D prettier prettier-plugin-tailwindcss
// .prettierrc
{
"plugins": ["prettier-plugin-tailwindcss"]
}
/* Antes (desordenado): */
class="text-white p-4 bg-blue-500 rounded flex mt-2"
/* Depois (ordenado automaticamente): */
class="mt-2 flex rounded bg-blue-500 p-4 text-white"O plugin prettier-plugin-tailwindcss ordena as classes automaticamente na ordem canónica do Tailwind (layout → flex → grid → spacing → sizing → typography → colors → effects). Elimina inconsistências na equipa e facilita a leitura. Funciona com HTML, Vue, React, Blade, Astro. Altamente recomendado em qualquer projeto.
content (tree-shaking)
// tailwind.config.js (v3)
module.exports = {
content: [
"./index.html",
"./src/**/*.{html,js,ts,vue,jsx,tsx}",
"./resources/views/**/*.blade.php",
"./app/Livewire/**/*.php",
],
}
/* v4: deteção automática (sem config) */
/* Usa @source para adicionar caminhos extras: */
@source "../vendor/laravel/framework/src";O content diz ao Tailwind quais ficheiros analisar para extrair classes usadas. Só o CSS das classes encontradas é gerado (tree-shaking). Inclua TODOS os ficheiros com classes: HTML, JS, Vue, Blade, PHP (Livewire). No v4, a deteção é automática na maioria dos casos. Use @source para caminhos fora do projeto (ex.: vendor). Se uma classe não aparece, provavelmente falta o ficheiro no content.
Via CDN (Play CDN)
<!-- Só para protótipos e desenvolvimento -->
<script src="https://cdn.tailwindcss.com"></script>
<!-- Configuração inline (opcional): -->
<script>
tailwind.config = {
theme: {
extend: {
colors: { marca: '#1fb6ff' }
}
}
}
</script>
<!-- Uso imediato: -->
<div class="p-4 bg-marca text-white">Olá!</div>O Play CDN é apenas para protótipos e aprendizagem — não use em produção (gera CSS em runtime, sem tree-shaking). Permite testar classes imediatamente sem build. A configuração é feita via objeto tailwind.config inline. Para produção, use sempre Vite ou PostCSS.
Personalizar tema (v4 CSS)
/* input.css — Tailwind v4 */
@import "tailwindcss";
@theme {
--color-marca: #1fb6ff;
--color-marca-dark: #009eeb;
--font-sans: 'Inter', sans-serif;
--font-display: 'Clash Display', sans-serif;
--spacing-128: 32rem;
--breakpoint-3xl: 1920px;
--radius-4xl: 2rem;
}
/* Uso: bg-marca, font-display, p-128, 3xl:flex, rounded-4xl */No v4, a configuração é feita em CSS com @theme — não precisa de tailwind.config.js. Defina variáveis --color-*, --font-*, --spacing-*, --breakpoint-*. Cada variável gera utilitários automaticamente: --color-marca → bg-marca, text-marca, border-marca. Mais simples e com autocomplete no editor.
CLI e build
/* Build para produção (v3 CLI standalone) */ npx tailwindcss -i input.css -o output.css --minify /* Watch em desenvolvimento */ npx tailwindcss -i input.css -o output.css --watch /* v4 com Vite (não precisa de CLI separado) */ npm run dev /* vite dev — hot reload */ npm run build /* vite build — CSS otimizado */ /* O output final é minúsculo (tree-shaking) */ /* Projeto grande: ~10-30kb de CSS final */
O CLI compila o CSS: -i (input), -o (output), --minify (produção), --watch (desenvolvimento com hot reload). No v4 com Vite, o build é integrado (vite build). O output final é minúsculo porque o tree-shaking remove todas as classes não usadas no HTML. Um projeto grande gera tipicamente 10-30kb de CSS.
Uso básico (utility-first)
<div class="p-4 bg-blue-500 text-white rounded-lg shadow-md"> Olá Tailwind! </div> <button class="px-6 py-2 bg-green-600 text-white font-semibold rounded-full hover:bg-green-700 transition duration-200"> Clica aqui </button> <a href="#" class="text-blue-600 underline hover:text-blue-800">Link</a>
O conceito utility-first: componha o design com classes pequenas diretamente no HTML, sem escrever CSS custom. p-4 = padding de 1rem, bg-blue-500 = fundo azul, rounded-lg = cantos arredondados, shadow-md = sombra média. Cada classe faz UMA coisa. O resultado é um design consistente e sem ficheiros CSS separados.
Valores arbitrários
/* Qualquer valor com [ ] */
w-[300px]
h-[calc(100vh-64px)]
bg-[#1fb6ff]
text-[13px]
grid-cols-[1fr_2fr_1fr]
top-[117px]
shadow-[0_0_10px_rgba(0,0,0,0.3)]
tracking-[0.2em]
max-w-[1400px]
z-[999]
/* Underscores = espaços */
bg-[url('/img/hero.png')]Colchetes [ ] permitem qualquer valor CSS sem configurar o tema. w-[300px] = width exata de 300px. bg-[#1fb6ff] = cor hexadecimal custom. grid-cols-[1fr_2fr] = template custom. Use underscores em vez de espaços dentro dos colchetes. Ideal para valores únicos que não justificam uma entrada no tema.
Preflight (reset CSS)
/* O Tailwind aplica um reset global (preflight): */
- margin: 0 em todos os elementos
- box-sizing: border-box globalmente
- border: 0 solid (sem borda por padrão)
- img, svg, video: display block, max-width 100%
- button, input: font inherit, sem estilos
- h1-h6, p: font-size/weight herdados
- a: color inherit, text-decoration inherit
- ul, ol: list-style none, padding 0
/* Desativar (não recomendado): */
corePlugins: { preflight: false }O preflight é o reset CSS do Tailwind (baseado no modern-normalize). Remove margens, paddings e estilos padrão do browser. Define box-sizing: border-box globalmente. Imagens tornam-se display: block com max-width: 100%. Botões e inputs herdam a fonte. É por isto que precisa de adicionar border explicitamente para ver bordas.
Layout e Display
Display
block /* display: block */ inline-block /* display: inline-block */ inline /* display: inline */ flex /* display: flex */ inline-flex /* display: inline-flex */ grid /* display: grid */ inline-grid /* display: inline-grid */ hidden /* display: none */ contents /* display: contents */ table /* display: table */ /* Responsivo: */ class="hidden md:flex" /* oculto no mobile, flex em md+ */ class="block lg:hidden" /* visível só no mobile */
block, inline, flex, grid controlam o tipo de exibição do elemento. hidden remove completamente do fluxo (como display: none). contents faz o elemento "desaparecer" mantendo os filhos visíveis no layout. Combine com breakpoints para mostrar/ocultar responsivamente: hidden md:flex é o padrão mais usado.
Z-index
z-0, z-10, z-20, z-30, z-40, z-50 z-auto /* z-index: auto */ -z-10 /* negativo (atrás) */ z-[100] /* arbitrário */ /* Convenção sugerida: */ /* Conteúdo base: z-0 (ou sem z-index) */ /* Dropdown/menu: z-10 */ /* Sticky header: z-20 */ /* Sidebar: z-30 */ /* Modal overlay: z-40 */ /* Modal/toast: z-50 */ /* Requer position: relative/absolute/fixed/sticky */
z-0 a z-50 controlam a ordem de empilhamento (qual elemento fica por cima). z-auto = sem z-index. Use z-[100] para valores custom. Adote uma convenção na equipa: conteúdo z-0, dropdowns z-10, sticky z-20, modais z-50. Só funciona com position (relative, absolute, fixed ou sticky).
Float e clear
float-start /* esquerda em LTR, direita em RTL */ float-end /* direita em LTR, esquerda em RTL */ float-none /* sem float */ clear-both /* limpa floats */ clearfix /* pseudo-element ::after no pai */ /* Uso legacy (texto à volta de imagem): */ <img class="float-start me-4 mb-2 w-32" src="foto.jpg"> <p>Texto flui à volta da imagem...</p> /* HOJE: prefira flex ou grid para layouts */
float-* é legacy — hoje prefira flex ou grid para layouts. float-start/float-end são RTL-aware (substituem float-left/float-right). clearfix limpa floats no pai (evita colapso de altura). Mantido para compatibilidade com layouts antigos e para o caso de uso de texto a fluir à volta de imagens.
Box sizing
box-border /* width inclui padding + border (padrão TW) */ box-content /* width só do conteúdo */ /* O Tailwind aplica box-border globalmente via preflight */ /* Exemplo com box-content: */ <div class="box-content w-32 p-4 border-2"> /* Conteúdo: 128px */ /* Total renderizado: 128 + 32 (padding) + 4 (border) = 164px */ </div> /* Com box-border (padrão): */ <div class="box-border w-32 p-4 border-2"> /* Total: 128px (conteúdo encolhe para caber) */ </div>
O Tailwind aplica box-sizing: border-box globalmente via preflight. box-border = a width inclui padding e border (mais intuitivo). box-content = width é só do conteúdo (comportamento CSS original). Raramente precisa de mudar — o border-box é mais previsível porque w-32 é sempre 128px independentemente do padding.
Container
<div class="container mx-auto px-4">
Conteúdo centrado com padding lateral
</div>
/* Config (v3): */
container: {
center: true,
padding: { DEFAULT: '1rem', sm: '2rem' },
screens: { '2xl': '1400px' }
}
/* v4 (CSS): */
@utility container {
margin-inline: auto;
padding-inline: 1rem;
}container define uma largura máxima responsiva que muda em cada breakpoint (640px, 768px, 1024px, 1280px, 1536px). mx-auto centra horizontalmente. px-4 adiciona padding lateral para não colar às bordas. No v3, configure center: true para centrar automaticamente. No v4, use @utility para personalizar.
Overflow
overflow-auto /* scroll se necessário */ overflow-hidden /* corta o excedente */ overflow-visible /* mostra (padrão) */ overflow-scroll /* scroll sempre */ overflow-x-auto /* scroll horizontal */ overflow-y-hidden /* corta vertical */ overflow-clip /* corta sem criar scroll container */ /* Truncar texto (1 linha): */ class="truncate" /* = overflow-hidden + text-ellipsis + whitespace-nowrap */ /* Tabela larga em mobile: */ <div class="overflow-x-auto"> <table class="w-full">...</table> </div>
overflow-hidden corta conteúdo excedente — essencial com rounded-* para imagens não ultrapassarem os cantos. overflow-x-auto para tabelas largas em mobile (scroll horizontal). truncate = atalho para texto de uma linha com reticências. overflow-clip corta sem criar scroll container (mais performático). overflow-auto mostra scroll só quando necessário.
Visibility e object-fit
visible /* visibility: visible */ invisible /* visibility: hidden (ocupa espaço) */ collapse /* visibility: collapse (tabelas) */ /* Object-fit (imagens/vídeos): */ object-contain /* cabe tudo (pode ter barras) */ object-cover /* preenche cortando */ object-fill /* estica (distorce) */ object-none /* tamanho original */ object-scale-down /* menor entre none e contain */ /* Thumbnail uniforme em grid: */ <img class="w-full h-48 object-cover" src="foto.jpg">
invisible oculta mas mantém o espaço ocupado (ao contrário de hidden que remove do fluxo). object-cover preenche o contentor cortando o excedente (thumbnails, hero images). object-contain mostra a imagem inteira (pode ter barras). Combine com w-full h-48 para imagens de tamanho uniforme em grids. object-fill distorce — evite.
Layout clássico (sidebar + main)
/* Flexbox: */ <div class="flex min-h-screen"> <aside class="w-64 shrink-0 bg-gray-100 p-4">Sidebar</aside> <main class="flex-1 p-8">Conteúdo</main> </div> /* Grid: */ <div class="grid grid-cols-1 md:grid-cols-[250px_1fr] min-h-screen"> <aside class="bg-gray-100 p-4">Sidebar</aside> <main class="p-8">Conteúdo</main> </div> /* Responsivo: sidebar some no mobile */ <aside class="hidden md:block w-64">Sidebar</aside>
Dois padrões para sidebar + conteúdo: flex com w-64 shrink-0 (sidebar fixa) + flex-1 (main estica), ou grid com grid-cols-[250px_1fr] (template explícito). min-h-screen garante altura mínima de ecrã inteiro. Responsivo: hidden md:block oculta a sidebar no mobile. Grid é mais explícito; flex é mais flexível.
Position
static /* padrão (sem posicionamento) */ relative /* relativo à posição normal */ absolute /* relativo ao pai relative mais próximo */ fixed /* relativo ao viewport (sempre visível) */ sticky /* cola ao scroll quando atinge o offset */ /* Padrão clássico: pai relative + filho absolute */ <div class="relative"> <div class="absolute top-0 right-0">Badge</div> </div> /* Navbar fixa ao scroll: */ <nav class="sticky top-0 z-50">Menu</nav>
relative no pai + absolute no filho é o padrão de posicionamento. sticky top-0 cola ao topo ao rolar (navbar, headers de tabela). fixed = sempre visível no viewport (toasts, FAB, modais). static é o padrão (sem posicionamento). Coordenadas: top-0, right-0, inset-0 (todos os lados). Sempre combine com z-index para controlar camadas.
Aspect ratio
aspect-auto /* proporção natural */ aspect-square /* 1/1 (quadrado) */ aspect-video /* 16/9 (vídeo) */ aspect-[4/3] /* arbitrário */ aspect-[21/9] /* ultrawide */ /* Vídeo responsivo: */ <div class="aspect-video w-full"> <iframe class="w-full h-full" src="..."></iframe> </div> /* Avatar quadrado: */ <img class="aspect-square w-24 object-cover rounded-full">
aspect-video = proporção 16:9 para vídeos responsivos (YouTube, Vimeo). aspect-square = 1:1 para avatares e thumbnails. aspect-[4/3] para ratios custom. Substitui o antigo hack de padding-bottom percentual. O conteúdo estica automaticamente para preencher a proporção definida. Combine com object-cover para imagens.
Pointer events e user select
pointer-events-none /* não clica (overlay, loading) */ pointer-events-auto /* restaura cliques */ select-none /* texto não selecionável */ select-text /* selecionável (padrão) */ select-all /* seleciona tudo ao clicar */ select-auto /* Overlay de loading (não bloqueia cliques): */ <div class="absolute inset-0 bg-white/50 pointer-events-none flex items-center justify-center"> <span class="animate-spin text-2xl">⟳</span> </div> /* Botão com ícone (ícone não interfere): */ <button><svg class="pointer-events-none">...</svg> Texto</button>
pointer-events-none desativa cliques no elemento (overlays decorativos, ícones dentro de botões, loading spinners). select-none impede seleção de texto (botões, labels, UI). select-all seleciona tudo ao clicar (códigos, URLs, chaves API). Combine com pointer-events-auto num filho para reativar cliques em elementos específicos dentro de um pai desativado.
Coordenadas (inset)
top-0, top-1/2, top-full, -top-4 bottom-0, left-0, right-0 inset-0 /* top+right+bottom+left: 0 */ inset-x-0 /* left + right: 0 */ inset-y-0 /* top + bottom: 0 */ start-0 /* left em LTR, right em RTL */ end-0 /* right em LTR, left em RTL */ /* Centrar com absolute (padrão): */ class="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2" /* Overlay full-screen: */ class="absolute inset-0 bg-black/50"
inset-0 = todos os lados a 0 (overlay full-screen, backgrounds). inset-x-0 = só horizontal. start/end são propriedades lógicas (RTL-aware). Para centrar um elemento: absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2. Valores negativos com prefixo - (ex.: -top-4 para sobrepor).
Columns (multi-coluna)
columns-1, columns-2, columns-3, columns-4 columns-auto columns-[250px] /* largura mínima por coluna */ <div class="columns-2 md:columns-3 gap-8"> <p class="break-inside-avoid mb-4">Texto...</p> <p class="break-inside-avoid mb-4">Texto...</p> <img class="break-inside-avoid mb-4" src="foto.jpg"> </div> /* break-inside-avoid impede quebra no meio do elemento */
columns-* cria layout multi-coluna (como jornal/revista). columns-2 md:columns-3 = 2 colunas no mobile, 3 em md+. gap-8 espaça as colunas. break-inside-avoid impede que um elemento seja partido entre colunas. Ideal para listas de links, FAQs, galerias masonry e conteúdo editorial. O conteúdo flui de cima para baixo em cada coluna.
Isolation e contain
isolate /* isolation: isolate (novo stacking context) */ isolation-auto contain-none contain-layout /* isola layout */ contain-paint /* isola paint (clip) */ contain-size /* isola tamanho */ contain-strict /* layout + paint + size */ contain-content /* layout + paint */ /* Problema: filho com -z-10 fica atrás do pai */ /* Solução: isolate no pai */ <div class="isolate relative bg-white"> <div class="absolute -z-10">Fundo decorativo</div> </div>
isolate cria um novo stacking context — impede que filhos com z-index negativo fiquem atrás do pai (problema comum com backgrounds decorativos). contain-* otimiza performance isolando layout/paint do resto da página. contain-paint impede que filhos "vazem" visualmente. Útil para componentes complexos, animações e listas longas.
Espaçamento e Dimensões
Padding
p-4 /* todos os lados (1rem = 16px) */ px-4 /* esquerda + direita (horizontal) */ py-2 /* topo + fundo (vertical) */ pt-4 /* só topo */ pr-2 /* só direita */ pb-4 /* só fundo */ pl-2 /* só esquerda */ ps-4 /* start (LTR: esquerda, RTL: direita) */ pe-4 /* end (LTR: direita, RTL: esquerda) */ /* Responsivo: */ class="p-4 md:p-8" /* mais padding em desktop */
p = padding. Sufixos: x (horizontal), y (vertical), t/b/l/r (lados físicos), s/e (lados lógicos, RTL-aware). Escala: 0 a 96 (cada unidade = 0.25rem). p-4 = 16px. Aceita prefixos responsivos: p-4 md:p-8 = mais padding em desktop.
Size (v3.4+)
size-4 /* width + height: 1rem (16px) */ size-8 /* 2rem x 2rem (32px) */ size-12 /* 3rem x 3rem (48px) */ size-full /* 100% x 100% */ size-screen /* 100vw x 100vh */ size-fit /* fit-content ambos */ size-auto /* Ícones: */ <svg class="size-5 text-gray-500">...</svg> /* Avatar: */ <img class="size-12 rounded-full object-cover" src="avatar.jpg"> /* Thumbnail quadrado: */ <img class="size-24 rounded-lg object-cover" src="foto.jpg">
size-* define width E height simultaneamente (atalho para w-* h-*). size-12 = 48px × 48px. Perfeito para ícones (size-5 = 20px), avatares (size-12 rounded-full) e thumbnails quadrados (size-24). Elimina a repetição w-* h-*. Disponível desde Tailwind v3.4. Aceita responsivo: size-12 md:size-16.
Padding responsivo
/* Secções com padding progressivo: */ class="py-8 md:py-16 lg:py-24" /* Container com padding lateral adaptativo: */ class="px-4 sm:px-6 lg:px-8" /* Card com padding responsivo: */ class="p-4 md:p-6 lg:p-8" /* Hero com mais espaço: */ <section class="py-16 md:py-24 lg:py-32"> <div class="px-4 md:px-0">Conteúdo</div> </section> /* Regra: mais espaço em ecrãs maiores */
Padding responsivo é essencial para designs profissionais: py-8 md:py-16 lg:py-24 = secções com mais espaço vertical em ecrãs maiores. px-4 sm:px-6 lg:px-8 = padding lateral progressivo. Regra geral: mobile tem menos espaço (ecrã pequeno), desktop tem mais (mais espaço disponível). Evita designs "apertados" no desktop ou "largos" no mobile.
Margin
m-4 /* todos os lados */ mx-auto /* centra horizontalmente */ my-4 /* topo + fundo */ mt-4 /* topo */ mb-0 /* remove margem inferior */ ms-2 /* start (RTL-aware) */ -me-2 /* end negativa */ -mt-4 /* margin-top negativa (puxa para cima) */ /* Centrar bloco com largura fixa: */ <div class="max-w-4xl mx-auto px-4">Conteúdo</div> /* Sobreposição (card sobe sobre secção anterior): */ <div class="-mt-8 relative z-10">Card</div>
m = margin, mesma lógica do padding. mx-auto centra blocos com largura fixa (essencial com max-w-*). Valores negativos com prefixo -: -mt-4 (puxa para cima), -me-2. Útil para sobreposições e ajustes finos. mb-0 remove margem inferior. ms/me são RTL-aware.
max-width (content)
max-w-xs /* 20rem (320px) */ max-w-sm /* 24rem (384px) */ max-w-md /* 28rem (448px) */ max-w-lg /* 32rem (512px) */ max-w-xl /* 36rem (576px) */ max-w-2xl /* 42rem (672px) */ max-w-4xl /* 56rem (896px) */ max-w-7xl /* 80rem (1280px) */ max-w-prose /* 65ch (largura ideal de leitura) */ max-w-screen-xl /* 1280px (breakpoint xl) */ /* Artigo legível: */ <article class="max-w-prose mx-auto">Texto longo...</article> /* Container de página: */ <div class="max-w-7xl mx-auto px-4">...</div>
max-w-* limita a largura máxima. max-w-prose = 65 caracteres (largura ideal de leitura para texto longo). max-w-7xl = 80rem (container de página). max-w-screen-xl = largura do breakpoint xl. Combine com mx-auto para centrar. Essencial para legibilidade — texto a 100% de largura é difícil de ler.
min-w-0 e overflow em flex
/* PROBLEMA: texto não trunca em flex */
<div class="flex">
<img class="size-12" src="avatar.jpg">
<p class="truncate">Texto muito longo...</p>
<!-- truncate NÃO funciona sem min-w-0! -->
</div>
/* SOLUÇÃO: min-w-0 no filho flexível */
<div class="flex gap-4">
<img class="shrink-0 size-12" src="avatar.jpg">
<div class="min-w-0">
<p class="truncate">Texto muito longo que agora trunca corretamente...</p>
</div>
</div>min-w-0 é ESSENCIAL em flex/grid para permitir que o conteúdo encolha abaixo do seu tamanho natural. Sem ele, truncate e overflow-hidden não funcionam porque o elemento flex tem min-width: auto por padrão (não encolhe abaixo do conteúdo). Adicione min-w-0 ao filho que precisa de truncar + shrink-0 nos elementos fixos.
Width
w-full /* 100% */ w-screen /* 100vw */ w-auto /* automática */ w-1/2 /* 50% */ w-1/3 /* 33.33% */ w-2/3 /* 66.67% */ w-1/4 /* 25% */ w-3/4 /* 75% */ w-64 /* 16rem (256px) */ w-fit /* fit-content */ w-min /* min-content */ w-max /* max-content */ /* Responsivo: */ class="w-full md:w-1/2 lg:w-1/3"
w-full = 100% do pai. Frações: w-1/2 (50%), w-2/3 (66%), w-3/4 (75%). w-fit = ajusta ao conteúdo. w-screen = 100% da viewport. Responsivo: w-full md:w-1/2 lg:w-1/3 = largura total no mobile, metade em tablet, terço em desktop. Combine com max-w-* para limitar.
space-between (espaço entre filhos)
/* Adiciona margem entre filhos (exceto o 1º) */ space-x-4 /* margin-left: 1rem nos filhos */ space-y-2 /* margin-top: 0.5rem nos filhos */ space-x-reverse space-y-reverse /* Stack vertical (formulários, listas): */ <div class="space-y-4"> <p>Parágrafo 1</p> <p>Parágrafo 2</p> <p>Parágrafo 3</p> </div> /* HOJE: prefira flex/grid + gap */ <div class="flex flex-col gap-4"> ← moderno
space-y-* adiciona margem vertical entre filhos (sem tocar no primeiro). Útil para listas de parágrafos, stacks de botões, formulários. Hoje, flex flex-col gap-4 é preferível (mais simples, sem seletores > * + *). space-x-reverse inverte a direção (para RTL ou flex-row-reverse). Mantido para compatibilidade.
Dimensões responsivas
/* Largura adaptativa: */ class="w-full md:w-1/2 lg:w-1/3" /* Altura adaptativa: */ class="h-48 md:h-64 lg:h-96" /* Size adaptativo: */ class="size-12 md:size-16" /* Max-width por breakpoint: */ class="max-w-sm md:max-w-md lg:max-w-2xl" /* Imagem responsiva: */ <img class="w-full h-auto md:w-1/2 md:h-64 object-cover"> /* Regra: defina mobile-first e sobrescreva */
Dimensões responsivas seguem o padrão mobile-first: defina o valor base (mobile) e sobrescreva em breakpoints maiores. w-full md:w-1/2 = 100% no mobile, 50% em md+. h-48 md:h-64 = mais altura em desktop. size-12 md:size-16 = ícones/avatares maiores. Sempre combine com object-cover para imagens não distorcerem.
Height
h-full /* 100% do pai */ h-screen /* 100vh (viewport) */ h-auto /* automática */ h-16 /* 4rem (64px) */ h-1/2 /* 50% do pai */ max-h-96 /* max-height: 24rem */ min-h-screen /* min-height: 100vh */ min-h-0 /* min-height: 0 */ /* Hero section full-height: */ <section class="min-h-screen flex items-center">...</section> /* Modal com scroll: */ <div class="max-h-[80vh] overflow-y-auto">...</div>
h-screen = 100% da viewport. min-h-screen = altura mínima de ecrã inteiro (hero sections, páginas de login — o conteúdo pode crescer). max-h-* limita altura máxima (modais, dropdowns com scroll). h-full requer que o pai tenha altura definida. min-h-0 é necessário em flex/grid para permitir overflow.
Margin negativa
/* Prefixo - para valores negativos */ -mt-4 /* margin-top: -1rem (puxa para cima) */ -ml-2 /* margin-left: -0.5rem */ -mx-4 /* margem negativa horizontal */ -inset-2 /* top/right/bottom/left: -0.5rem */ /* Card que sobrepõe a secção anterior: */ <section class="bg-blue-600 pb-16">Hero</section> <div class="-mt-8 mx-auto max-w-4xl bg-white rounded-xl shadow-lg p-8"> Card sobreposto </div> /* Imagem que "sai" do contentor: */ <img class="-mx-4 w-[calc(100%+2rem)]" src="wide.jpg">
Valores negativos com prefixo -: -mt-4 puxa o elemento para cima (sobreposição). Padrão clássico: hero com pb-16 + card com -mt-8 (card sobe sobre o hero). -mx-4 para imagens que "saem" do padding do contentor. -inset-2 para overlays ligeiramente maiores. Essencial para designs com sobreposições e profundidade.
Box sizing e contain
box-border /* width inclui padding + border (padrão TW) */ box-content /* width só do conteúdo */ /* contain (performance): */ contain-none contain-layout /* isola layout */ contain-paint /* isola paint (clip visual) */ contain-size /* isola tamanho */ contain-strict /* layout + paint + size */ contain-content /* layout + paint */ /* Otimizar listas longas: */ <div class="contain-content"> <!-- 1000 items --> </div>
O Tailwind aplica box-sizing: border-box globalmente via preflight — a width inclui padding e border. box-content reverte para o comportamento original (width só do conteúdo). contain-* otimiza performance: contain-paint impede que filhos "vazem" visualmente, contain-layout isola o layout. Útil para listas longas e componentes independentes.
Tipografia
Tamanho de fonte
text-xs /* 0.75rem (12px) + line-height 1rem */ text-sm /* 0.875rem (14px) + line-height 1.25rem */ text-base /* 1rem (16px) — padrão do browser */ text-lg /* 1.125rem (18px) */ text-xl /* 1.25rem (20px) */ text-2xl /* 1.5rem (24px) */ text-3xl /* 1.875rem (30px) */ text-4xl /* 2.25rem (36px) */ text-5xl /* 3rem (48px) */ text-6xl ... text-9xl /* Responsivo: */ class="text-xl md:text-3xl lg:text-5xl"
text-* define o tamanho da fonte E o line-height proporcional automaticamente. text-base = 16px (padrão do browser). text-sm/text-xs para texto secundário. text-4xl a text-9xl para títulos hero. Responsivo: text-xl md:text-3xl lg:text-5xl = menor no mobile, maior em desktop.
Line height e letter spacing
/* Line height (entrelinha): */ leading-none /* 1 (sem espaço) */ leading-tight /* 1.25 (títulos) */ leading-snug /* 1.375 */ leading-normal /* 1.5 (padrão) */ leading-relaxed /* 1.625 (corpo de texto) */ leading-loose /* 2 (muito espaço) */ /* Letter spacing (tracking): */ tracking-tighter /* -0.05em */ tracking-tight /* -0.025em (títulos grandes) */ tracking-normal /* 0 */ tracking-wide /* 0.025em (maiúsculas) */ tracking-wider /* 0.05em */ tracking-widest /* 0.1em */
leading-* controla a entrelinha (espaço entre linhas). leading-tight para títulos (linhas próximas), leading-relaxed para corpo de texto (mais espaço, mais legível). tracking-* controla o espaçamento entre letras. tracking-wide para texto em maiúsculas, tracking-tight para títulos grandes (letras mais juntas).
Text overflow e wrapping
text-ellipsis /* reticências (com truncate) */ text-clip /* corta sem reticências */ whitespace-normal /* quebra normal (padrão) */ whitespace-nowrap /* nunca quebra */ whitespace-pre /* preserva espaços e \n */ whitespace-pre-wrap /* preserva + permite quebra */ whitespace-break-spaces /* como pre-wrap + quebra espaços */ /* Código com scroll horizontal: */ <pre class="whitespace-pre overflow-x-auto p-4 bg-gray-900 text-green-400 rounded-lg">código aqui</pre> /* Badge que não quebra: */ <span class="whitespace-nowrap px-2 py-1 bg-gray-100 rounded">Badge</span>
text-ellipsis mostra reticências ao cortar (requer overflow-hidden + whitespace-nowrap). whitespace-pre-wrap preserva formatação de código mas permite quebra de linha. whitespace-nowrap para badges e labels que não devem quebrar. overflow-x-auto + whitespace-pre para blocos de código com scroll horizontal.
Tipografia responsiva
/* Títulos escaláveis: */ <h1 class="text-3xl md:text-4xl lg:text-6xl font-bold"> Título Hero </h1> <h2 class="text-2xl md:text-3xl font-semibold"> Subtítulo </h2> /* Corpo de texto: */ <p class="text-base md:text-lg leading-relaxed text-gray-600"> Parágrafo com boa legibilidade... </p> /* Regra: mobile 1 tamanho menor que desktop */ /* text-3xl → md:text-4xl → lg:text-5xl */
Tipografia responsiva: títulos escalam com breakpoints — text-3xl md:text-4xl lg:text-6xl (menor no mobile, maior em desktop). Corpo de texto: text-base md:text-lg com leading-relaxed para legibilidade. Regra prática: mobile 1-2 tamanhos menor que desktop. Evite texto menor que text-sm (14px) para corpo. text-gray-600 para texto secundário.
Peso da fonte
font-thin /* 100 */ font-extralight /* 200 */ font-light /* 300 */ font-normal /* 400 (padrão) */ font-medium /* 500 */ font-semibold /* 600 */ font-bold /* 700 */ font-extrabold /* 800 */ font-black /* 900 */ /* Uso típico: */ <h1 class="text-4xl font-bold">Título principal</h1> <h2 class="text-2xl font-semibold">Subtítulo</h2> <p class="font-normal text-gray-600">Corpo de texto</p> <span class="text-sm font-medium">Label</span>
font-* define o peso da fonte. font-bold (700) para títulos, font-semibold (600) para subtítulos e UI moderna, font-medium (500) para labels e botões, font-normal (400) para corpo de texto. Certifique-se de que a fonte tem os pesos necessários — carregue do Google Fonts com os pesos específicos para evitar FOUT.
Truncar e clamp
/* Uma linha com reticências: */ <p class="truncate">Texto muito longo que corta com reticências...</p> /* Múltiplas linhas (2-6): */ <p class="line-clamp-3">Texto que corta após 3 linhas e mostra reticências no fim da terceira linha...</p> /* Quebra de palavras: */ break-words /* quebra palavras longas (URLs) */ break-all /* quebra em qualquer caractere */ whitespace-nowrap /* nunca quebra (badges, labels) */ whitespace-pre-line /* preserva \n do texto */ /* line-clamp requer display: -webkit-box (automático) */
truncate = uma linha com reticências (atalho para overflow-hidden + text-ellipsis + whitespace-nowrap). line-clamp-3 = corta após N linhas com reticências (requer display box — automático no Tailwind). break-words evita overflow de URLs longas. whitespace-nowrap impede quebra (badges, labels, datas).
Text transform e indent
/* Transformação: */ uppercase /* MAIÚSCULAS */ lowercase /* minúsculas */ capitalize /* Primeira Letra De Cada Palavra */ normal-case /* normal (remove transformação) */ /* Indentação: */ indent-4 /* text-indent: 1rem */ indent-8 /* text-indent: 2rem */ -indent-4 /* negativo */ /* Hífenes: */ hyphens-none | hyphens-manual | hyphens-auto /* Label clássico: */ <p class="uppercase tracking-wide text-sm font-semibold text-gray-500"> Categoria </p>
uppercase + tracking-wide + text-sm + font-semibold = padrão clássico para labels, badges e categorias. capitalize para títulos. indent-* adiciona indentação na primeira linha (texto editorial). hyphens-auto para texto justificado em colunas estreitas (requer lang no HTML).
Prose (plugin typography)
/* Plugin: @tailwindcss/typography */ <article class="prose prose-lg"> <h1>Título do artigo</h1> <p>Parágrafo com formatação automática...</p> <ul><li>Item 1</li><li>Item 2</li></ul> <blockquote>Citação</blockquote> <pre><code>código</code></pre> </article> /* Tamanhos: prose-sm, prose, prose-lg, prose-xl, prose-2xl */ /* Cores: prose-slate, prose-gray, prose-zinc */ /* Dark: dark:prose-invert */ <article class="prose dark:prose-invert max-w-prose">
O plugin @tailwindcss/typography adiciona a classe prose que estiliza automaticamente conteúdo HTML rico (markdown, CMS, WYSIWYG). Aplica tipografia bonita a h1-h6, p, ul, blockquote, pre, table. Tamanhos: prose-sm a prose-2xl. dark:prose-invert para dark mode. Essencial para blogs e documentação.
Estilo e decoração
italic /* itálico */ not-italic /* remove itálico */ underline /* sublinhado */ overline /* linha acima */ line-through /* rasurado (preço antigo) */ no-underline /* sem decoração (links) */ /* Sublinhado estilizado: */ class="underline underline-offset-4 decoration-blue-500 decoration-2" /* Maiúsculas/minúsculas: */ uppercase | lowercase | capitalize | normal-case /* Preço com desconto: */ <span class="line-through text-gray-400">€99</span> <span class="font-bold text-green-600">€49</span>
italic/not-italic controlam o estilo da fonte. underline, line-through (rasurado — preços antigos), no-underline (remove sublinhado de links). underline-offset-4 afasta o sublinhado do texto. decoration-blue-500 decoration-2 muda cor e espessura. uppercase para labels e badges.
Font family
font-sans /* ui-sans-serif, system-ui, -apple-system, ... */
font-serif /* ui-serif, Georgia, Cambria, ... */
font-mono /* ui-monospace, SFMono-Regular, Menlo, ... */
/* Custom (v3 config): */
fontFamily: { display: ['Clash Display', 'sans-serif'] }
/* Uso: class="font-display" */
/* v4 (@theme): */
--font-display: 'Clash Display', sans-serif;
/* Uso: */
<h1 class="font-display text-5xl font-bold">Título custom</h1>
<code class="font-mono text-sm bg-gray-100 px-2 py-1 rounded">npm install</code>font-sans (padrão do Tailwind), font-serif, font-mono são as famílias base. Para fontes custom, defina em fontFamily (v3) ou --font-* (v4). font-mono para código, comandos e dados técnicos. Carregue as fontes via Google Fonts (<link>) ou @font-face no CSS. Sempre especifique fallbacks.
Font variant e features
/* Números: */ tabular-nums /* números monoespaçados (tabelas) */ lining-nums /* números alinhados */ oldstyle-nums /* números antigos (descendentes) */ /* Variantes: */ normal-nums ordinal /* 1º, 2º, 3º */ slashed-zero /* 0 com barra (distingue de O) */ /* Font features (OpenType): */ [font-feature-settings:'ss01','cv01'] /* Tabela de valores: */ <td class="tabular-nums text-right">€1.234,56</td> <td class="tabular-nums text-right">€99,00</td>
tabular-nums = números com largura fixa — essencial para tabelas de valores, timers, contadores e dados financeiros (os dígitos alinham em colunas). ordinal para indicadores ordinais (1º, 2º). slashed-zero distingue 0 de O (códigos, seriais). font-feature-settings via valor arbitrário para OpenType features avançadas.
Alinhamento de texto
text-left /* esquerda (padrão LTR) */ text-center /* centrado */ text-right /* direita */ text-justify /* justificado */ /* Responsivo: */ class="text-center md:text-left" /* Vertical (elementos inline/table-cell): */ align-baseline | align-top align-middle | align-bottom align-text-top | align-text-bottom /* Ícone alinhado com texto: */ <span>Texto <svg class="inline align-middle size-4">...</svg></span>
text-center para títulos, CTAs e hero sections. text-left para corpo de texto (mais legível). Responsivo: text-center md:text-left = centrado no mobile, esquerda em desktop. align-* alinha elementos inline verticalmente: align-middle para ícones ao lado de texto. text-justify para texto em colunas estreitas (com hyphens-auto).
Listas
list-none /* sem marcador (menus, nav) */
list-disc /* pontos (padrão ul) */
list-decimal /* números (padrão ol) */
list-inside /* marcador dentro do padding */
list-outside /* marcador fora (padrão) */
/* Lista com estilo: */
<ul class="list-disc list-inside space-y-2 text-gray-700">
<li>Primeiro item</li>
<li>Segundo item</li>
<li>Terceiro item</li>
</ul>
/* Lista custom (sem marcador, com ícone): */
<ul class="space-y-2">
<li class="flex items-center gap-2">
<svg class="size-4 text-green-500">✓</svg> Item
</li>
</ul>list-none remove marcadores (menus, navegação). list-disc/list-decimal restauram os marcadores padrão (o preflight remove-os). list-inside coloca o marcador dentro do padding. Para listas custom com ícones, use list-none + flex items-center gap-2 com um SVG. space-y-2 espaça os itens.
Placeholder e seleção
/* Placeholder: */ <input class="placeholder:text-gray-400 placeholder:italic" placeholder="Escreva aqui..."> /* Seleção de texto: */ <p class="selection:bg-blue-200 selection:text-blue-900"> Texto com seleção customizada </p> /* Caret (cursor do input): */ <input class="caret-blue-500"> /* Combinação num input: */ <input class="w-full px-4 py-2 rounded-lg border placeholder:text-gray-400 caret-blue-600 selection:bg-blue-100 focus:ring-2 focus:ring-blue-500">
placeholder:text-gray-400 estiliza o placeholder (variante placeholder:). selection:bg-* muda a cor de seleção de texto (detalhe de polish). caret-* muda a cor do cursor no input. São detalhes subtis que melhoram a experiência visual e mostram atenção ao detalhe. Combine com focus:ring-2 para um input completo.
Cores e Backgrounds
Cor de texto
text-red-500 text-blue-600 text-green-700 text-gray-900 text-white text-black text-transparent /* Opacidade: */ text-red-500/50 /* 50% opacidade */ text-black/75 /* Cor arbitrária: */ text-[#1fb6ff] text-[rgb(31,182,255)] /* Hierarquia típica: */ <h1 class="text-gray-900">Título</h1> <p class="text-gray-600">Corpo</p> <span class="text-gray-400">Secundário</span>
text-{cor}-{tom} define a cor do texto. Escala de 50 (muito claro) a 950 (muito escuro). text-white/text-black para extremos. /50 adiciona opacidade (50%). text-transparent para texto invisível (com bg-clip-text para gradientes). Hierarquia: text-gray-900 (títulos), text-gray-600 (corpo), text-gray-400 (secundário).
Opacidade
opacity-0 /* invisível */ opacity-5 /* 5% */ opacity-25 /* 25% */ opacity-50 /* 50% */ opacity-75 /* 75% */ opacity-100 /* total (padrão) */ /* Cor com alpha (sintaxe /): */ bg-black/50 /* fundo preto 50% */ text-white/75 /* texto branco 75% */ border-gray-200/50 /* Hover com opacidade: */ class="opacity-70 hover:opacity-100 transition-opacity" /* Overlay de modal: */ <div class="fixed inset-0 bg-black/50 backdrop-blur-sm"></div>
opacity-* controla a transparência do elemento INTEIRO (incluindo filhos). /50 na cor adiciona alpha só à cor (sem afetar filhos). bg-black/50 para overlays de modal. opacity-70 hover:opacity-100 + transition-opacity para efeito hover subtil em imagens e ícones. Prefira /alpha na cor quando quer transparência sem afetar o conteúdo.
Outline
outline-none /* remove outline */ outline /* outline sólido */ outline-dashed outline-dotted outline-2 /* espessura */ outline-blue-500 /* cor */ outline-offset-2 /* distância do elemento */ /* Acessibilidade (focus visível só com teclado): */ <button class="focus-visible:outline focus-visible:outline-2 focus-visible:outline-blue-600 focus-visible:outline-offset-2"> /* NUNCA: focus:outline-none sem alternativa */
outline-* estiliza o contorno (não afeta layout, diferente de border). focus-visible:outline mostra só ao navegar com teclado (melhor que focus:outline-none que remove a acessibilidade). outline-offset-2 afasta o contorno do elemento. NUNCA remova o focus sem alternativa — use focus:ring-2 ou focus-visible:outline para manter acessibilidade.
Cor de fundo
bg-blue-500
bg-gray-100
bg-white
bg-black
bg-transparent
bg-inherit
bg-current /* cor do texto atual */
/* Opacidade: */
bg-blue-500/75
bg-black/50
/* Cor arbitrária: */
bg-[#1fb6ff]
/* Imagem de fundo: */
bg-[url('/img/pattern.png')]
/* Overlay escuro sobre imagem: */
<div class="bg-black/50 absolute inset-0"></div>bg-{cor}-{tom} define o fundo. bg-white/bg-gray-100 para fundos claros. /75 = 75% opacidade (overlays). bg-current usa a cor do texto (útil para ícones SVG que herdam a cor). bg-[url(...)] para imagens de fundo arbitrárias. bg-black/50 para overlays escuros sobre imagens (melhora legibilidade do texto).
Border color
border-gray-300 border-blue-500 border-red-200 border-transparent border-current /* cor do texto */ border-inherit /* Lados específicos: */ border-t-gray-200 /* só topo */ border-b-blue-500 /* só fundo */ /* Opacidade: */ border-gray-300/50 /* Exemplo: card com borda subtil */ <div class="border border-gray-200 rounded-lg p-4"> /* Separador: */ <hr class="border-t border-gray-200">
border-{cor} define a cor da borda. border-t-*/border-b-* para lados específicos (separadores, sublinhados). border-transparent para bordas invisíveis (manter espaço para hover). border-current usa a cor do texto (ícones com borda). Combine com border (1px) ou border-2 para espessura. border-gray-200 é o padrão para bordas subtis.
Background image e size
bg-cover /* preenche (corta excedente) */
bg-contain /* cabe tudo (pode ter barras) */
bg-auto /* tamanho original */
bg-center /* centrado */
bg-top, bg-bottom, bg-left, bg-right
bg-no-repeat /* sem repetição */
bg-fixed /* parallax (fixo ao scroll) */
bg-local /* scroll com conteúdo */
/* Hero com imagem de fundo: */
<div class="bg-cover bg-center bg-no-repeat h-96"
style="background-image: url('hero.jpg')">
<div class="bg-black/50 h-full flex items-center">
<h1 class="text-white text-4xl">Título</h1>
</div>
</div>bg-cover + bg-center = imagem de fundo que preenche sem distorcer (corta o excedente). bg-no-repeat evita repetição. bg-fixed para efeito parallax. Defina a imagem via style inline ou bg-[url(...)]. Combine com overlay bg-black/50 para legibilidade do texto sobre a imagem. Padrão essencial para hero sections.
Paleta de cores padrão
/* Neutros (5 opções): */ slate (azulado) | gray (neutro) | zinc (quente) neutral (puro) | stone (terroso) /* Cores (17): */ red, orange, amber, yellow, lime, green, emerald, teal, cyan, sky, blue, indigo, violet, purple, fuchsia, pink, rose /* Escala por cor (11 tons): */ 50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 950 /* Total: 22 cores × 11 tons = 242 cores */
22 cores × 11 tons = 242 cores disponíveis. Neutros: slate (azulado, moderno), gray (neutro, versátil), zinc (quente), stone (terroso). Escala: 50 (muito claro, fundos) → 500 (base, ações) → 950 (muito escuro, texto). Use 500/600 para botões, 100/200 para fundos, 700/900 para texto.
Ring (anel de focus)
ring-1, ring-2, ring-4, ring-8, ring ring-blue-500 ring-offset-2 ring-offset-white /* Focus state (acessibilidade): */ <button class="focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2"> /* Anel decorativo (avatar): */ <img class="ring-4 ring-blue-300 rounded-full" src="avatar.jpg"> /* Ring em hover: */ <div class="hover:ring-2 hover:ring-blue-400 transition">
ring-* cria um anel (via box-shadow) à volta do elemento — não afeta o layout. ring-offset-2 adiciona espaço entre o elemento e o anel. Essencial para focus:ring-2 (acessibilidade — substitui o outline padrão). ring-4 ring-blue-300 para avatares com destaque. Combine com ring-offset-white em fundos escuros.
bg-clip e mix-blend
/* Clip (recorte do fundo): */ bg-clip-border bg-clip-padding bg-clip-content bg-clip-text /* fundo visível só no texto */ /* Texto com gradiente: */ <h1 class="bg-gradient-to-r from-blue-600 to-purple-600 bg-clip-text text-transparent">Título com gradiente</h1> /* Blend modes: */ mix-blend-multiply /* escurece */ mix-blend-screen /* clareia */ mix-blend-overlay /* contrasta */ mix-blend-difference /* inverte */ /* Overlay criativo: */ <div class="bg-blue-600 mix-blend-multiply">
bg-clip-text + text-transparent = texto com gradiente ou imagem de fundo (muito popular em hero sections). mix-blend-* aplica blend modes (como Photoshop): multiply escurece, screen clareia, overlay contrasta. Útil para overlays criativos, efeitos de imagem e composições visuais avançadas.
Gradientes
<div class="bg-gradient-to-r from-blue-500 to-purple-600"> /* Direções: */ bg-gradient-to-r /* → direita */ bg-gradient-to-l /* ← esquerda */ bg-gradient-to-t /* ↑ cima */ bg-gradient-to-b /* ↓ baixo */ bg-gradient-to-tr /* ↗ diagonal */ bg-gradient-to-br /* ↘ diagonal */ /* Paragem intermédia: */ class="bg-gradient-to-r from-cyan-500 via-blue-500 to-purple-600" /* Gradiente de texto: */ class="bg-gradient-to-r from-blue-600 to-purple-600 bg-clip-text text-transparent"
bg-gradient-to-* define a direção do gradiente. from-* = cor inicial, to-* = cor final, via-* = paragem intermédia (3+ cores). Para texto com gradiente: bg-clip-text text-transparent + gradiente no fundo. Combine com hover:from-* para animar a cor inicial no hover. Gradientes são populares em hero sections e botões CTA.
Divide (separadores entre filhos)
divide-y /* linha horizontal entre filhos */ divide-x /* linha vertical entre filhos */ divide-y-2 /* 2px de espessura */ divide-gray-200 /* cor */ divide-dashed /* tracejado */ divide-y-reverse /* Lista com separadores: */ <ul class="divide-y divide-gray-200"> <li class="py-3">Item 1</li> <li class="py-3">Item 2</li> <li class="py-3">Item 3</li> </ul> /* Vantagem: sem borda no último item */
divide-y adiciona bordas entre filhos (sem tocar no primeiro/último). divide-gray-200 define a cor. divide-dashed para tracejado. Substitui border-b em cada item (mais limpo, sem borda no último). Ideal para listas, feeds, tabelas e qualquer stack vertical com separadores. divide-x para separadores verticais (botões lado a lado).
Cores semânticas (estados)
/* Sucesso: */ class="bg-green-100 text-green-800 border-green-200" /* Erro: */ class="bg-red-100 text-red-800 border-red-200" /* Aviso: */ class="bg-amber-100 text-amber-800 border-amber-200" /* Info: */ class="bg-blue-100 text-blue-800 border-blue-200" /* Neutro: */ class="bg-gray-100 text-gray-800 border-gray-200" /* Padrão: fundo claro (100) + texto escuro (800) + borda (200) */
Cores semânticas para estados: green (sucesso), red (erro), amber (aviso), blue (info), gray (neutro). Padrão consistente: fundo claro (100) + texto escuro (800) + borda subtil (200). Garante contraste legível sem ser agressivo. Use em alertas, badges, toasts e mensagens de validação.
Bordas e Efeitos
Border (estilo e espessura)
border /* 1px todos os lados */ border-2 /* 2px */ border-4 /* 4px */ border-8 /* 8px */ border-0 /* remove */ border-t /* só topo (1px) */ border-b-2 /* só fundo (2px) */ border-x /* esquerda + direita */ border-y /* topo + fundo */ /* Estilo: */ border-solid | border-dashed | border-dotted border-double | border-none /* Card com borda subtil: */ <div class="border border-gray-200 rounded-lg p-4">
border = 1px sólido em todos os lados (o mais usado). border-2/border-4 para mais espessura. border-t/border-b para lados específicos (separadores, sublinhados). border-dashed/border-dotted para estilos alternativos. Combine com border-gray-200 para cor subtil. O preflight remove bordas padrão — adicione explicitamente.
Transformações
/* Escala: */ scale-105, scale-95, scale-0, scale-150 scale-x-50, scale-y-110 /* Rotação: */ rotate-45, rotate-90, rotate-180 -rotate-12 /* Translação: */ translate-x-4, -translate-y-2 translate-x-1/2, -translate-x-1/2 /* Skew: */ skew-x-3, -skew-y-6 /* Hover (zoom em card): */ class="hover:scale-105 transition-transform duration-300" /* Ícone que roda: */ class="group-hover:rotate-90 transition-transform"
scale-105 = 105% (hover em cards, zoom subtil). rotate-45 = 45° (setas, ícones). translate-x-1/2 = desloca 50% (centragem com absolute). skew-* para efeitos inclinados. Valores negativos com -. Combine com transition-transform para animar. hover:scale-110 = zoom no hover (imagens, cards).
Cursor e resize
cursor-pointer /* mão (links/botões) */ cursor-default /* seta normal */ cursor-not-allowed /* proibido (disabled) */ cursor-wait /* ampulheta (loading) */ cursor-text /* texto (inputs) */ cursor-move /* mover (drag) */ cursor-grab /* agarrar */ cursor-grabbing /* a arrastar */ cursor-zoom-in cursor-crosshair /* Resize (textareas): */ resize-none | resize | resize-x | resize-y /* Botão disabled: */ <button disabled class="cursor-not-allowed opacity-50">
cursor-pointer para elementos clicáveis (o Tailwind remove do button por padrão no preflight). cursor-not-allowed para estados disabled. cursor-grab/grabbing para drag & drop. resize-none remove o resize de textareas (padrão em UI custom). resize-y só permite resize vertical. Combine com disabled:opacity-50.
Border radius
rounded-none /* 0 (sharp) */ rounded-sm /* 0.125rem (2px) */ rounded /* 0.25rem (4px) — padrão */ rounded-md /* 0.375rem (6px) */ rounded-lg /* 0.5rem (8px) */ rounded-xl /* 0.75rem (12px) */ rounded-2xl /* 1rem (16px) */ rounded-3xl /* 1.5rem (24px) */ rounded-full /* 9999px (círculo/pílula) */ /* Lados específicos: */ rounded-t-lg /* só topo */ rounded-b-none /* remove fundo */ rounded-l-full /* só esquerda */ rounded-tr-xl /* só canto superior direito */
rounded = 0.25rem (padrão). rounded-lg/rounded-xl para cards modernos. rounded-full = círculo (avatares) ou pílula (botões, badges). rounded-t-*/rounded-b-* para lados específicos (cards com imagem no topo). rounded-none remove (estilo sharp/brutalist). rounded-tr-xl para cantos individuais.
Animações
animate-spin /* rotação contínua (loading) */ animate-ping /* pulsa e expande (notificação) */ animate-pulse /* pulsa opacidade (skeleton) */ animate-bounce /* salta (atenção) */ animate-none /* remove animação */ /* Loading spinner: */ <span class="animate-spin inline-block size-6 border-4 border-gray-300 border-t-blue-600 rounded-full"></span> /* Notificação (ponto pulsante): */ <span class="relative"> <span class="animate-ping absolute size-3 bg-red-500 rounded-full"></span> <span class="relative size-3 bg-red-500 rounded-full"></span> </span>
animate-spin para spinners de loading. animate-ping para notificações (pulsa e expande — combine com um ponto estático por cima). animate-pulse para skeleton loading (blocos cinzentos que pulsam). animate-bounce para chamar atenção (setas de scroll). Spinner: border-4 border-t-blue-600 rounded-full animate-spin. Para animações custom, use @keyframes no CSS.
Scroll behavior e snap
/* Smooth scroll: */ scroll-smooth /* scroll suave (âncoras) */ scroll-auto /* instantâneo */ /* Scroll snap: */ snap-x /* snap horizontal */ snap-y /* snap vertical */ snap-mandatory /* obrigatório */ snap-proximity /* por proximidade */ snap-start, snap-center, snap-end snap-none /* Carrossel nativo (sem JS): */ <div class="flex overflow-x-auto snap-x snap-mandatory"> <div class="snap-center shrink-0 w-full">Slide 1</div> <div class="snap-center shrink-0 w-full">Slide 2</div> <div class="snap-center shrink-0 w-full">Slide 3</div> </div>
scroll-smooth no html para scroll suave em âncoras (links #secção). snap-x snap-mandatory + snap-center nos filhos = carrossel nativo sem JavaScript. snap-proximity = snap só quando perto. shrink-0 impede que os slides encolham. Alternativa moderna e performática a bibliotecas de slider (Swiper, Slick).
Sombras (box-shadow)
shadow-sm /* subtil (cards planos) */ shadow /* padrão */ shadow-md /* médio (dropdowns) */ shadow-lg /* grande (modais) */ shadow-xl /* extra */ shadow-2xl /* máximo (hero) */ shadow-inner /* interna (inputs pressionados) */ shadow-none /* remove */ /* Cor da sombra: */ shadow-blue-500/50 shadow-lg shadow-blue-500/25 /* Hover (elevação): */ class="shadow hover:shadow-lg transition-shadow duration-300"
shadow = sombra padrão. shadow-sm subtil (cards planos), shadow-lg pronunciada (dropdowns, modais). shadow-inner = inset (inputs pressionados, wells). Cor: shadow-blue-500/25 para sombras coloridas. Hover: hover:shadow-lg transition-shadow para efeito de elevação (card "sobe"). Essencial para profundidade e hierarquia visual.
Filters (imagem)
/* Blur: */ blur-sm, blur, blur-md, blur-lg, blur-xl /* Brilho/contraste: */ brightness-50, brightness-100, brightness-150 contrast-50, contrast-100, contrast-200 /* Saturação: */ saturate-0, saturate-100, saturate-200 /* Grayscale/Sepia/Invert: */ grayscale, sepia, invert, hue-rotate-90 /* Hover (foto de equipa): */ class="grayscale hover:grayscale-0 transition duration-300" /* Imagem escurecida: */ class="brightness-75 hover:brightness-100 transition"
blur-* desfoca (overlays, backgrounds de modal). brightness-50 escurece, brightness-150 clareia. grayscale + hover:grayscale-0 = efeito clássico em fotos de equipa (cinzento → cor no hover). saturate-0 = sem cor. Combine com transition para animar os filtros no hover. Essencial para galerias e portfolios.
Will-change e performance
will-change-auto
will-change-scroll /* scroll-position */
will-change-contents /* contents */
will-change-transform /* transform */
/* GPU acceleration: */
transform-gpu /* translateZ(0) — força layer GPU */
transform-none
/* Backface (flip cards 3D): */
backface-visible
backface-hidden /* esconde o verso */
/* Flip card: */
<div class="[perspective:1000px]">
<div class="transition-transform duration-500
[transform-style:preserve-3d] hover:[transform:rotateY(180deg)]">
<div class="[backface-visibility:hidden]">Frente</div>
<div class="[transform:rotateY(180deg)] [backface-visibility:hidden]">Verso</div>
</div>
</div>will-change-transform avisa o browser para otimizar (cria layer GPU). Use com moderação — só em elementos que vão animar. transform-gpu força aceleração GPU. backface-hidden para flip cards 3D (esconde o verso ao rodar). Remova will-change após a animação para libertar memória. Flip card usa perspective + preserve-3d + rotateY.
Transições
transition /* propriedades comuns (cor, sombra, transform) */ transition-all /* todas as propriedades */ transition-colors /* cores (bg, text, border) */ transition-transform /* só transform */ transition-opacity transition-shadow transition-none /* Duração e easing: */ duration-150, duration-200, duration-300, duration-500 ease-linear, ease-in, ease-out, ease-in-out /* Botão com transição suave: */ <button class="transition-colors duration-200 hover:bg-blue-700 active:bg-blue-800">
transition anima propriedades comuns (cores, sombras, transforms, opacity). transition-colors = só cores (mais performático que transition-all). duration-200 = 200ms (ideal para UI). ease-in-out = aceleração suave. Sempre combine com o estado (hover:, focus:). Sem transition, a mudança é instantânea (sem animação).
Backdrop filter
backdrop-blur-sm backdrop-blur backdrop-blur-md backdrop-blur-lg backdrop-blur-xl backdrop-brightness-50 backdrop-saturate-150 /* Navbar com vidro fosco (glassmorphism): */ <nav class="fixed top-0 w-full bg-white/70 backdrop-blur-md border-b border-gray-200/50 z-50"> Menu </nav> /* Modal overlay: */ <div class="fixed inset-0 bg-black/30 backdrop-blur-sm">
backdrop-blur-* desfoca o conteúdo ATRÁS do elemento (efeito vidro fosco / glassmorphism). Combine com bg-white/70 (fundo semi-transparente) — sem opacidade, o blur não é visível. backdrop-brightness-50 escurece o fundo. Popular em navbars, modais e overlays modernos. Requer um bg-* com opacidade para o efeito funcionar.
Efeito glassmorphism
/* Card com vidro fosco: */ <div class="bg-white/20 backdrop-blur-lg border border-white/30 rounded-2xl shadow-xl p-6"> Conteúdo glassmorphism </div> /* Navbar glass: */ <nav class="bg-white/70 backdrop-blur-md border-b border-gray-200/50 shadow-sm"> /* Dark mode glass: */ <div class="bg-gray-900/50 backdrop-blur-xl border border-white/10 rounded-xl"> /* Requer: bg com opacidade + backdrop-blur + borda subtil */
Glassmorphism (vidro fosco): combine bg-white/20 (fundo semi-transparente) + backdrop-blur-lg (desfoque) + border border-white/30 (borda subtil) + rounded-2xl shadow-xl. Funciona sobre imagens ou gradientes coloridos. Em dark mode: bg-gray-900/50 + border-white/10. Popular em navbars, cards e overlays modernos (estilo macOS/iOS).
Responsivo e Estados
Breakpoints
sm: /* ≥ 640px (telemóvel landscape) */ md: /* ≥ 768px (tablet) */ lg: /* ≥ 1024px (desktop pequeno) */ xl: /* ≥ 1280px (desktop) */ 2xl: /* ≥ 1536px (ecrã grande) */ /* Mobile-first: */ class="w-full md:w-1/2 lg:w-1/3" /* O padrão é mobile-first: */ /* base = mobile (todos os tamanhos) */ /* prefixo = sobrescreve a partir desse breakpoint */ /* NÃO existe prefixo xs (base = mobile) */
Mobile-first: classes sem prefixo aplicam em TODOS os tamanhos; com prefixo, sobrescrevem a partir desse breakpoint. w-full md:w-1/2 = 100% no mobile, 50% em md+. Não existe prefixo xs — a base É o mobile. Os breakpoints são configuráveis no tema (v3) ou via --breakpoint-* (v4). Pense "a partir de" e não "até".
group (pai controla filhos)
<div class="group cursor-pointer">
<h3 class="text-gray-900 group-hover:text-blue-600
transition-colors">
Título
</h3>
<p class="text-gray-500 group-hover:text-gray-700">
Descrição
</p>
<span class="opacity-0 group-hover:opacity-100
transition-opacity">
→ Ver mais
</span>
</div>
/* group-focus, group-active, group-hover */
/* Nomeado: group/card + group-hover/card: */group no pai + group-hover:* no filho = o filho reage ao hover do PAI. Útil para cards: hover no card muda cor do título, mostra seta, eleva sombra. group-focus:, group-active: também funcionam. Para grupos aninhados, nomeie: group/card + group-hover/card: (evita conflitos). Essencial para componentes interativos.
Container queries (v3.2+)
/* Plugin: @tailwindcss/container-queries */
<div class="@container">
<div class="grid grid-cols-1 @lg:grid-cols-3">
<div>Sidebar</div>
<div class="@lg:col-span-2">Conteúdo</div>
</div>
</div>
/* Breakpoints: @sm, @md, @lg, @xl, @2xl */
/* Baseados na largura do PAI, não do viewport */
/* v4 (nativo, sem plugin): */
@container
@min-[400px]:flex-row
/* Nomeado: @container/sidebar + @lg/sidebar: */@container no pai + @lg:* no filho = estilos baseados na largura do CONTENTOR (não do viewport). Ideal para componentes reutilizáveis: um card na sidebar (estreita) vs. no main (largo) adapta-se automaticamente. @sm, @md, @lg são os breakpoints. No v4, container queries são nativas (sem plugin). Nomeie com @container/nome para múltiplos containers.
Breakpoints custom
/* v3 (config): */
theme: {
screens: {
'xs': '475px',
'sm': '640px',
'md': '768px',
'lg': '1024px',
'xl': '1280px',
'2xl': '1536px',
'3xl': '1920px',
}
}
/* v4 (CSS): */
@theme {
--breakpoint-xs: 475px;
--breakpoint-3xl: 1920px;
}
/* Uso: xs:text-sm, 3xl:text-2xl */Breakpoints custom: adicione xs (475px) para telemóveis pequenos ou 3xl (1920px) para ecrãs grandes. No v3, defina em theme.screens (substitui) ou theme.extend.screens (adiciona). No v4, use --breakpoint-* no @theme. Uso: xs:text-sm, 3xl:text-2xl. Mantenha os padrões e adicione só o necessário.
Estados (hover/focus/active)
<button class="bg-blue-500 text-white px-4 py-2 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-400 active:bg-blue-800 disabled:opacity-50 disabled:cursor-not-allowed transition-colors"> Clica </button> /* Estados disponíveis: */ hover: | focus: | focus-within: | focus-visible: active: | visited: | disabled: | checked: first: | last: | odd: | even: | empty: required: | valid: | invalid: | read-only:
hover: = ao passar o rato. focus:ring-2 = acessibilidade (navegação com teclado). active: = ao clicar/pressionar. disabled:opacity-50 = estado desativado. focus-visible: = só ao navegar com teclado (melhor UX que focus:). Sempre use transition para suavizar as mudanças de estado. Nunca remova o focus sem alternativa.
peer (irmão anterior)
/* Toggle custom: */
<input class="peer sr-only" type="checkbox" id="toggle">
<label for="toggle"
class="block w-12 h-6 bg-gray-300 rounded-full
peer-checked:bg-blue-600 transition-colors">
</label>
/* Validação: */
<input class="peer" type="email">
<p class="hidden peer-invalid:block text-red-500">Inválido</p>
/* Nomeado (múltiplos peers): */
<input class="peer/input">
<span class="peer-checked/input:text-blue-600">
/* O peer DEVE vir ANTES do elemento estilizado no DOM */peer no elemento anterior + peer-checked:* no seguinte = o seguinte reage ao estado do anterior. Essencial para toggles custom (checkbox + label), validação visual (peer-invalid:), e inputs com labels flutuantes. O peer deve vir ANTES do elemento estilizado no DOM. Para múltiplos peers, nomeie: peer/input + peer-checked/input:.
RTL e direções lógicas
/* Lógico (RTL-aware): */ ms-4 /* margin-start (esq em LTR, dir em RTL) */ me-4 /* margin-end */ ps-4 /* padding-start */ pe-4 /* padding-end */ start-0 /* left em LTR, right em RTL */ end-0 /* right em LTR, left em RTL */ text-start | text-end /* Físico (fixo): */ ml-4, mr-4, pl-4, pr-4, left-0, right-0 text-left, text-right /* Variante RTL: */ rtl:space-x-reverse rtl:text-right
Propriedades lógicas (ms, me, ps, pe, start, end) adaptam-se automaticamente a RTL (árabe, hebraico). Prefira lógicas em código novo para internacionalização. rtl:space-x-reverse inverte espaçamento em RTL. text-start/text-end substituem text-left/text-right. Essencial para apps multi-idioma.
Dark mode
/* v3 config: */
darkMode: 'class' /* ou 'media' (padrão) */
/* v4: padrão = media; para class: */
@custom-variant dark (&:where(.dark, .dark *));
/* Uso (pares light/dark): */
<div class="bg-white text-gray-900
dark:bg-gray-900 dark:text-white
dark:border-gray-700">
Conteúdo
</div>
/* Toggle via JS: */
document.documentElement.classList.toggle('dark')
/* Sempre defina PARES: bg-white dark:bg-gray-900 */dark: aplica estilos no tema escuro. darkMode: 'class' (v3) = controlado por classe .dark no html. 'media' (padrão) = segue prefers-color-scheme do sistema operativo. No v4, use @custom-variant para modo class. Sempre defina pares: bg-white dark:bg-gray-900. Inclua bordas: border-gray-200 dark:border-gray-700.
Variantes de filho e posição
/* Primeiro/último filho: */ first:pt-0 last:pb-0 last:border-0 /* Odd/even (linhas alternadas): */ odd:bg-gray-50 even:bg-white /* Único filho: */ only:rounded-lg /* Vazio: */ empty:hidden /* Lista com separadores e padding ajustado: */ <ul class="divide-y divide-gray-200"> <li class="py-3 first:pt-0 last:pb-0">Item</li> </ul> /* Tabela com linhas alternadas: */ <tr class="odd:bg-gray-50 even:bg-white">
first:, last:, odd:, even:, only:, empty: são variantes de posição/estado do elemento. first:pt-0 last:pb-0 remove padding extra no início/fim de listas. odd:bg-gray-50 = linhas alternadas (tabelas). last:border-0 remove borda do último item. empty:hidden oculta elementos vazios.
Print e motion
/* Print: */ print:hidden /* oculto na impressão */ print:block /* visível só na impressão */ print:text-black /* texto preto na impressão */ print:shadow-none /* sem sombras */ /* Motion (respeita preferências do utilizador): */ motion-safe:animate-bounce motion-reduce:transition-none motion-reduce:animate-none /* Botão com animação acessível: */ <button class="motion-safe:hover:scale-105 motion-reduce:hover:scale-100 transition"> /* Respeita prefers-reduced-motion do SO */
print:hidden oculta elementos na impressão (nav, botões, sidebars). print:text-black força texto preto (economiza tinta). motion-safe: aplica animações só se o utilizador não pediu movimento reduzido. motion-reduce: remove animações para quem prefere. Essencial para acessibilidade (distúrbios vestibulares, epilepsia). Respeita prefers-reduced-motion.
Mostrar/ocultar responsivo
/* Esconder no mobile, mostrar em md+: */ hidden md:block /* Mostrar só no mobile: */ block md:hidden /* Visibilidade (mantém espaço): */ visible | invisible /* Menu desktop + hambúrguer mobile: */ <nav class="hidden md:flex gap-4"> <a href="#">Início</a> <a href="#">Sobre</a> </nav> <button class="md:hidden">☰</button> /* Sidebar: oculta no mobile */ <aside class="hidden lg:block w-64">Sidebar</aside>
hidden md:block = oculto no mobile, visível em md+. block md:hidden = visível só no mobile. hidden = display: none (remove do fluxo, não ocupa espaço). invisible = visibility: hidden (mantém espaço). Padrão clássico: nav hidden md:flex + botão hambúrguer md:hidden. Essencial para navegação responsiva.
Variantes de dados e ARIA
/* Data attributes: */ data-[state=open]:block data-[active=true]:text-blue-600 data-[side=top]:animate-in /* ARIA: */ aria-selected:bg-blue-100 aria-expanded:rotate-180 aria-hidden:true:invisible aria-invalid:border-red-500 aria-current:font-bold /* Accordion (ícone roda ao expandir): */ <button aria-expanded="false" class="aria-expanded:rotate-180 transition-transform"> ▼ </button>
data-[state=open]: estiliza baseado em atributos data-* (popular em Radix UI, Headless UI, Alpine.js). aria-expanded:rotate-180 roda o ícone quando expandido (accordions). aria-invalid:border-red-500 para validação acessível. aria-current:font-bold para navegação ativa. Essencial para componentes acessíveis com estados geridos por JavaScript.
Responsivo completo (exemplo)
<section class="py-8 md:py-16 lg:py-24">
<div class="container mx-auto px-4 sm:px-6 lg:px-8">
<h1 class="text-2xl md:text-4xl lg:text-5xl
font-bold text-center md:text-left">
Título
</h1>
<p class="mt-4 text-base md:text-lg text-gray-600
max-w-prose mx-auto md:mx-0">
Descrição...
</p>
<div class="grid grid-cols-1 md:grid-cols-2
lg:grid-cols-3 gap-4 md:gap-8 mt-8 md:mt-12">
<div class="p-4 md:p-6 bg-white rounded-xl shadow">Card</div>
</div>
</div>
</section>Padrão responsivo completo: padding progressivo (py-8 md:py-16 lg:py-24), tipografia escalável (text-2xl md:text-4xl), grid adaptativo (grid-cols-1 md:grid-cols-2 lg:grid-cols-3), gap responsivo (gap-4 md:gap-8), alinhamento adaptável (text-center md:text-left). Mobile-first: defina o mobile e sobrescreva em breakpoints maiores.
Avançado e Boas Práticas
@apply (componentes CSS)
/* input.css */
@layer components {
.btn {
@apply px-4 py-2 rounded-lg font-medium
transition-colors duration-200;
}
.btn-primary {
@apply btn bg-blue-600 text-white
hover:bg-blue-700;
}
.btn-outline {
@apply btn border-2 border-blue-600 text-blue-600
hover:bg-blue-50;
}
}
/* Uso: */
<button class="btn-primary">Ok</button>@apply extrai classes reutilizáveis em CSS. @layer components garante a ordem correta (não sobrescreve utilities). Útil para botões, inputs e padrões repetidos em conteúdo sem componentes (Markdown, CMS, emails). MAS: prefira componentes do framework (React/Vue/Blade) para reutilização. @apply é para quando precisa de classes em CSS puro.
tailwind-merge e clsx
import { twMerge } from 'tailwind-merge'
import { clsx } from 'clsx'
/* twMerge resolve conflitos: */
twMerge('px-4 py-2', 'px-6') /* → 'py-2 px-6' */
twMerge('text-red-500', 'text-blue-500') /* → 'text-blue-500' */
/* clsx condicional: */
clsx('btn', { 'btn-active': isActive })
/* cn() = clsx + twMerge (padrão shadcn/ui): */
function cn(...inputs) {
return twMerge(clsx(inputs))
}
<div class={cn('p-4', isActive && 'bg-blue-50', className)}>tailwind-merge resolve conflitos: twMerge('px-4', 'px-6') = px-6 (último ganha, sem duplicados). clsx compõe classes condicionalmente. cn() = combinação dos dois (padrão em shadcn/ui). Essencial para componentes que aceitam className prop e precisam de merge sem conflitos. Sem isto, px-4 px-6 gera comportamento imprevisível.
Debug e troubleshooting
/* 1. Classe não funciona? Verifique o content: */ content: ["./resources/views/**/*.blade.php"] /* 2. Inspecione com DevTools: */ /* - A classe está no CSS gerado? */ /* - Há conflito de especificidade? */ /* - Há outra classe a sobrescrever? */ /* 3. Use o plugin Debug Screens: */ /* Mostra o breakpoint ativo no canto */ npm install -D @tailwindcss/debug-screens /* 4. Importante (último recurso): */ class="!text-red-500" /* !important */ /* 5. Ordem: a ÚLTIMA classe no CSS ganha */ /* (não a última no HTML) */
Troubleshooting: 1) Classe não aparece? Verifique o content no config (ficheiro pode não estar incluído). 2) Inspecione com DevTools — a classe está no CSS gerado? Há conflito de especificidade? 3) @tailwindcss/debug-screens mostra o breakpoint ativo. 4) ! prefixo adiciona !important (último recurso). 5) A ORDEM no CSS importa, não a ordem no HTML — a última classe gerada ganha.
@layer e @utility (v4)
/* v4: criar utilitários custom */
@utility scrollbar-hide {
-ms-overflow-style: none;
scrollbar-width: none;
&::-webkit-scrollbar { display: none; }
}
@utility text-shadow {
text-shadow: 0 2px 4px rgba(0,0,0,0.3);
}
/* Uso (funciona com variantes!): */
<div class="scrollbar-hide hover:text-shadow md:text-shadow">
/* v3 (@layer): */
@layer utilities {
.scrollbar-hide { ... }
}
/* Layers: base < components < utilities */No v4, @utility cria utilitários custom que funcionam com variantes (hover:scrollbar-hide, md:text-shadow). No v3, use @layer utilities (mas sem variantes automáticas). @layer components para classes compostas. @layer base para reset/estilos globais. A ordem das layers importa: base < components < utilities.
Componentes Blade (Laravel)
{{-- resources/views/components/button.blade.php --}}
@props(['variant' => 'primary', 'size' => 'md'])
@php
$base = 'inline-flex items-center gap-2 rounded-lg
font-medium transition-colors focus:ring-2';
$variants = [
'primary' => 'bg-blue-600 text-white hover:bg-blue-700',
'outline' => 'border-2 border-blue-600 text-blue-600',
];
$sizes = ['sm' => 'px-3 py-1.5 text-sm',
'md' => 'px-4 py-2', 'lg' => 'px-6 py-3 text-lg'];
@endphp
<button {{ $attributes->class([$base,
$variants[$variant], $sizes[$size]]) }}>
{{ $slot }}
</button>
{{-- Uso: <x-button variant="outline" size="lg">Ok</x-button> --}}Componentes Blade reutilizáveis: defina $base + arrays de variantes. Use $attributes->class([]) para merge de classes (Laravel merge automaticamente). Props com defaults: @props(['variant' => 'primary']). Uso: <x-button variant="outline" size="lg">. Alternativa ao @apply — mais flexível e com suporte a variantes. Padrão recomendado em Laravel.
Performance e produção
/* 1. Tree-shaking (automático): */ /* Só classes usadas no HTML são geradas */ /* Projeto grande: ~10-30kb de CSS final */ /* 2. PurgeCSS (v3 — automático via content) */ /* 3. Minificação: */ npx tailwindcss -i input.css -o output.css --minify /* 4. Evite transition-all (específico é melhor): */ transition-colors /* bom */ transition-all /* pesado (todas as props) */ /* 5. will-change com moderação */ /* 6. Lazy load de imagens: */ <img loading="lazy" class="..." src="foto.jpg">
Performance: 1) tree-shaking automático — só classes usadas são geradas (10-30kb final). 2) Minifique com --minify ou vite build. 3) Prefira transition-colors a transition-all (menos propriedades animadas = mais performático). 4) will-change com moderação (cria layers GPU). 5) loading="lazy" em imagens abaixo do fold. 6) Evite @apply excessivo (gera CSS duplicado).
Boas práticas
/* 1. Mobile-first: base → sm → md → lg */
class="flex-col md:flex-row"
/* 2. Componentes no framework (não @apply) */
<Button variant="primary" size="lg" />
/* 3. Prettier para ordenar classes */
prettier-plugin-tailwindcss
/* 4. Evitar classes duplicadas/conflituosas */
/* Mau: class="p-4 p-2" */
/* 5. Usar variantes em vez de CSS custom */
hover:bg-blue-700 (não .btn:hover { })
/* 6. max-w-prose para texto longo */
<article class="max-w-prose">
/* 7. gap em vez de space-x/y */
class="flex gap-4"Boas práticas: 1) Mobile-first sempre (base → breakpoints maiores). 2) Extraia componentes no framework (React/Vue/Blade) em vez de @apply. 3) Use prettier-plugin-tailwindcss para ordem consistente. 4) Evite classes duplicadas/conflituosas. 5) Prefira variantes (hover:) a CSS custom. 6) max-w-prose para legibilidade. 7) gap em vez de space-*.
Animações custom (@keyframes)
/* v4 (CSS): */
@theme {
--animate-fade-in: fade-in 0.3s ease-out;
--animate-slide-up: slide-up 0.5s ease-out;
}
@keyframes fade-in {
from { opacity: 0; }
to { opacity: 1; }
}
@keyframes slide-up {
from { opacity: 0; transform: translateY(1rem); }
to { opacity: 1; transform: translateY(0); }
}
/* Uso: class="animate-fade-in" */
/* v3 (config): */
theme: { extend: { animation: {
'fade-in': 'fade-in 0.3s ease-out' },
keyframes: { 'fade-in': { ... } } } }Animações custom: defina @keyframes + variável --animate-* (v4) ou theme.extend.animation + keyframes (v3). Uso: animate-fade-in, animate-slide-up. Funciona com variantes: hover:animate-fade-in. Para animações complexas (stagger, spring), use bibliotecas como framer-motion ou @tailwindcss/animate.
CVA (Class Variance Authority)
import { cva } from 'class-variance-authority'
const button = cva(
'px-4 py-2 rounded-lg font-medium transition',
{
variants: {
variant: {
primary: 'bg-blue-600 text-white hover:bg-blue-700',
outline: 'border-2 border-blue-600 text-blue-600',
ghost: 'hover:bg-gray-100',
},
size: {
sm: 'px-3 py-1.5 text-sm',
lg: 'px-6 py-3 text-lg',
},
},
defaultVariants: { variant: 'primary', size: 'sm' },
}
)
<button class={button({ variant: 'outline', size: 'lg' })}>CVA (class-variance-authority) gere variantes de classes em componentes React. Define classes base + variantes (variant, size) + defaults. Gera as classes corretas sem conflitos. Popular em React + Tailwind (shadcn/ui usa CVA). Alternativa: clsx + tailwind-merge para composição manual. Essencial para design systems com múltiplas variantes.
sr-only e acessibilidade
/* Texto visível só para leitores de ecrã: */ <a href="#conteudo" class="sr-only focus:not-sr-only focus:absolute focus:top-2 focus:left-2 focus:z-50 focus:px-4 focus:py-2 focus:bg-white focus:rounded-lg focus:shadow"> Saltar para o conteúdo </a> /* sr-only: */ /* position: absolute; width: 1px; height: 1px; */ /* padding: 0; margin: -1px; overflow: hidden; */ /* clip: rect(0,0,0,0); border: 0; */ /* Label acessível (sem visual): */ <label class="sr-only" for="pesquisa">Pesquisar</label> <input id="pesquisa" class="...">
sr-only oculta visualmente mas mantém acessível a leitores de ecrã (position absolute, 1px, clip). Essencial para: labels de inputs com ícone, "skip links" (sr-only focus:not-sr-only = visível só ao focar com teclado), texto descritivo. focus:not-sr-only torna visível ao focar (skip navigation). NUNCA use hidden ou display: none para conteúdo acessível.
Flexbox
Ativar flex e direção
<div class="flex">Contentor flex (linha horizontal)</div> <div class="inline-flex">Flex com display inline</div> /* Direção: */ flex-row /* → horizontal (padrão) */ flex-row-reverse /* ← horizontal invertido */ flex-col /* ↓ vertical (coluna) */ flex-col-reverse /* ↑ vertical invertido */ /* Padrão responsivo mais usado: */ class="flex flex-col md:flex-row" /* Empilha no mobile, lado a lado em md+ */
flex torna o elemento um flex container — os filhos ficam lado a lado por padrão. flex-row (padrão) = linha horizontal; flex-col = coluna vertical. O padrão mobile-first mais usado: flex-col md:flex-row = empilha no mobile, lado a lado em md+. inline-flex = flex com display inline (para botões com ícone).
flex-wrap
flex-wrap /* permite quebra de linha */ flex-nowrap /* não quebra (padrão) */ flex-wrap-reverse /* quebra invertida */ /* Lista de tags/chips: */ <div class="flex flex-wrap gap-2"> <span class="px-3 py-1 bg-gray-100 rounded-full text-sm">Tag 1</span> <span class="px-3 py-1 bg-gray-100 rounded-full text-sm">Tag 2</span> <span class="px-3 py-1 bg-gray-100 rounded-full text-sm">Tag 3</span> <span class="px-3 py-1 bg-gray-100 rounded-full text-sm">Tag 4</span> </div> /* Sem wrap: itens encolhem ou transbordam */
flex-wrap permite que os itens passem para a linha seguinte quando não cabem na horizontal. flex-nowrap (padrão) força tudo numa linha (itens podem encolher ou transbordar). Essencial para listas de tags, chips, filtros, botões de toolbar. Combine com gap-2 para espaçamento consistente entre itens em todas as linhas.
align-content (multi-linha)
/* Requer flex-wrap + altura definida para ter efeito */ content-start content-center content-between content-around content-evenly content-stretch /* padrão */ <div class="flex flex-wrap content-center h-64 gap-4"> <div class="w-1/3 p-4 bg-gray-100">A</div> <div class="w-1/3 p-4 bg-gray-100">B</div> <div class="w-1/3 p-4 bg-gray-100">C</div> <div class="w-1/3 p-4 bg-gray-100">D</div> </div>
content-* alinha as LINHAS quando há flex-wrap e múltiplas linhas. Sem wrap ou com uma só linha, não tem efeito. content-center = linhas centradas verticalmente no contentor. content-between = primeira linha no topo, última no fundo. Útil para grids de cards com altura fixa onde quer distribuir as linhas uniformemente.
Navbar com flex
<nav class="flex items-center justify-between px-6 h-16">
<!-- Logo -->
<a href="/" class="text-xl font-bold">Logo</a>
<!-- Links (centro) -->
<div class="hidden md:flex items-center gap-6">
<a href="#" class="text-gray-600 hover:text-gray-900">Início</a>
<a href="#" class="text-gray-600 hover:text-gray-900">Sobre</a>
<a href="#" class="text-gray-600 hover:text-gray-900">Contacto</a>
</div>
<!-- Ações (direita) -->
<div class="flex items-center gap-3">
<button class="px-4 py-2 text-sm">Entrar</button>
<button class="px-4 py-2 bg-blue-600 text-white
rounded-lg text-sm">Registar</button>
</div>
</nav>Navbar com flex: flex items-center justify-between distribui logo, links e ações. h-16 para altura consistente. Links com hidden md:flex (ocultos no mobile). gap-6 espaça os links. gap-3 para os botões de ação. Padrão universal de navegação — funciona em qualquer projeto.
justify-content (eixo principal)
justify-start /* início (padrão) */ justify-end /* fim */ justify-center /* centro */ justify-between /* espaço ENTRE itens */ justify-around /* espaço À VOLTA de cada item */ justify-evenly /* espaço IGUAL entre todos */ justify-stretch /* esticar para preencher */ /* Navbar: logo à esquerda, menu à direita */ <div class="flex justify-between items-center"> <span>Logo</span> <nav>Menu</nav> </div> /* Centrar horizontalmente: */ <div class="flex justify-center">...</div>
justify-* distribui itens no eixo principal (horizontal em flex-row, vertical em flex-col). justify-between = primeiro item no início, último no fim, espaço entre os restantes. justify-center = tudo centrado. O padrão mais usado em navbars: justify-between items-center (logo + menu nas extremidades, centrados verticalmente).
gap (espaço entre itens)
gap-0, gap-1, gap-2, gap-3, gap-4, gap-6, gap-8 gap-x-4 /* só horizontal (entre colunas) */ gap-y-2 /* só vertical (entre linhas) */ <div class="flex gap-4"> <div>Item</div> <div>Item</div> </div> <div class="grid grid-cols-3 gap-x-6 gap-y-4"> <div>Célula</div> </div> /* Responsivo: */ class="gap-2 md:gap-6"
gap-* define o espaçamento entre flex/grid items — substitui margens manuais. gap-x-* = horizontal, gap-y-* = vertical. Mais limpo que space-x-*/space-y-* (que usa seletores complexos). Funciona em flex E grid. Aceita prefixos responsivos: gap-2 md:gap-6 (mais espaço em desktop). É a forma moderna de espaçar itens.
order (ordem visual)
order-1, order-2, order-3 ... order-12 order-first /* order: -9999 */ order-last /* order: 9999 */ order-none /* order: 0 (padrão) */ <div class="flex"> <div class="order-2">Visualmente 2º</div> <div class="order-1">Visualmente 1º</div> </div> /* Responsivo: imagem antes do texto no desktop */ <div class="flex flex-col md:flex-row"> <div class="order-2 md:order-1">Texto</div> <div class="order-1 md:order-2">Imagem</div> </div>
order-* reordena visualmente sem mudar o HTML (DOM mantém a ordem original). order-first = primeiro; order-last = último. Útil para responsivo: order-1 md:order-2 muda a ordem em md+. O padrão é order-0. Não afeta acessibilidade (leitores de ecrã seguem a ordem do DOM, não a visual).
Media object (imagem + texto)
/* Comentário / perfil / notificação */
<div class="flex gap-4">
<img class="shrink-0 size-12 rounded-full object-cover"
src="avatar.jpg" alt="Avatar">
<div class="min-w-0">
<p class="font-semibold truncate">João Silva</p>
<p class="text-sm text-gray-600">Comentário aqui...</p>
<time class="text-xs text-gray-400">há 2 horas</time>
</div>
</div>
/* min-w-0 permite truncate no texto */O padrão "media object" (imagem + texto ao lado): flex gap-4 + imagem com shrink-0 (não encolhe) + conteúdo com min-w-0 (permite truncate). size-12 rounded-full para avatar circular. min-w-0 é ESSENCIAL em flex para permitir que o texto trunque — sem ele, o conteúdo nunca encolhe abaixo do tamanho natural.
align-items (eixo cruzado)
items-start /* topo */ items-end /* fundo */ items-center /* centro vertical */ items-baseline /* linha de base do texto */ items-stretch /* esticar (padrão) */ /* Centrar verticalmente: */ <div class="flex items-center h-20"> <div>Centrado verticalmente</div> </div> /* Baseline (labels + inputs alinhados): */ <div class="flex items-baseline gap-2"> <label>Nome:</label> <input class="text-lg"> </div>
items-* alinha itens no eixo cruzado (vertical em flex-row). items-center = centrado verticalmente (o mais usado). items-stretch (padrão) = todos com a mesma altura do mais alto. items-baseline = alinha pela linha de base do texto (útil para labels + inputs com tamanhos diferentes). items-start/items-end para topo/fundo.
flex-grow e flex-shrink
grow /* flex-grow: 1 (cresce para preencher) */ grow-0 /* flex-grow: 0 (não cresce) */ shrink /* flex-shrink: 1 (encolhe se necessário) */ shrink-0 /* flex-shrink: 0 (não encolhe) */ /* Input + botão (padrão clássico): */ <div class="flex gap-2"> <input class="grow" placeholder="Pesquisar..."> <button class="shrink-0 px-4">Buscar</button> </div> /* Imagem fixa + texto flexível: */ <div class="flex gap-4"> <img class="shrink-0 size-16" src="avatar.jpg"> <p class="grow">Texto que pode ser longo...</p> </div>
grow = cresce para preencher espaço disponível. shrink-0 = não encolhe (botões, labels, imagens com tamanho fixo). Padrão clássico: input com grow + botão com shrink-0 (o input ocupa o espaço todo, o botão mantém o tamanho). Sem shrink-0, o botão pode encolher e o texto quebrar.
Centrar na perfeição
/* Flexbox (mais comum): */
<div class="flex items-center justify-center h-screen">
<div class="text-center">
Centrado nos 2 eixos
</div>
</div>
/* Grid (uma linha): */
<div class="grid place-items-center h-screen">
<div>Centrado</div>
</div>
/* Absolute + translate: */
<div class="relative h-64">
<div class="absolute top-1/2 left-1/2
-translate-x-1/2 -translate-y-1/2">
Centrado
</div>
</div>Três formas de centrar: 1) flex items-center justify-center — o mais usado, precisa de altura no pai (h-screen, h-full). 2) grid place-items-center — uma linha, mais conciso. 3) absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 — para overlays e modais. O padrão moderno substitui os antigos hacks de margin: auto e transforms.
align-self (um item)
self-auto /* herda do pai (padrão) */ self-start /* topo */ self-center /* centro */ self-end /* fundo */ self-stretch /* esticar */ self-baseline /* linha de base */ /* Botão no fundo de um card: */ <div class="flex flex-col h-full"> <h3>Título</h3> <p class="flex-1">Descrição...</p> <button class="self-end mt-auto">Comprar</button> </div>
self-* sobrepõe o items-* do pai num único item. Mesmos valores: start, center, end, stretch, baseline. Útil quando um item precisa de alinhamento diferente dos irmãos. Exemplo clássico: botão no fundo de um card com self-end mt-auto (empurra para baixo independentemente do conteúdo acima).
flex (shorthand)
flex-1 /* flex: 1 1 0% (cresce igual) */ flex-auto /* flex: 1 1 auto (base no conteúdo) */ flex-initial /* flex: 0 1 auto (padrão) */ flex-none /* flex: none (não cresce/encolhe) */ /* Colunas iguais: */ <div class="flex gap-4"> <div class="flex-1">A (1/3)</div> <div class="flex-1">B (1/3)</div> <div class="flex-1">C (1/3)</div> </div> /* Sidebar fixa + conteúdo flexível: */ <div class="flex"> <aside class="flex-none w-64">Sidebar</aside> <main class="flex-1">Conteúdo</main> </div>
flex-1 = todos crescem igualmente (colunas de largura igual). flex-auto = cresce baseado no tamanho do conteúdo. flex-none = tamanho fixo (não flexível). flex-initial = padrão (encolhe mas não cresce). Use flex-1 para dividir espaço em partes iguais. flex-none + flex-1 = sidebar fixa + conteúdo que preenche o resto.
space-between (legacy)
/* space-x/y adiciona margem entre filhos (exceto 1º) */ space-x-4 /* margin-left nos filhos (exceto 1º) */ space-y-2 /* margin-top nos filhos (exceto 1º) */ space-x-reverse /* HOJE: prefira gap */ <div class="flex gap-4"> ← moderno, simples <div class="flex space-x-4"> ← legacy, seletores complexos /* space-y ainda útil para stacks verticais simples: */ <div class="space-y-4"> <p>Parágrafo 1</p> <p>Parágrafo 2</p> </div>
space-x-*/space-y-* adicionam margem entre filhos (exceto o primeiro) usando seletores > * + *. Hoje, gap-* é preferível: mais simples, funciona em grid, sem seletores complexos. space-y-* ainda é conveniente para stacks verticais simples (parágrafos, listas). Em código novo, use sempre gap.
Grid
Grid básico
<div class="grid grid-cols-3 gap-4"> <div class="bg-gray-100 p-4">1</div> <div class="bg-gray-100 p-4">2</div> <div class="bg-gray-100 p-4">3</div> <div class="bg-gray-100 p-4">4</div> </div> /* Padrão responsivo (cards): */ class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-6" /* 1 col mobile → 2 em sm → 3 em lg → 4 em xl */
grid + grid-cols-* define o número de colunas. gap-4 espaça as células. O padrão responsivo para cards: grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 = 1 coluna no mobile, 2 em tablet, 3 em desktop, 4 em ecrã grande. Mais simples que flex para layouts em grelha regular.
row-span (ocupar linhas)
row-span-1, row-span-2 ... row-span-6 row-span-full /* todas as linhas */ <div class="grid grid-cols-3 grid-rows-3 gap-4"> <div class="row-span-2 bg-blue-100 p-4">Ocupa 2 linhas</div> <div class="bg-gray-100 p-4">Normal</div> <div class="bg-gray-100 p-4">Normal</div> <div class="bg-gray-100 p-4">Normal</div> <div class="bg-gray-100 p-4">Normal</div> </div> /* Mosaico tipo dashboard: */ <div class="col-span-2 row-span-2">Widget grande</div>
row-span-* faz um item ocupar múltiplas linhas. row-span-2 = 2 linhas de altura. row-span-full = todas as linhas. Útil para sidebars, imagens grandes em mosaicos ou widgets de dashboard. Combine com col-span para criar áreas retangulares de qualquer tamanho num grid.
Grid responsivo (padrões)
/* Cards responsivos: */ <div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6"> /* Sidebar + conteúdo: */ <div class="grid grid-cols-1 md:grid-cols-[250px_1fr] gap-8"> <aside>Sidebar</aside> <main>Conteúdo</main> </div> /* Auto-fit (sem breakpoints): */ <div class="grid grid-cols-[repeat(auto-fit,minmax(280px,1fr))] gap-6"> /* Holy grail (header + 3 cols + footer): */ <div class="grid grid-rows-[auto_1fr_auto] h-screen"> <header>Topo</header> <div class="grid grid-cols-[200px_1fr_200px]">...</div> <footer>Rodapé</footer> </div>
Padrões essenciais: grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 para cards responsivos. grid-cols-[250px_1fr] para sidebar fixa + conteúdo flexível. repeat(auto-fit,minmax(280px,1fr)) = grid totalmente responsivo sem media queries. "Holy grail" = grid aninhado com header/footer fixos e 3 colunas. Grid é ideal para layouts bidimensionais.
grid-cols (nº de colunas)
grid-cols-1, grid-cols-2, grid-cols-3 ... grid-cols-12 grid-cols-none /* remove grid */ /* Template arbitrário: */ grid-cols-[200px_1fr] /* sidebar + conteúdo */ grid-cols-[1fr_2fr_1fr] /* 3 colunas proporcionais */ grid-cols-[repeat(auto-fit,minmax(250px,1fr))] /* auto */ /* Responsivo: */ class="grid-cols-2 md:grid-cols-3 lg:grid-cols-6" /* Underscores substituem espaços nos colchetes */
grid-cols-1 a grid-cols-12 para colunas iguais. grid-cols-[200px_1fr] para template custom (sidebar fixa + conteúdo flexível). repeat(auto-fit,minmax(250px,1fr)) = grid responsivo SEM breakpoints (colunas automáticas baseadas no espaço disponível). Use underscores em vez de espaços dentro dos colchetes.
col-start e col-end
col-start-1, col-start-2 ... col-start-13 col-end-1, col-end-2 ... col-end-13 col-auto /* Item da coluna 2 à 4 (2 colunas de largura): */ <div class="col-start-2 col-end-4">Centrado</div> /* Centrar conteúdo num grid de 12: */ <div class="grid grid-cols-12"> <div class="col-start-3 col-span-8">Conteúdo centrado</div> </div> /* Layout assimétrico: */ <div class="col-start-1 col-span-7">Principal</div> <div class="col-start-9 col-span-4">Lateral</div>
col-start-* e col-end-* posicionam itens em linhas específicas do grid. As linhas são numeradas de 1 a N+1 (grid de 12 tem linhas 1-13). col-start-2 col-end-4 = da linha 2 à 4. Útil para layouts assimétricos, centrar conteúdo (col-start-3 col-span-8 num grid de 12) e criar espaços vazios intencionais.
gap e espaçamento
gap-0, gap-1, gap-2, gap-3, gap-4, gap-6, gap-8 gap-x-4 /* só entre colunas (horizontal) */ gap-y-2 /* só entre linhas (vertical) */ <div class="grid grid-cols-3 gap-x-6 gap-y-4"> <div>A</div> <div>B</div> <div>C</div> </div> /* Responsivo: */ class="gap-2 md:gap-6" /* Sem gap (bordas coladas): */ class="grid grid-cols-3 divide-x divide-y"
gap-* define o espaço entre células do grid. gap-x-* = horizontal (entre colunas), gap-y-* = vertical (entre linhas). Substitui o antigo hack de margens negativas. Aceita prefixos responsivos: gap-2 md:gap-6 (mais espaço em desktop). Para grids sem gap mas com separadores, use divide-x divide-y nas células.
grid-rows
grid-rows-1, grid-rows-2 ... grid-rows-6 grid-rows-none /* Template arbitrário: */ grid-rows-[auto_1fr_auto] grid-rows-[200px_minmax(100px,1fr)] /* Layout full-height (header + main + footer): */ <div class="grid grid-rows-[auto_1fr_auto] h-screen"> <header class="bg-gray-100 p-4">Topo</header> <main class="p-8 overflow-y-auto">Conteúdo (estica)</main> <footer class="bg-gray-100 p-4">Rodapé</footer> </div>
grid-rows-* define o número de linhas. grid-rows-[auto_1fr_auto] = layout clássico: header com altura automática, main que estica (1fr), footer automático. 1fr = fração do espaço disponível. Combine com h-screen para layout full-height sem scroll na página (o scroll fica só no main com overflow-y-auto).
place-items e place-content
/* Alinhar itens dentro das células: */ place-items-center /* centro nos 2 eixos */ place-items-start place-items-end place-items-stretch /* padrão */ /* Alinhar o grid inteiro no container: */ place-content-center place-content-between place-content-around /* Centragem perfeita em grid: */ <div class="grid place-items-center h-64"> <div>Centrado na célula</div> </div> /* Ícone centrado em célula quadrada: */ <div class="grid place-items-center size-12 bg-gray-100 rounded-lg"> <svg class="size-6">...</svg> </div>
place-items-* alinha o conteúdo dentro de cada célula (atalho para items-* + justify-items-*). place-content-* alinha o grid inteiro no container. place-items-center = centragem perfeita em grid (uma linha). Útil para ícones em células quadradas, avatares em células de tabela, e qualquer centragem simples.
col-span (ocupar colunas)
col-span-1, col-span-2 ... col-span-12 col-span-full /* ocupa TODAS as colunas */ <div class="grid grid-cols-4 gap-4"> <div class="col-span-2 bg-blue-100 p-4">Ocupa 2 colunas</div> <div class="bg-gray-100 p-4">1 col</div> <div class="bg-gray-100 p-4">1 col</div> <div class="col-span-full bg-green-100 p-4">Linha inteira</div> </div> /* Item destacado num grid de cards: */ <div class="col-span-2 row-span-2">Destaque</div>
col-span-* faz um item ocupar múltiplas colunas. col-span-2 = 2 colunas de largura. col-span-full = todas as colunas (linha inteira — útil para headers, banners, separadores). O item "empurra" os seguintes para a posição disponível. Combine com row-span para áreas retangulares grandes (destaques em mosaicos).
auto-flow (densidade)
grid-flow-row /* preenche por linhas (padrão) */ grid-flow-col /* preenche por colunas */ grid-flow-dense /* preenche buracos */ grid-flow-row-dense /* linhas + denso */ grid-flow-col-dense /* colunas + denso */ /* Mosaico sem espaços vazios: */ <div class="grid grid-cols-3 grid-flow-dense gap-4"> <div class="col-span-2">Largo</div> <div>Normal</div> <div>Normal</div> <div>Normal</div> <div>Normal</div> </div>
grid-flow-row (padrão) preenche linha a linha. grid-flow-col preenche coluna a coluna. grid-flow-dense preenche buracos deixados por itens com col-span (reordena visualmente para não deixar espaços vazios). Útil para mosaicos tipo Pinterest, galerias de imagens e dashboards com widgets de tamanhos variados.
Formulários e Inputs
Input de texto
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">
Email
</label>
<input type="email"
class="w-full px-3 py-2 rounded-lg
border border-gray-300 shadow-sm
placeholder:text-gray-400
focus:outline-none focus:ring-2
focus:ring-blue-500 focus:border-blue-500
transition-colors"
placeholder="nome@exemplo.com">
</div>Input completo: w-full px-3 py-2 (tamanho), rounded-lg border border-gray-300 (borda), shadow-sm (profundidade subtil), focus:ring-2 focus:ring-blue-500 (focus acessível), placeholder:text-gray-400 (placeholder subtil). Label com text-sm font-medium text-gray-700. transition-colors suaviza a mudança de estado.
Toggle switch
/* Toggle com peer (sem JS): */
<label class="relative inline-flex items-center cursor-pointer">
<input type="checkbox" class="peer sr-only">
<div class="w-11 h-6 bg-gray-300 rounded-full
peer-checked:bg-blue-600
peer-focus:ring-2 peer-focus:ring-blue-300
after:content-[''] after:absolute after:top-0.5
after:left-0.5 after:bg-white after:rounded-full
after:h-5 after:w-5 after:transition-all
peer-checked:after:translate-x-5
transition-colors"></div>
</label>
/* peer-checked: muda o estilo quando marcado */Toggle switch sem JavaScript: peer sr-only no checkbox (oculto mas acessível) + peer-checked:bg-blue-600 no visual (muda a cor quando marcado). O "botão" usa after:content-[''] com after:translate-x-5 no checked para deslizar. sr-only mantém o input acessível a leitores de ecrã. transition-colors suaviza.
Input disabled e readonly
/* Disabled: */
<input disabled
class="w-full px-3 py-2 rounded-lg border border-gray-200
bg-gray-100 text-gray-500 cursor-not-allowed
placeholder:text-gray-400"
placeholder="Campo desativado">
/* Readonly: */
<input readonly
class="w-full px-3 py-2 rounded-lg border border-gray-200
bg-gray-50 text-gray-600 cursor-default"
value="Não editável">
/* Estados via variante disabled: */
class="disabled:opacity-50 disabled:cursor-not-allowed
disabled:bg-gray-100"Disabled: bg-gray-100 text-gray-500 cursor-not-allowed (visual desativado). Readonly: bg-gray-50 text-gray-600 cursor-default (visual ligeiramente diferente). Use a variante disabled: para estilizar estados: disabled:opacity-50 disabled:cursor-not-allowed. A diferença: disabled não envia o valor; readonly envia mas não edita.
Validação visual (peer)
/* Input com validação via peer: */
<div>
<input type="email"
class="peer w-full px-3 py-2 rounded-lg border
border-gray-300
focus:ring-2 focus:ring-blue-500
invalid:border-red-500 invalid:ring-red-500"
required>
<p class="hidden peer-invalid:block mt-1
text-sm text-red-600">
Email inválido
</p>
<p class="hidden peer-valid:block mt-1
text-sm text-green-600">
✓ Email válido
</p>
</div>Validação visual com peer: invalid:border-red-500 no input (borda vermelha quando inválido). Mensagens: hidden peer-invalid:block (mostra só quando inválido) e hidden peer-valid:block (mostra só quando válido). Usa a validação nativa do HTML5 (required, type="email"). Sem JavaScript — o browser valida automaticamente.
Input com erro
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">
Password
</label>
<input type="password"
class="w-full px-3 py-2 rounded-lg
border border-red-500 ring-1 ring-red-500
focus:outline-none focus:ring-2 focus:ring-red-500
placeholder:text-gray-400">
<p class="mt-1 text-sm text-red-600">
A password deve ter pelo menos 8 caracteres.
</p>
</div>
/* Sucesso: border-green-500 + text-green-600 */Estado de erro: border-red-500 ring-1 ring-red-500 (borda vermelha com anel). Mensagem: text-sm text-red-600 mt-1. Para sucesso: border-green-500 + mensagem text-green-600. O ring-1 reforça a indicação visual. Sempre associe a mensagem ao input com aria-describedby para acessibilidade.
Textarea
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">
Mensagem
</label>
<textarea rows="4"
class="w-full px-3 py-2 rounded-lg
border border-gray-300 shadow-sm
placeholder:text-gray-400
focus:outline-none focus:ring-2
focus:ring-blue-500 focus:border-blue-500
resize-y transition-colors"
placeholder="Escreva a sua mensagem..."></textarea>
<p class="mt-1 text-xs text-gray-500">Máx. 500 caracteres</p>
</div>Textarea: mesmas classes do input + rows="4" (altura inicial) + resize-y (permite resize vertical, não horizontal). resize-none para desativar resize completamente. Texto de ajuda: text-xs text-gray-500 mt-1. Para textareas maiores, use min-h-[120px]. O padrão de foco é idêntico ao input: focus:ring-2 focus:ring-blue-500.
File input
/* File input simples: */
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">
Ficheiro
</label>
<input type="file"
class="block w-full text-sm text-gray-500
file:mr-4 file:py-2 file:px-4
file:rounded-lg file:border-0
file:text-sm file:font-medium
file:bg-blue-50 file:text-blue-700
hover:file:bg-blue-100
file:cursor-pointer cursor-pointer">
</div>
/* file: é a variante para o botão interno */File input estilizado: a variante file: estiliza o botão interno do input. file:py-2 file:px-4 file:rounded-lg (tamanho do botão), file:bg-blue-50 file:text-blue-700 (cores), hover:file:bg-blue-100 (hover). O texto do input: text-sm text-gray-500. file:border-0 remove a borda do botão. file:cursor-pointer para o cursor.
Select
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">
País
</label>
<select
class="w-full px-3 py-2 rounded-lg
border border-gray-300 shadow-sm
bg-white text-gray-900
focus:outline-none focus:ring-2
focus:ring-blue-500 focus:border-blue-500
appearance-none
bg-[url('data:image/svg+xml,...')] bg-no-repeat
bg-[right_0.75rem_center] bg-[length:1rem]">
<option>Portugal</option>
<option>Brasil</option>
</select>
</div>Select estilizado: mesmas classes do input + appearance-none (remove a seta padrão do browser) + ícone custom via bg-[url(...)] posicionado com bg-[right_0.75rem_center]. bg-white garante fundo consistente. Para uma solução mais simples, use o plugin @tailwindcss/forms que estiliza selects automaticamente com um reset consistente.
Input group (prefixo/sufixo)
/* Com prefixo: */
<div class="flex">
<span class="inline-flex items-center px-3
rounded-l-lg border border-r-0 border-gray-300
bg-gray-50 text-gray-500 text-sm">
https://
</span>
<input class="flex-1 px-3 py-2 rounded-r-lg
border border-gray-300 focus:ring-2
focus:ring-blue-500 focus:border-blue-500"
placeholder="exemplo.com">
</div>
/* Com ícone dentro: */
<div class="relative">
<svg class="absolute left-3 top-1/2 -translate-y-1/2 size-5 text-gray-400">🔍</svg>
<input class="w-full pl-10 pr-4 py-2 rounded-lg border">
</div>Input group: prefixo com rounded-l-lg border-r-0 bg-gray-50 + input com rounded-r-lg flex-1 (bordas coladas). Para ícone dentro do input: relative no pai + absolute left-3 top-1/2 -translate-y-1/2 no ícone + pl-10 no input (padding para não sobrepor o ícone). Padrão comum em campos de pesquisa e URLs.
Plugin @tailwindcss/forms
/* Instalação: */
npm install -D @tailwindcss/forms
/* v3 (config): */
plugins: [require('@tailwindcss/forms')]
/* v4 (CSS): */
@plugin "@tailwindcss/forms";
/* O plugin aplica um reset consistente a: */
input, select, textarea, checkbox, radio
/* Antes: estilos inconsistentes entre browsers */
/* Depois: base limpa e previsível */
/* Uso normal com classes Tailwind: */
<input class="rounded-lg border-gray-300
focus:ring-blue-500 focus:border-blue-500">O plugin @tailwindcss/forms aplica um reset consistente a todos os elementos de formulário (inputs, selects, textareas, checkboxes, radios). Remove estilos inconsistentes entre browsers e fornece uma base limpa. Depois, estilize com classes Tailwind normais. Altamente recomendado em qualquer projeto com formulários. No v4, use @plugin no CSS.
Checkbox e radio
/* Checkbox custom: */
<label class="flex items-center gap-3 cursor-pointer">
<input type="checkbox"
class="size-4 rounded border-gray-300
text-blue-600 focus:ring-blue-500
focus:ring-offset-0 cursor-pointer">
<span class="text-sm text-gray-700">Aceito os termos</span>
</label>
/* Radio: */
<label class="flex items-center gap-3 cursor-pointer">
<input type="radio" name="opcao"
class="size-4 border-gray-300
text-blue-600 focus:ring-blue-500 cursor-pointer">
<span class="text-sm text-gray-700">Opção A</span>
</label>Checkbox/radio com Tailwind: size-4 (tamanho), rounded (checkbox) ou sem rounded (radio), border-gray-300 (borda), text-blue-600 (cor quando marcado), focus:ring-blue-500 (focus). cursor-pointer no label para indicar clicável. O plugin @tailwindcss/forms melhora o reset. gap-3 espaça o input do texto.
Formulário completo
<form class="space-y-6 max-w-md">
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">Nome</label>
<input class="w-full px-3 py-2 rounded-lg border border-gray-300
focus:ring-2 focus:ring-blue-500 focus:border-blue-500">
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">Email</label>
<input type="email" class="w-full px-3 py-2 rounded-lg border
border-gray-300 focus:ring-2 focus:ring-blue-500">
</div>
<div class="flex items-center gap-2">
<input type="checkbox" class="size-4 rounded text-blue-600">
<label class="text-sm text-gray-600">Lembrar-me</label>
</div>
<button class="w-full py-2.5 bg-blue-600 text-white rounded-lg
font-medium hover:bg-blue-700 transition-colors">
Entrar
</button>
</form>Formulário completo: space-y-6 espaça os campos. Cada campo: label (text-sm font-medium) + input (w-full px-3 py-2 rounded-lg border). Checkbox com flex items-center gap-2. Botão full-width: w-full py-2.5 bg-blue-600 rounded-lg font-medium. max-w-md limita a largura para legibilidade. Padrão universal de formulários.
Label flutuante
/* Label que sobe ao focar (com peer): */
<div class="relative">
<input type="text" id="nome" placeholder=" "
class="peer w-full px-3 pt-5 pb-2 rounded-lg
border border-gray-300
focus:ring-2 focus:ring-blue-500">
<label for="nome"
class="absolute left-3 top-3.5 text-gray-500
transition-all duration-200
peer-focus:top-1.5 peer-focus:text-xs
peer-focus:text-blue-600
peer-[:not(:placeholder-shown)]:top-1.5
peer-[:not(:placeholder-shown)]:text-xs">
Nome
</label>
</div>Label flutuante: peer no input + peer-focus:top-1.5 peer-focus:text-xs no label (sobe e encolhe ao focar). peer-[:not(:placeholder-shown)]: mantém o label em cima quando tem conteúdo. placeholder=" " (espaço) é necessário para o seletor funcionar. pt-5 pb-2 dá espaço para o label. transition-all suaviza a animação.
Componentes Práticos
Botão reutilizável
<button class="inline-flex items-center gap-2 px-5 py-2.5 rounded-lg bg-blue-600 text-white font-medium hover:bg-blue-700 active:bg-blue-800 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 disabled:opacity-50 disabled:pointer-events-none transition-colors duration-200"> <svg class="size-5">...</svg> Clique aqui </button> /* Variantes: outline, ghost, danger */ class="border-2 border-blue-600 text-blue-600 hover:bg-blue-50" /* outline */
Botão completo: inline-flex items-center gap-2 (ícone + texto alinhados), px-5 py-2.5 (padding), rounded-lg (cantos), estados hover/active/focus/disabled, transition-colors (suave). focus:ring-offset-2 para acessibilidade visível. Variantes: outline (border-2), ghost (hover:bg-gray-100), danger (bg-red-600).
Skeleton loading
<div class="animate-pulse space-y-4">
<div class="h-48 bg-gray-200 rounded-lg"></div>
<div class="space-y-2">
<div class="h-4 bg-gray-200 rounded w-3/4"></div>
<div class="h-4 bg-gray-200 rounded w-1/2"></div>
<div class="h-4 bg-gray-200 rounded w-5/6"></div>
</div>
<div class="flex gap-3">
<div class="size-10 bg-gray-200 rounded-full"></div>
<div class="h-4 bg-gray-200 rounded w-24 self-center"></div>
</div>
</div>Skeleton: animate-pulse + blocos bg-gray-200 rounded com alturas/larguras variadas. h-4 w-3/4 simula linhas de texto. size-10 rounded-full simula avatar. space-y-* espaça os blocos. Substitua pelo conteúdo real quando carregar (via JS/framework). Padrão essencial para UX de loading — mostra a estrutura enquanto os dados não chegam.
Alert / Toast
/* Alert (inline): */ <div class="flex items-center gap-3 p-4 rounded-lg bg-green-50 border border-green-200"> <svg class="size-5 text-green-600 shrink-0">✓</svg> <p class="text-sm text-green-800">Operação realizada!</p> </div> /* Toast (fixo no canto): */ <div class="fixed bottom-4 right-4 z-50 flex items-center gap-3 px-4 py-3 bg-gray-900 text-white rounded-lg shadow-xl animate-in slide-in-from-bottom"> <span>Mensagem guardada</span> <button class="text-gray-400 hover:text-white">×</button> </div>
Alert inline: flex items-center gap-3 p-4 rounded-lg + cores semânticas (bg-green-50 border-green-200). Ícone com shrink-0 (não encolhe). Toast: fixed bottom-4 right-4 z-50 (canto inferior direito), bg-gray-900 text-white shadow-xl (escuro, destaque). Botão de fechar: text-gray-400 hover:text-white. Use animate-in para entrada suave.
Avatar group
/* Grupo de avatares sobrepostos: */
<div class="flex -space-x-3">
<img class="size-10 rounded-full ring-2 ring-white
object-cover" src="a1.jpg">
<img class="size-10 rounded-full ring-2 ring-white
object-cover" src="a2.jpg">
<img class="size-10 rounded-full ring-2 ring-white
object-cover" src="a3.jpg">
<span class="size-10 rounded-full ring-2 ring-white
bg-gray-200 flex items-center justify-center
text-xs font-medium text-gray-600">
+5
</span>
</div>
/* -space-x-3 sobrepõe; ring-2 ring-white separa */Avatar group: flex -space-x-3 sobrepõe os avatares (margem negativa). ring-2 ring-white cria separação branca entre eles. size-10 rounded-full object-cover para avatares circulares uniformes. Contador: bg-gray-200 flex items-center justify-center text-xs (círculo cinzento com "+5"). Popular em listas de membros, comentários e atividade de equipa.
Card com hover
<div class="group max-w-sm rounded-xl overflow-hidden
bg-white shadow-md hover:shadow-xl
transition-shadow duration-300">
<div class="overflow-hidden">
<img src="foto.jpg" alt=""
class="w-full h-48 object-cover
group-hover:scale-105 transition-transform duration-300">
</div>
<div class="p-6">
<h3 class="font-semibold text-lg
group-hover:text-blue-600 transition-colors">
Título
</h3>
<p class="mt-2 text-gray-600 text-sm">Descrição...</p>
</div>
</div>Card com efeitos: hover:shadow-xl (elevação), group-hover:scale-105 (zoom na imagem), group-hover:text-blue-600 (cor no título). overflow-hidden no contentor da imagem + rounded-xl para cantos arredondados. transition-* suaviza tudo. group propaga o hover do card para os filhos. Padrão essencial para listas de produtos, blog posts e portfolios.
Modal / Dialog
<div class="fixed inset-0 z-50 flex items-center
justify-center p-4">
<!-- Overlay -->
<div class="absolute inset-0 bg-black/50
backdrop-blur-sm"></div>
<!-- Dialog -->
<div class="relative bg-white rounded-2xl shadow-xl
w-full max-w-md p-6 z-10">
<h2 class="text-lg font-semibold">Título</h2>
<p class="mt-2 text-gray-600">Conteúdo do modal...</p>
<div class="mt-6 flex justify-end gap-3">
<button class="px-4 py-2 text-gray-700
hover:bg-gray-100 rounded-lg">Cancelar</button>
<button class="px-4 py-2 bg-blue-600 text-white
rounded-lg hover:bg-blue-700">Confirmar</button>
</div>
</div>
</div>Modal: fixed inset-0 z-50 (overlay full-screen), bg-black/50 backdrop-blur-sm (fundo escuro fosco), flex items-center justify-center (centra o dialog). Dialog: relative bg-white rounded-2xl shadow-xl max-w-md. z-10 acima do overlay. Botões: flex justify-end gap-3. Use <dialog> nativo ou Headless UI para acessibilidade completa.
Tabela responsiva
<div class="overflow-x-auto rounded-lg border border-gray-200">
<table class="w-full text-sm text-left">
<thead class="bg-gray-50 text-gray-600 uppercase text-xs">
<tr>
<th class="px-4 py-3 font-medium">Nome</th>
<th class="px-4 py-3 font-medium">Email</th>
<th class="px-4 py-3 font-medium">Estado</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-200">
<tr class="hover:bg-gray-50 transition-colors">
<td class="px-4 py-3 font-medium">João</td>
<td class="px-4 py-3 text-gray-600">joao@mail.com</td>
<td class="px-4 py-3">
<span class="px-2 py-1 bg-green-100 text-green-800
rounded-full text-xs">Ativo</span>
</td>
</tr>
</tbody>
</table>
</div>Tabela: overflow-x-auto no pai (scroll horizontal em mobile). w-full text-sm text-left na tabela. Header: bg-gray-50 uppercase text-xs. Linhas: divide-y divide-gray-200 (separadores). Hover: hover:bg-gray-50. Badge de estado com cores semânticas. px-4 py-3 para padding consistente. Essencial para dashboards e listagens.
Breadcrumb
<nav class="flex items-center gap-2 text-sm text-gray-500">
<a href="/" class="hover:text-gray-900 transition-colors">Início</a>
<span class="text-gray-300">/</span>
<a href="/produtos" class="hover:text-gray-900">Produtos</a>
<span class="text-gray-300">/</span>
<span class="text-gray-900 font-medium" aria-current="page">
Detalhe
</span>
</nav>
/* Com ícone de seta: */
<svg class="size-4 text-gray-400">›</svg>
/* Separador com slash, seta ou ícone */Breadcrumb: flex items-center gap-2 text-sm (linha horizontal). Links: text-gray-500 hover:text-gray-900 (cinzento, escurece no hover). Página atual: text-gray-900 font-medium + aria-current="page" (acessibilidade). Separador: text-gray-300 (slash, seta ou ícone). Essencial para navegação hierárquica (e-commerce, documentação, dashboards).
Navbar responsiva
<nav class="sticky top-0 z-50 bg-white/80
backdrop-blur-md border-b border-gray-200">
<div class="container mx-auto px-4 h-16
flex items-center justify-between">
<a href="/" class="text-xl font-bold">Logo</a>
<div class="hidden md:flex items-center gap-6">
<a href="#" class="text-gray-600 hover:text-gray-900
transition-colors">Início</a>
<a href="#" class="text-gray-600 hover:text-gray-900">Sobre</a>
<button class="px-4 py-2 bg-blue-600 text-white
rounded-lg text-sm font-medium hover:bg-blue-700">
Entrar
</button>
</div>
<button class="md:hidden text-2xl">☰</button>
</div>
</nav>Navbar moderna: sticky top-0 z-50 (fixa ao scroll), bg-white/80 backdrop-blur-md (vidro fosco), flex items-center justify-between (logo + menu nas extremidades). Links hidden md:flex (desktop), botão md:hidden (mobile). h-16 para altura consistente. container mx-auto px-4 limita a largura. Padrão universal de navegação.
Dropdown menu
<div class="relative inline-block">
<button class="px-4 py-2 border rounded-lg">Opções ▼</button>
<!-- Menu (oculto por padrão, mostrar via JS) -->
<div class="absolute right-0 mt-2 w-48
bg-white rounded-lg shadow-lg border border-gray-200
py-1 z-10">
<a href="#" class="block px-4 py-2 text-sm text-gray-700
hover:bg-gray-100 transition-colors">Perfil</a>
<a href="#" class="block px-4 py-2 text-sm text-gray-700
hover:bg-gray-100">Definições</a>
<hr class="my-1 border-gray-200">
<a href="#" class="block px-4 py-2 text-sm text-red-600
hover:bg-red-50">Sair</a>
</div>
</div>Dropdown: relative no pai + absolute right-0 mt-2 no menu (posicionado abaixo, alinhado à direita). w-48 bg-white rounded-lg shadow-lg border (visual). Itens: block px-4 py-2 text-sm hover:bg-gray-100. Separador: hr border-gray-200. Item perigoso: text-red-600 hover:bg-red-50. z-10 acima do conteúdo. Mostre/oculte via JS ou data-[state=open]:block.
Hero section
<section class="relative bg-gradient-to-br from-blue-600
to-purple-700 text-white py-20 md:py-32">
<div class="container mx-auto px-4 text-center">
<h1 class="text-4xl md:text-6xl font-bold
leading-tight max-w-3xl mx-auto">
Construa algo incrível
</h1>
<p class="mt-6 text-lg md:text-xl text-blue-100
max-w-2xl mx-auto">
Descrição do produto ou serviço em poucas palavras.
</p>
<div class="mt-10 flex flex-col sm:flex-row
gap-4 justify-center">
<a href="#" class="px-8 py-3 bg-white text-blue-700
rounded-lg font-semibold hover:bg-blue-50">Começar</a>
<a href="#" class="px-8 py-3 border-2 border-white/50
rounded-lg font-semibold hover:bg-white/10">Saber mais</a>
</div>
</div>
</section>Hero section: bg-gradient-to-br from-blue-600 to-purple-700 (fundo gradiente), py-20 md:py-32 (espaço vertical generoso). Título: text-4xl md:text-6xl font-bold max-w-3xl mx-auto (grande, centrado, limitado). Botões: flex flex-col sm:flex-row gap-4 justify-center (empilha no mobile). CTA primário: fundo branco; secundário: border-2 border-white/50.
Tabs / Separadores
<div class="border-b border-gray-200">
<nav class="flex gap-6 -mb-px">
<button class="pb-3 px-1 border-b-2 border-blue-600
text-blue-600 font-medium text-sm">
Ativo
</button>
<button class="pb-3 px-1 border-b-2 border-transparent
text-gray-500 hover:text-gray-700
hover:border-gray-300 text-sm transition-colors">
Inativo
</button>
</nav>
</div>
/* Conteúdo abaixo: */
<div class="py-4">Conteúdo do tab ativo</div>Tabs: border-b border-gray-200 no contentor (linha base). Tab ativo: border-b-2 border-blue-600 text-blue-600 font-medium (sublinhado azul). Inativo: border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300. -mb-px sobrepõe a borda base. pb-3 px-1 para padding. Mostre/oculte conteúdo via JS ou hidden.
Badge e tag
/* Badge simples: */ <span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-green-100 text-green-800"> Ativo </span> /* Com ponto de estado: */ <span class="inline-flex items-center gap-1.5 px-3 py-1 rounded-full text-sm bg-blue-50 text-blue-700"> <span class="size-2 rounded-full bg-blue-500"></span> Online </span> /* Removível (com hover): */ <span class="group inline-flex items-center gap-1 px-3 py-1 rounded-full bg-gray-100 text-sm"> Tag <button class="group-hover:text-red-600">×</button> </span>
Badge: inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium + cores semânticas (bg-green-100 text-green-800). Ponto de estado: size-2 rounded-full bg-blue-500. Cores subtis (fundo 50/100, texto 700/800) para contraste legível sem ser agressivo. Removível: group + group-hover:text-red-600 no botão ×.
Tooltip
/* Tooltip com group (CSS only): */
<div class="relative group inline-block">
<button class="px-4 py-2 bg-gray-100 rounded-lg">
Hover aqui
</button>
<div class="absolute bottom-full left-1/2 -translate-x-1/2
mb-2 px-3 py-1.5 bg-gray-900 text-white text-xs
rounded-lg opacity-0 group-hover:opacity-100
transition-opacity pointer-events-none
whitespace-nowrap">
Texto do tooltip
<div class="absolute top-full left-1/2 -translate-x-1/2
border-4 border-transparent border-t-gray-900"></div>
</div>
</div>Tooltip CSS-only: group no pai + opacity-0 group-hover:opacity-100 no tooltip (aparece no hover). Posição: absolute bottom-full left-1/2 -translate-x-1/2 mb-2 (acima, centrado). pointer-events-none para não interferir com o rato. Seta: border-4 border-transparent border-t-gray-900. whitespace-nowrap impede quebra. Para produção, use Headless UI ou Radix.
Footer
<footer class="bg-gray-900 text-gray-400 py-12">
<div class="container mx-auto px-4
grid grid-cols-1 md:grid-cols-4 gap-8">
<div>
<h3 class="text-white font-semibold mb-4">Logo</h3>
<p class="text-sm">Descrição da empresa...</p>
</div>
<div>
<h4 class="text-white font-medium mb-3 text-sm
uppercase tracking-wide">Produto</h4>
<ul class="space-y-2 text-sm">
<li><a href="#" class="hover:text-white transition-colors">Funcionalidades</a></li>
<li><a href="#" class="hover:text-white">Preços</a></li>
</ul>
</div>
</div>
<div class="container mx-auto px-4 mt-8 pt-8
border-t border-gray-800 text-sm text-center">
© 2024 Empresa
</div>
</footer>Footer: bg-gray-900 text-gray-400 py-12 (fundo escuro). Grid de colunas: grid-cols-1 md:grid-cols-4 gap-8. Títulos: text-white font-medium uppercase tracking-wide text-sm. Links: hover:text-white transition-colors. Separador: border-t border-gray-800 mt-8 pt-8. Copyright centrado. Padrão universal de rodapé com múltiplas colunas de links.
Progress bar
/* Barra de progresso: */
<div class="w-full bg-gray-200 rounded-full h-2.5">
<div class="bg-blue-600 h-2.5 rounded-full transition-all
duration-500" style="width: 65%"></div>
</div>
/* Com label: */
<div class="flex justify-between text-sm mb-1">
<span class="font-medium text-gray-700">Progresso</span>
<span class="text-gray-500">65%</span>
</div>
/* Step progress: */
<div class="flex items-center gap-2">
<div class="size-8 rounded-full bg-blue-600 text-white
flex items-center justify-center text-sm">1</div>
<div class="flex-1 h-1 bg-blue-600"></div>
<div class="size-8 rounded-full bg-gray-200 text-gray-500
flex items-center justify-center text-sm">2</div>
</div>Progress bar: w-full bg-gray-200 rounded-full h-2.5 (track) + bg-blue-600 h-2.5 rounded-full (fill com style="width: 65%"). transition-all duration-500 anima a mudança. Label: flex justify-between text-sm. Step progress: círculos numerados (size-8 rounded-full) + linhas conectoras (flex-1 h-1). Essencial para wizards e uploads.