Capítulo 8 — Layout com Flexbox¶
Vídeo curto explicativo (link será adicionado posteriormente)
8.1 — O que é Flexbox e quando usar¶
Vídeo curto explicativo (link será adicionado posteriormente)
O Flexbox (Flexible Box Layout Module) é um modelo de layout CSS projetado para distribuir espaço e alinhar elementos em uma dimensão — uma linha ou uma coluna. Introduzido como recomendação pelo W3C em 2012 e amplamente suportado desde 2015, o Flexbox resolveu um problema que afligia desenvolvedores web há quase duas décadas: a ausência de um mecanismo declarativo e previsível para alinhar e distribuir elementos em um container.
8.1.1 — O problema que o Flexbox resolve¶
Antes do Flexbox, criar layouts que pareciam simples — centralizar verticalmente um elemento, fazer colunas de altura igual, distribuir itens uniformemente em uma barra de navegação — exigia combinações frágeis e contraintuitivas de propriedades CSS que não foram projetadas para layout:
/* Era do pré-Flexbox: hacks para centralização vertical */
/* Hack 1: tabela (semanticamente incorreto) */
.container { display: table; }
.filho { display: table-cell; vertical-align: middle; }
/* Hack 2: posicionamento absoluto (inflexível) */
.filho {
position: absolute;
top: 50%;
left: 50%;
margin-top: -50px; /* metade da altura — valor hardcoded */
margin-left: -100px; /* metade da largura — valor hardcoded */
}
/* Hack 3: floats (requer clearfix, quebra o fluxo) */
.coluna { float: left; width: 33.33%; }
.container::after { content: ""; display: table; clear: both; }
Esses padrões funcionavam em casos específicos, mas quebravam ao mudar o tamanho do container, adicionar conteúdo dinâmico ou adaptar para diferentes viewports. O Flexbox substituiu todos esses hacks por um modelo coerente e expressivo:
/* Flexbox: centralização vertical e horizontal em duas linhas */
.container {
display: flex;
justify-content: center;
align-items: center;
}
8.1.2 — Conceito de container e itens¶
O Flexbox opera em dois níveis hierárquicos:
- Flex container: o elemento ao qual
display: flexé aplicado. Ele define o contexto flex e controla como seus filhos diretos são distribuídos. - Flex items: os filhos diretos do flex container. Eles são os elementos que recebem e respondem às regras de layout flex.
<nav class="navbar"> <!-- flex container -->
<a href="/">Logo</a> <!-- flex item -->
<a href="/sobre">Sobre</a> <!-- flex item -->
<a href="/contato">Contato</a> <!-- flex item -->
</nav>
.navbar {
display: flex; /* transforma .navbar em flex container */
/* Os filhos diretos (<a>) tornam-se automaticamente flex items */
}
Ponto crítico: apenas os filhos diretos do container se tornam flex items. Descendentes mais profundos não são afetados diretamente pelo contexto flex do container pai — a menos que eles próprios também sejam declarados como flex containers.
8.1.3 — Quando usar Flexbox vs Grid¶
Flexbox e Grid são complementares, não concorrentes. A escolha entre eles segue um princípio simples:
| Flexbox | Grid | |
|---|---|---|
| Dimensionalidade | Uma dimensão (linha ou coluna) | Duas dimensões (linhas e colunas) |
| Controle | A partir do conteúdo (content-first) | A partir do layout (layout-first) |
| Melhor para | Componentes: navbars, cards, forms, botões | Estruturas de página: grids de conteúdo, layouts completos |
A heurística prática: se você está distribuindo itens em uma única direção — uma linha de botões, uma lista de cards, uma barra de navegação —, Flexbox é a escolha natural. Se você precisa alinhar elementos em linhas e colunas simultaneamente — uma grade de artigos, um layout de página com header/sidebar/main/footer —, Grid é mais adequado. Na prática, a maioria dos projetos usa ambos: Grid para a estrutura macro da página, Flexbox para os componentes internos.
Referência: MDN — Flexbox
8.2 — Os dois eixos do Flexbox¶
Vídeo curto explicativo (link será adicionado posteriormente)
O modelo mental mais importante para dominar o Flexbox é a compreensão dos dois eixos que governam todo o sistema de alinhamento.
8.2.1 — Eixo principal (main axis)¶
O eixo principal é a direção ao longo da qual os flex items são distribuídos. Por padrão, ele corre horizontalmente da esquerda para a direita. As propriedades de alinhamento que atuam sobre o eixo principal são justify-content (no container) e justify-self (nos itens, com suporte limitado no Flexbox).
Eixo principal padrão (flex-direction: row):
←────────────────────────────────────────→
[ Item 1 ] [ Item 2 ] [ Item 3 ]
8.2.2 — Eixo cruzado (cross axis)¶
O eixo cruzado é sempre perpendicular ao eixo principal. Por padrão, ele corre verticalmente de cima para baixo. As propriedades que atuam sobre o eixo cruzado são align-items e align-content (no container) e align-self (nos itens).
Eixo cruzado padrão (flex-direction: row):
↑
│ [ Item 1 ] [ Item 2 ] [ Item 3 ]
│
↓
8.2.3 — Como flex-direction muda os eixos¶
A propriedade flex-direction define a direção do eixo principal — e consequentemente do eixo cruzado. Esta é a propriedade mais fundamental do Flexbox, pois redefine o significado de todas as outras propriedades de alinhamento:
/* row (padrão): eixo principal → horizontal (esquerda para direita) */
.container { flex-direction: row; }
/* row-reverse: eixo principal → horizontal (direita para esquerda) */
.container { flex-direction: row-reverse; }
/* column: eixo principal → vertical (cima para baixo) */
.container { flex-direction: column; }
/* column-reverse: eixo principal → vertical (baixo para cima) */
.container { flex-direction: column-reverse; }
flex-direction: row flex-direction: column
──────────────────── ─────────────────────
→ [1] [2] [3] ↓ [1]
eixo principal: → [2]
eixo cruzado: ↓ [3]
eixo principal: ↓
eixo cruzado: →
Imagem sugerida: diagrama visual dos quatro valores de
flex-directionmostrando a orientação dos eixos principal e cruzado em cada caso, com os itens numerados dispostos de acordo.(imagem será adicionada posteriormente)
A compreensão de que justify-content atua sempre sobre o eixo principal e align-items atua sempre sobre o eixo cruzado — independentemente de qual seja qual — é o que permite usar Flexbox com previsibilidade. Muita confusão com Flexbox vem de pensar em termos de "horizontal/vertical" em vez de "eixo principal/cruzado".
8.3 — Propriedades do container flex¶
Vídeo curto explicativo (link será adicionado posteriormente)
8.3.1 — display: flex e display: inline-flex¶
/* flex: o container se comporta como bloco (ocupa toda a largura) */
.container {
display: flex;
}
/* inline-flex: o container se comporta como inline-block */
.badge {
display: inline-flex;
align-items: center;
gap: 0.25rem;
}
A distinção é sobre o comportamento externo do container — como ele se relaciona com o fluxo do documento ao redor. Internamente, os dois se comportam de forma idêntica para os flex items.
8.3.2 — flex-direction¶
Já apresentado na seção 8.2.3. Recapitulando os quatro valores:
.container {
flex-direction: row; /* padrão */
flex-direction: row-reverse;
flex-direction: column;
flex-direction: column-reverse;
}
Caso de uso prático de column: componentes de card com conteúdo empilhado verticalmente, layouts mobile-first que empilham elementos, sidebars de navegação vertical.
8.3.3 — flex-wrap¶
Por padrão, flex items não quebram linha — eles encolhem para caber no container mesmo que isso os torne menores do que seu tamanho ideal. flex-wrap controla esse comportamento:
.container {
flex-wrap: nowrap; /* padrão: todos na mesma linha, encolhem se necessário */
flex-wrap: wrap; /* quebra para a próxima linha quando necessário */
flex-wrap: wrap-reverse; /* quebra para linha acima */
}
flex-wrap: nowrap (padrão):
[ Item 1 ][ Item 2 ][ Item 3 ][ Item 4 ][ Item 5 ]
↑ itens encolhem para caber
flex-wrap: wrap:
[ Item 1 ][ Item 2 ][ Item 3 ]
[ Item 4 ][ Item 5 ]
↑ itens quebram para a próxima linha
flex-wrap: wrap é fundamental para layouts responsivos com Flexbox — permite que itens se reorganizem naturalmente em telas menores sem media queries.
8.3.4 — flex-flow — shorthand¶
flex-flow combina flex-direction e flex-wrap em uma única declaração:
.container {
flex-flow: row wrap; /* direção + quebra */
flex-flow: column nowrap;
flex-flow: row-reverse wrap;
}
8.3.5 — justify-content — alinhamento no eixo principal¶
justify-content define como os flex items são distribuídos ao longo do eixo principal quando há espaço sobrando:
.container {
justify-content: flex-start; /* padrão: itens no início */
justify-content: flex-end; /* itens no final */
justify-content: center; /* itens centralizados */
justify-content: space-between; /* espaço igual ENTRE os itens */
justify-content: space-around; /* espaço igual AO REDOR de cada item */
justify-content: space-evenly; /* espaço igual entre todos, incluindo bordas */
}
justify-content: flex-start
[1][2][3]_ _ _ _ _ _
justify-content: flex-end
_ _ _ _ _ _[1][2][3]
justify-content: center
_ _ _[1][2][3]_ _ _
justify-content: space-between
[1]_ _ _ _[2]_ _ _ _[3]
justify-content: space-around
_ [1] _ _ [2] _ _ [3] _
←→ ←→ ←→
(espaço dobrado entre itens)
justify-content: space-evenly
_ _[1]_ _[2]_ _[3]_ _
←→ ←→ ←→ ←→
(espaço idêntico em todos os gaps)
No DevTools: no painel Elements, ao selecionar um flex container, o Chrome exibe um ícone de grade ao lado de
display: flexna aba Styles. Clicando nele, abre um editor visual interativo de Flexbox que permite testar todos os valores dejustify-contentealign-itemsem tempo real — uma ferramenta essencial para entender o comportamento de cada valor.
8.3.6 — align-items — alinhamento no eixo cruzado¶
align-items define como os flex items são alinhados ao longo do eixo cruzado:
.container {
align-items: stretch; /* padrão: itens se esticam para preencher o container */
align-items: flex-start; /* itens alinhados no início do eixo cruzado */
align-items: flex-end; /* itens alinhados no final do eixo cruzado */
align-items: center; /* itens centralizados no eixo cruzado */
align-items: baseline; /* itens alinhados pela linha de base do texto */
}
align-items: stretch (padrão) align-items: center
┌──────────────────────┐ ┌──────────────────────┐
│ ┌────┐ ┌──────┐ ┌──┐ │ │ ┌────┐ │
│ │ │ │ │ │ │ │ │ │ │ ┌──────┐ │
│ │ 1 │ │ 2 │ │3 │ │ │ │ 1 │ │ 2 │ │
│ │ │ │ │ │ │ │ │ │ │ └──────┘ │
│ └────┘ └──────┘ └──┘ │ │ └────┘ ┌──┐ │
└──────────────────────┘ │ │3 │ │
itens esticam na altura do │ └──┘ │
container └──────────────────────┘
itens centralizados
baseline é especialmente útil quando itens têm fontes de tamanhos diferentes e precisam ser alinhados pelo texto:
.toolbar {
display: flex;
align-items: baseline; /* alinha pelo texto de cada item */
}
8.3.7 — align-content — alinhamento de múltiplas linhas¶
align-content só tem efeito quando flex-wrap: wrap está ativo e há múltiplas linhas de flex items. Ele controla a distribuição das linhas no eixo cruzado — análogo ao justify-content, mas para linhas em vez de itens:
.container {
flex-wrap: wrap;
align-content: flex-start; /* linhas no início */
align-content: flex-end; /* linhas no final */
align-content: center; /* linhas centralizadas */
align-content: space-between; /* espaço igual entre linhas */
align-content: space-around; /* espaço ao redor das linhas */
align-content: stretch; /* padrão: linhas se esticam */
}
Confusão comum:
align-itemsalinha os itens dentro de cada linha;align-contentdistribui as linhas no container. Em containers de linha única,align-contentnão tem efeito.
8.3.8 — gap, row-gap e column-gap¶
A propriedade gap define o espaçamento entre flex items sem usar margins — o que evita o problema clássico de "margem na última coluna":
.container {
display: flex;
gap: 1rem; /* espaçamento igual em todos os eixos */
gap: 1rem 2rem; /* row-gap | column-gap */
row-gap: 1rem; /* apenas entre linhas */
column-gap: 2rem; /* apenas entre colunas */
}
Sem gap (usando margin): Com gap:
[1][margin][2][margin][3][margin] [1][gap][2][gap][3]
↑ ↑
margem indesejada sem margem extra
no último item
gap é a forma recomendada de criar espaçamento em layouts flex modernos — mais semântico e menos propenso a erros do que margins nos itens.
8.4 — Propriedades dos itens flex¶
Vídeo curto explicativo (link será adicionado posteriormente)
As propriedades dos itens controlam como cada flex item individualmente cresce, encolhe e se posiciona dentro do container.
8.4.1 — flex-grow — capacidade de crescimento¶
flex-grow define a proporção na qual um item pode crescer para ocupar o espaço disponível no container. O valor padrão é 0 — os itens não crescem além de seu tamanho base:
/* Três itens: apenas o segundo cresce */
.item-1 { flex-grow: 0; } /* não cresce */
.item-2 { flex-grow: 1; } /* ocupa todo o espaço disponível */
.item-3 { flex-grow: 0; } /* não cresce */
/* Dois itens com crescimento proporcional */
.item-principal { flex-grow: 2; } /* recebe 2/3 do espaço disponível */
.item-lateral { flex-grow: 1; } /* recebe 1/3 do espaço disponível */
Container: 900px | Item 1: 100px base | Item 2: 100px base | Item 3: 100px base
Espaço disponível: 900 - 300 = 600px
flex-grow: 0, 1, 0:
[100px][ 700px (100+600) ][100px]
flex-grow: 1, 1, 1:
[ 300px ][ 300px ][ 300px ]
(600px divididos igualmente entre os três)
8.4.2 — flex-shrink — capacidade de encolhimento¶
flex-shrink define a proporção na qual um item pode encolher quando o espaço é insuficiente. O valor padrão é 1 — todos os itens encolhem proporcionalmente:
.item-fixo { flex-shrink: 0; } /* não encolhe — mantém tamanho base */
.item-flexivel { flex-shrink: 1; } /* encolhe normalmente (padrão) */
.item-rapido { flex-shrink: 3; } /* encolhe 3x mais rápido que os outros */
Caso de uso comum: um ícone ou logo em uma navbar que não deve encolher, enquanto o restante dos itens se adapta:
.navbar-logo {
flex-shrink: 0; /* logo nunca encolhe */
width: 120px;
}
.navbar-links {
flex-shrink: 1; /* links podem encolher */
}
8.4.3 — flex-basis — tamanho base¶
flex-basis define o tamanho inicial de um item antes de flex-grow e flex-shrink serem aplicados. Funciona como width (em flex-direction: row) ou como height (em flex-direction: column):
.item {
flex-basis: auto; /* padrão: usa width/height do item */
flex-basis: 0; /* tamanho inicial zero — cresce a partir do zero */
flex-basis: 200px; /* tamanho base fixo de 200px */
flex-basis: 33.33%; /* tamanho base de 1/3 do container */
}
flex-basis: 0 vs flex-basis: auto: quando flex-basis: 0, o espaço disponível é distribuído proporcionalmente sem considerar o conteúdo dos itens. Com flex-basis: auto, o conteúdo é considerado antes da distribuição.
8.4.4 — flex — shorthand e valores comuns¶
O shorthand flex combina flex-grow, flex-shrink e flex-basis:
.item {
flex: <grow> <shrink> <basis>;
flex: 1; /* flex: 1 1 0% — cresce, encolhe, base zero */
flex: auto; /* flex: 1 1 auto — cresce, encolhe, base automática */
flex: none; /* flex: 0 0 auto — não cresce, não encolhe */
flex: 0 auto; /* flex: 0 1 auto — não cresce, encolhe */
flex: 2 1 300px; /* cresce 2x, encolhe 1x, base 300px */
}
Os valores mais utilizados na prática:
/* flex: 1 — o item mais comum: cresce proporcionalmente */
.coluna { flex: 1; }
/* Colunas com proporções diferentes */
.coluna-principal { flex: 2; } /* ocupa 2/3 */
.coluna-lateral { flex: 1; } /* ocupa 1/3 */
/* flex: none — item com tamanho fixo, não se adapta */
.sidebar-fixa { flex: none; width: 250px; }
/* flex: 0 0 auto — equivalente ao none */
.logo { flex: 0 0 auto; }
Boa prática: prefira o shorthand
flexàs propriedades individuaisflex-grow,flex-shrinkeflex-basis. O shorthand define valores padrão inteligentes para os componentes não especificados — por exemplo,flex: 1defineflex-basis: 0%, que geralmente é o comportamento desejado.
8.4.5 — align-self — alinhamento individual¶
align-self sobrescreve o align-items do container para um item específico. Aceita os mesmos valores de align-items:
.container {
display: flex;
align-items: center; /* todos os itens centralizados por padrão */
}
.item-topo {
align-self: flex-start; /* este item se alinha no topo */
}
.item-base {
align-self: flex-end; /* este item se alinha na base */
}
.item-esticado {
align-self: stretch; /* este item se estica para preencher */
}
8.4.6 — order — reordenação visual¶
order controla a ordem visual dos flex items sem alterar a ordem no HTML. O valor padrão é 0; valores menores aparecem primeiro, valores maiores aparecem depois:
.item-a { order: 2; } /* aparece por último */
.item-b { order: -1; } /* aparece antes de todos (ordem 0) */
.item-c { order: 1; } /* aparece segundo */
/* HTML: A, B, C → Visual: B(-1), A(0→padrão não declarado), C(1), A(2)... */
/* Na prática: B, C, A */
Caso de uso legítimo: reordenar elementos em diferentes breakpoints para responsividade — por exemplo, mover uma barra lateral para antes do conteúdo principal em mobile:
@media (max-width: 768px) {
.sidebar { order: -1; } /* sobe para antes do main em mobile */
.conteudo { order: 1; }
}
⚠️ Atenção crítica — ver seção 8.6:
orderaltera apenas a apresentação visual — a ordem de leitura dos leitores de tela e a navegação por teclado seguem a ordem do DOM. Usarorderpara reordenar conteúdo semanticamente importante cria uma experiência inacessível para usuários de tecnologias assistivas.
8.5 — Padrões práticos de layout com Flexbox¶
Vídeo curto explicativo (link será adicionado posteriormente)
Compreender as propriedades do Flexbox isoladamente não é suficiente — a habilidade real está em combiná-las para resolver problemas concretos de layout. Esta seção apresenta os padrões mais frequentes no desenvolvimento web moderno.
8.5.1 — Navbar responsiva¶
Uma barra de navegação com logo à esquerda e links à direita é um dos layouts mais comuns da Web, e um dos que mais se beneficiam do Flexbox:
<header class="navbar">
<a href="/" class="navbar__logo">
<img src="logo.svg" alt="IFAL" />
</a>
<nav class="navbar__links">
<a href="/">Início</a>
<a href="/cursos">Cursos</a>
<a href="/sobre">Sobre</a>
<a href="/contato">Contato</a>
</nav>
</header>
.navbar {
display: flex;
justify-content: space-between; /* logo esquerda, links direita */
align-items: center; /* centraliza verticalmente */
padding: 1rem 2rem;
background-color: var(--cor-primaria);
}
.navbar__logo img {
height: 40px;
flex-shrink: 0; /* logo não encolhe */
}
.navbar__links {
display: flex; /* os links também são um flex container */
gap: 2rem;
align-items: center;
}
.navbar__links a {
color: white;
text-decoration: none;
font-size: 0.95rem;
}
/* Responsividade: empilha em mobile */
@media (max-width: 768px) {
.navbar {
flex-direction: column;
gap: 1rem;
}
.navbar__links {
gap: 1rem;
}
}
8.5.2 — Centralização perfeita¶
Centralizar um elemento tanto horizontal quanto verticalmente foi historicamente um dos problemas mais difíceis do CSS. Com Flexbox, torna-se trivial:
/* Centralização no container */
.container-centralizado {
display: flex;
justify-content: center; /* eixo principal: horizontal */
align-items: center; /* eixo cruzado: vertical */
min-height: 100vh; /* ou qualquer altura definida */
}
/* Centralização de um único item usando margin: auto */
.item-centralizado {
margin: auto;
/* margin: auto em flex items absorve todo o espaço disponível
em todas as direções — centralizando o item */
}
margin: auto em flex items é uma técnica poderosa e menos conhecida: quando aplicada a um flex item, a margem auto absorve todo o espaço disponível na direção correspondente:
.navbar {
display: flex;
align-items: center;
padding: 0 2rem;
}
.navbar__logo { margin-right: auto; } /* empurra tudo para a direita */
/* Resultado: logo à esquerda, demais itens à direita */
/* sem usar justify-content: space-between */
8.5.3 — Cards em linha com altura igual¶
Um dos problemas clássicos do layout web é garantir que cards em linha tenham a mesma altura, independentemente do tamanho do conteúdo interno:
<section class="cards">
<article class="card">
<img src="img1.jpg" alt="..." />
<div class="card__corpo">
<h2>Título curto</h2>
<p>Descrição breve.</p>
</div>
<footer class="card__rodape">
<a href="#">Saiba mais</a>
</footer>
</article>
<article class="card">
<img src="img2.jpg" alt="..." />
<div class="card__corpo">
<h2>Título mais longo que o anterior</h2>
<p>Descrição bem mais longa que ocupa mais linhas de texto.</p>
</div>
<footer class="card__rodape">
<a href="#">Saiba mais</a>
</footer>
</article>
</section>
/* Container de cards */
.cards {
display: flex;
flex-wrap: wrap;
gap: 1.5rem;
}
/* Cada card: flex container em coluna */
.card {
display: flex;
flex-direction: column; /* empilha conteúdo verticalmente */
flex: 1 1 280px; /* cresce, encolhe, mínimo de 280px */
border-radius: var(--raio-borda);
box-shadow: var(--sombra-md);
overflow: hidden;
}
.card img {
width: 100%;
height: 200px;
object-fit: cover; /* corta a imagem para preencher o espaço */
}
.card__corpo {
flex: 1; /* ocupa todo o espaço disponível — empurra o rodapé para baixo */
padding: 1.5rem;
}
/* O rodapé fica sempre na base do card, independente do conteúdo */
.card__rodape {
padding: 1rem 1.5rem;
border-top: 1px solid #eee;
}
O segredo deste padrão é flex: 1 no .card__corpo: ele faz com que o corpo do card ocupe todo o espaço vertical disponível, independentemente do tamanho do conteúdo — o que empurra o rodapé para a base de todos os cards de forma igual.
8.5.4 — Footer grudado no rodapé (sticky footer)¶
Um problema clássico: o footer deve ficar na base da viewport em páginas com pouco conteúdo, e após o conteúdo em páginas longas:
<body>
<header>...</header>
<main>...</main>
<footer>...</footer>
</body>
body {
display: flex;
flex-direction: column;
min-height: 100vh; /* body ocupa pelo menos toda a altura da tela */
}
main {
flex: 1; /* main cresce para ocupar todo o espaço disponível */
/* header e footer ficam com seu tamanho natural */
/* footer é empurrado para o final */
}
Este é um dos padrões mais elegantes do Flexbox: três linhas de CSS resolvem um problema que antes exigia posicionamento absoluto ou cálculos com calc().
8.5.5 — Layout de formulário com labels e inputs alinhados¶
<form class="formulario">
<div class="campo">
<label for="nome">Nome:</label>
<input type="text" id="nome" name="nome" />
</div>
<div class="campo">
<label for="email">E-mail:</label>
<input type="email" id="email" name="email" />
</div>
<div class="acoes">
<button type="reset">Limpar</button>
<button type="submit">Enviar</button>
</div>
</form>
.formulario {
display: flex;
flex-direction: column;
gap: 1rem;
max-width: 500px;
}
/* Cada campo: label + input lado a lado */
.campo {
display: flex;
align-items: center;
gap: 1rem;
}
.campo label {
flex: 0 0 100px; /* largura fixa: não cresce, não encolhe */
text-align: right;
font-weight: 600;
}
.campo input {
flex: 1; /* input ocupa todo o espaço restante */
padding: 0.5rem;
border: 1px solid #ccc;
border-radius: 4px;
}
/* Botões de ação alinhados à direita */
.acoes {
display: flex;
justify-content: flex-end;
gap: 0.75rem;
}
8.6 — Flexbox e acessibilidade¶
Vídeo curto explicativo (link será adicionado posteriormente)
O Flexbox introduz uma capacidade que, mal utilizada, cria problemas sérios de acessibilidade: a possibilidade de separar a ordem visual dos elementos da sua ordem no DOM.
8.6.1 — A propriedade order e a ordem de leitura¶
A especificação CSS deixa claro: propriedades como order e flex-direction: row-reverse afetam apenas a apresentação visual. A ordem em que os elementos aparecem no DOM continua sendo a ordem utilizada por:
- Leitores de tela (NVDA, JAWS, VoiceOver) ao ler o conteúdo sequencialmente
- Navegação por teclado ao avançar pelo
Tab - Seleção de texto ao arrastar o cursor
- Mecanismos de busca ao indexar o conteúdo
Isso significa que se você usa order para apresentar visualmente o elemento B antes do elemento A, um usuário de leitor de tela ouvirá A antes de B — criando uma experiência desconexada entre o que é visto e o que é ouvido.
/* PROBLEMÁTICO: reordenação que cria desconexão semântica */
.card-destaque { order: -1; } /* aparece visualmente primeiro */
/* mas no DOM ainda é o terceiro elemento — leitor de tela lê por último */
8.6.2 — Reordenação visual vs ordem do DOM¶
A regra é direta: se a ordem visual importa para a compreensão do conteúdo, ela deve ser refletida na ordem do DOM.
order e reordenação por Flexbox são aceitáveis quando:
- A reordenação é puramente estética (ex.: mover um elemento decorativo)
- O conteúdo faz sentido em qualquer ordem (ex.: uma galeria de imagens independentes)
- A reordenação é aplicada apenas para efeitos visuais em viewports específicos onde a lógica de leitura não muda
order e reordenação por Flexbox não são aceitáveis quando:
- A ordem dos elementos é parte do significado do conteúdo (ex.: etapas de um processo, hierarquia de informação)
- O elemento reordenado é interativo (link, botão, campo) — a navegação por teclado seguirá a ordem do DOM
/* USO ACEITÁVEL: reordenação estética em galeria */
.galeria__destaque {
order: -1; /* imagem de destaque aparece primeiro visualmente */
/* todas as imagens são equivalentes — qualquer ordem faz sentido */
}
/* USO PROBLEMÁTICO: reordenação de conteúdo sequencial */
.passo-3 { order: 1; } /* Passo 3 aparece visualmente antes do Passo 1 */
.passo-1 { order: 2; } /* leitor de tela lê na ordem do DOM: 3, 1, 2 */
.passo-2 { order: 3; } /* confuso para usuários de tecnologia assistiva */
/* SOLUÇÃO: reorganize o DOM, não a apresentação visual */
A diretriz WCAG 2.1 relevante é o critério de sucesso 1.3.2 — Sequência com Significado (nível A): "Se a sequência em que o conteúdo é apresentado afeta seu significado, uma sequência de leitura correta pode ser determinada programaticamente."
Referências: - MDN — Flexbox e acessibilidade - W3C — CSS Flexible Box Layout Module Level 1 - CSS Tricks — A Complete Guide to Flexbox - Flexbox Froggy — exercício interativo
Atividades — Capítulo 8¶
1. Em um flex container com flex-direction: column, qual propriedade controla o alinhamento horizontal dos itens?
2. Três flex items têm flex-grow: 1, flex-grow: 2 e flex-grow: 1, respectivamente. O container tem 200px de espaço disponível após o tamanho base dos itens. Quanto espaço cada item recebe?
3. Por que o uso de order para reordenar conteúdo semanticamente sequencial (como etapas de um processo) é considerado uma falha de acessibilidade?
- GitHub Classroom: Construir uma página com: (1) navbar com logo e links usando Flexbox; (2) seção de cards responsivos com altura igual e footer sempre na base; (3) sticky footer aplicado ao
<body>. Todos os layouts devem usar apenas Flexbox, semfloatoupositionpara estrutura. (link será adicionado)
:material-arrow-left: Voltar ao Capítulo 7 — Fundamentos do CSS :material-arrow-right: Ir ao Capítulo 9 — Layout com Grid