DevTools

Cheatsheet Tailwind CSS

Framework CSS utility-first

Voltar às linguagens
Tailwind CSS
154 cards encontrados
Categorias:
Versões:

Instalação e Configuração


14 cards
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-marcabg-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


14 cards
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


12 cards
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


14 cards
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


12 cards
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


12 cards
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


13 cards
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


10 cards
@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


14 cards
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


10 cards
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


13 cards
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


16 cards
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.