Skip to content
This page has been auto-translated and may contain errors.View in English

Exibição e fluxo normal

docs.scrimba.com

Coloque três parágrafos e alguns links em uma página sem CSS nenhum e eles ainda se organizam: os parágrafos se empilham na página, os links ficam dentro do texto onde você os escreveu. Ninguém mandou o navegador fazer isso. Antes de você escrever uma única regra de layout, já existe um layout, e toda técnica que você usa depois é uma mudança nele em vez de um começo do nada. Este capítulo é sobre esse ponto de partida e a única propriedade que o governa.

Fluxo normal

Quando um navegador exibe uma página sem CSS de layout próprio, ele usa fluxo normal: a forma padrão como os elementos se organizam. Coisas em bloco como parágrafos e títulos se empilham de cima para baixo, cada um em sua própria linha. Texto e links correm ao longo de uma linha, da esquerda para a direita, voltando para a próxima linha quando o espaço acaba.

Você já conheceu as peças que fluem ao redor: este capítulo se baseia no modelo de caixa, porque são essas caixas que fluem. O fluxo normal vale a pena nomear porque tudo mais no layout é definido contra ele. Flexbox, grid e posicionamento são todas formas de dizer "organize esses elementos de forma diferente do padrão", então conhecer o padrão é o que faz as mudanças fazerem sentido.

O fluxo normal é o layout padrão do navegador: a disposição que você obtém antes de qualquer flex, grid, float ou posicionamento entrar em cena. Caixas de bloco se empilham verticalmente na página em ordem de origem, cada uma começando em uma nova linha e ocupando toda a largura disponível. Caixas inline fluem ao longo da linha, da esquerda para a direita em um idioma da esquerda para a direita, voltando para a próxima linha quando a atual se enche.

O motivo de nomeá-lo é que as ferramentas de layout são definidas como desvios dele. Quando você define display: flex em um contêiner, você está dizendo ao navegador para organizar os filhos desse contêiner por regras flex em vez de fluxo normal. O padrão nunca desaparece; você opta por contêineres individuais fora dele. É por isso também que um documento sem estilo ainda é legível: o fluxo normal é um layout real, não a ausência de um.

O fluxo normal é o modo de layout que o navegador aplica por padrão, antes de floats, posicionamento, flex ou grid mudarem algo. Tem dois sub-modos funcionando juntos: layout de bloco, que empilha caixas de nível de bloco verticalmente em ordem de origem na página, e layout inline, que organiza caixas de nível inline horizontalmente dentro de uma linha e as envolve em caixas de linha. Uma caixa de bloco disposta em fluxo normal ocupa toda a largura disponível e começa em uma nova linha; uma caixa inline ocupa apenas a largura que seu conteúdo precisa e fica dentro da linha atual.

Nomeá-lo com precisão importa porque todo o sistema de layout é construído como um conjunto de alternativas a ele. display: flex e display: grid substituem o layout interno de um contêiner por regras flex ou grid, e position: absolute ou um float tira uma caixa do fluxo normal completamente para que o conteúdo ao redor se organize como se ela não estivesse lá. Em cada caso, o fluxo normal é a base da qual você está se desviando, e uma caixa que não é explicitamente retirada dele ou entregue a outro modo de layout ainda está fluindo. É por isso que um documento sem folha de estilo é renderizado em uma ordem sensata: o fluxo de bloco e inline é o padrão, não um fallback.

JunoFluxo normal O fluxo normal é o layout que você obtém de graça: blocos se empilham na página, texto e links correm ao longo da linha. Ninguém o ativa, já está lá antes de você escrever CSS. Tudo mais no layout é uma mudança neste padrão, então ajuda visualizar o padrão primeiro.
JunoFluxo normal O fluxo normal é o padrão do navegador: blocos se empilham de cima para baixo em ordem de origem, caixas inline correm ao longo da linha e envolvem. Flex, grid e posicionamento são todas formas de fazer um contêiner optar por sair dele, nunca uma substituição para ele em todos os lugares de uma vez. Uma página sem estilo lê bem porque o fluxo normal é um layout real, não a falta de um.
JunoFluxo normal O fluxo normal é layout de bloco se empilhando verticalmente mais layout inline correndo ao longo da linha, aplicado por padrão antes de qualquer coisa tocar a caixa. display: flex e display: grid trocam o layout interno de um contêiner, e float ou position: absolute puxam uma caixa para fora do fluxo para que irmãos a ignorem. O que você não desvia fica em fluxo, é por isso que um documento sem folha de estilo ainda é renderizado em ordem.

Caixas de bloco e caixas inline

Os elementos vêm em dois sabores principais no fluxo normal. Uma caixa de bloco ocupa toda a largura de seu contêiner e se empilha em sua própria linha, empurrando o próximo elemento para baixo. Um parágrafo <p>, um título <h1> e um <div> são todos blocos, e é por isso que se alinham um sob o outro.

Uma caixa inline é diferente. Ela fica dentro de uma linha de texto e ocupa apenas o espaço que seu conteúdo precisa, então várias podem compartilhar uma linha. Um <span> ou um link <a> é inline, e é por isso que um link dentro de uma frase fica no fluxo das palavras em vez de pular para sua própria linha.

html
<p>Este parágrafo é um bloco, então fica em sua própria linha.</p>
<p>Leia o <a href="/css/box-model">modelo de caixa</a> para mais.</p>
<!-- o link é inline, então fica dentro da frase -->

Cada caixa no fluxo normal é disposta como nível de bloco ou nível inline, e as duas seguem regras diferentes. Uma caixa de bloco começa em uma nova linha, preenche a largura disponível por padrão e se empilha verticalmente. <div>, <p>, <h1> e <section> são blocos por padrão. Uma caixa inline flui dentro de uma linha ao lado de texto, ocupa apenas a largura de seu conteúdo e fica ao lado de seus vizinhos até a linha envolver. <span>, <a> e <strong> são inline por padrão.

A diferença que pega as pessoas é o que as caixas inline ignoram. Uma caixa inline ignora width, height e margens superior e inferior. Defina width: 200px em um <span> e nada acontece, porque uma caixa inline é dimensionada por seu conteúdo, não por você. Padding e margem esquerda e direita se aplicam, mas espaçamento vertical não empurra as linhas ao redor da forma que faria em um bloco.

css
.tag {
  width: 200px;        /* ignorado: um span é inline, dimensionado por conteúdo */
  padding: 0 8px;      /* padding horizontal funciona */
  margin-top: 40px;    /* ignorado: sem margem vertical em caixas inline */
}

No fluxo normal uma caixa é disposta por layout de bloco ou layout inline dependendo de seu tipo de display, e os dois diferem de formas que vão além de "se empilha ou envolve". Uma caixa de bloco gera uma quebra antes e depois de si mesma, consome o tamanho inline completo de seu bloco contêiner a menos que receba uma largura, e honra todas as quatro margens e ambas as dimensões. Uma caixa inline participa de uma caixa de linha, é dimensionada por seu conteúdo, e seu layout é governado por line-height e alinhamento de baseline em vez de width e height.

A parte precisa é quais propriedades uma caixa inline abandona. width e height não se aplicam a uma caixa inline não-substituída como um <span> ou <a>, porque seu tamanho vem de seu conteúdo e da linha ao redor. Margens superior e inferior são computadas mas não têm efeito na altura da linha, então nunca empurram linhas adjacentes para longe, e padding superior e inferior é renderizado visualmente mas não muda a altura da caixa de linha também, então pode sobrepor linhas vizinhas. Margem e padding esquerda e direita se aplicam e mudam vizinhos inline. Elementos inline substituídos como <img> são a exceção: carregam dimensões intrínsecas, então width e height se aplicam a eles mesmo sendo inline-level.

css
.badge {              /* .badge é um <span>, inline por padrão */
  width: 120px;       /* sem efeito: width não se aplica a caixas inline */
  height: 40px;       /* sem efeito pela mesma razão */
  padding: 12px;      /* esquerda/direita movem vizinhos; superior/inferior podem sobrepor linhas */
  margin: 8px 0;      /* os 8px verticais são ignorados, o 0 horizontal se aplicaria */
}
JunoCaixas de bloco e caixas inline Caixas de bloco como <p> e <div> ocupam a largura total e se empilham em suas próprias linhas. Caixas inline como <span> e <a> ficam dentro de uma linha e ocupam apenas o espaço que precisam. É por isso que um link fica dentro de sua frase em vez de quebrar para sua própria linha.
JunoCaixas de bloco e caixas inline Caixas de bloco preenchem a largura e se empilham; caixas inline fluem ao longo da linha e dimensionam para seu conteúdo. A armadilha é que uma caixa inline ignora width, height e margens verticais, então definir width em um <span> não faz nada. Padding e margem horizontal ainda funcionam, e é por isso que isso pega as pessoas.
JunoCaixas de bloco e caixas inline Uma caixa inline é dimensionada por seu conteúdo e sua caixa de linha, então width e height não se aplicam, e margem e padding vertical não empurram linhas adjacentes para longe. Margem e padding horizontal se aplicam e movem vizinhos. A exceção são elementos substituídos como <img>, que carregam suas próprias dimensões e, portanto, aceitam width e height mesmo sendo inline.

A propriedade display

Todo elemento tem um tipo padrão, bloco ou inline, mas você não está preso a ele. A propriedade display permite que você mude o tipo que um elemento se comporta. Defina display: block em um link e agora ele ocupa sua própria linha; defina display: inline em um item de lista e ele fica em uma linha.

Existe um terceiro valor que resolve um problema comum: display: inline-block. Ele flui na linha como uma caixa inline, mas aceita uma largura, uma altura e padding vertical como um bloco. Isso é o que você quer para algo como um botão ou uma pastilha de navegação que deve ficar ao lado de seus vizinhos ainda ocupando um tamanho definido.

css
.nav-link {
  display: inline-block;   /* flui na linha, mas aceita width e padding */
  padding: 8px 16px;       /* padding vertical agora funciona, diferente de inline puro */
}

A propriedade display define como uma caixa se organiza, e os três valores de fluxo são block, inline e inline-block. display: block faz uma caixa começar em sua própria linha e preencher a largura, seja qual for o padrão do elemento. display: inline a faz fluir dentro de uma linha e descartar width, height e margens verticais. Nenhum deles muda o significado do elemento, apenas seu layout.

inline-block é o híbrido útil: a caixa flui na linha como uma caixa inline, então várias ficam lado a lado, mas aceita width, height e padding e margem verticais como um bloco. Use-o quando você quer coisas em uma linha que ainda precisam de dimensões reais, um conjunto de botões ou links de navegação, sem passar para flexbox. Quando você precisa organizar uma linha inteira ou grid de itens com alinhamento e espaçamento, display: flex em flexbox é a ferramenta melhor; inline-block é para o caso menor de algumas caixas dimensionadas em uma linha.

css
.stat {
  display: inline-block;   /* fica em uma linha com seus irmãos */
  width: 120px;            /* mas ocupa uma largura fixa, que inline ignoraria */
  padding: 12px;           /* padding completo se aplica, superior e inferior inclusos */
}

display seleciona o modo de layout para uma caixa, e os três valores que a mantêm no fluxo normal são block, inline e inline-block. block dá uma caixa que quebra antes e depois e preenche o tamanho inline de seu bloco contêiner; inline dá uma caixa que entra em uma caixa de linha e descarta width, height e margens verticais. Definir display nunca toca a semântica, apenas o layout: um <div> definido para display: inline ainda é um <div> para o DOM e tecnologia assistiva, só que organiza inline.

inline-block é o híbrido deliberado. A caixa é nível inline, então participa de uma caixa de linha e fica ao lado de vizinhos inline, mas seu interior é organizado como um bloco, então width, height e todas as quatro margens e paddings se aplicam e ocupam espaço real de layout. Isso a torna correta para um pequeno número de caixas dimensionadas em uma linha onde você não quer um contêiner flex, por exemplo blocos de estatísticas de largura fixa ou pastilhas de navegação. A ressalva é que porque é nível inline, o espaço em branco entre dois elementos inline-block em seu HTML é renderizado como um espaço real entre eles, que a seção avançada abaixo cobre. Para qualquer coisa com alinhamento, distribuição ou envolvimento em uma linha completa, prefira o layout flex em flexbox; inline-block é a ferramenta estreita, não a geral.

css
.pill {
  display: inline-block;   /* caixa nível inline, interior nível bloco */
  width: 96px;             /* se aplica, porque o interior organiza como um bloco */
  padding: 10px 14px;      /* todos os quatro lados ocupam espaço de layout */
  margin: 0 4px;           /* margem vertical agora se aplica também */
}
JunoA propriedade display A propriedade display muda se um elemento se comporta como um bloco ou como uma caixa inline. block ocupa sua própria linha, inline fica na linha de texto. A opção de meio útil é inline-block, que flui na linha mas ainda aceita uma largura e padding, então é o que você quer para botões e links de navegação.
JunoA propriedade displaydisplay define o layout, não o significado: block, inline ou o híbrido inline-block. Use inline-block quando você quer algumas caixas dimensionadas ficando em uma linha, uma vez que flui inline mas aceita width, height e padding completo. Para uma linha inteira que precisa de alinhamento e espaçamento, use flexbox.
JunoA propriedade displaydisplay escolhe o modo de layout e nunca a semântica, então um <div> inline ainda é um <div> para o DOM. inline-block é uma caixa nível inline com interiores nível bloco, então fica em uma linha mas honra width, height e todas as quatro margens. Mantenha-o para um punhado de caixas dimensionadas e passe uma linha real para flexbox, e tenha cuidado com a lacuna de espaço em branco que deixa entre caixas adjacentes.

Ocultando coisas: display none versus visibility hidden

Às vezes você precisa que um elemento não apareça. Existem duas formas, e elas se comportam diferentemente. display: none remove o elemento completamente: ele desaparece e não deixa nenhuma lacuna, como se não estivesse na página. visibility: hidden o torna invisível mas mantém seu espaço, então há um buraco vazio onde estava.

Qual deles você quer depende se você quer o espaço de volta. Use display: none para remover algo completamente, como um menu que está fechado. Use visibility: hidden quando você quer ocultar algo sem que o layout pule, porque sua caixa permanece reservada.

css
.closed-menu {
  display: none;          /* desaparecido, e sem lacuna deixada para trás */
}
.placeholder {
  visibility: hidden;     /* invisível, mas ainda ocupa seu espaço */
}

As duas formas de ocultar um elemento não são intercambiáveis. display: none tira o elemento do fluxo normal completamente: não gera caixa, não ocupa espaço, e os elementos ao redor se fecham como se ele nunca tivesse estado lá. visibility: hidden mantém a caixa em fluxo e reserva seu espaço, então o layout não muda; o elemento apenas é pintado invisível.

Há uma diferença de acessibilidade que importa tanto quanto a visual. Um elemento com display: none também é removido da árvore de acessibilidade, então leitores de tela o pulam, o que é correto para conteúdo que não está presente, como um painel colapsado. visibility: hidden também oculta conteúdo de leitores de tela enquanto mantém o espaço. Se você quer algo visualmente desaparecido mas ainda anunciado para tecnologia assistiva, nenhum desses está certo; isso é para o que uma classe utilitária visually-hidden é feita, que você pode ler sobre ao lado da semântica em como CSS funciona.

css
.tab-panel[hidden] {
  display: none;          /* removido do fluxo e da árvore de acessibilidade */
}
.spacer {
  visibility: hidden;     /* mantém seu espaço, ainda oculto de leitores de tela */
}

display: none e visibility: hidden ambos ocultam, mas diferem em fluxo, na árvore de caixa e em acessibilidade. display: none não gera nenhuma caixa: o elemento está ausente do layout, não ocupa espaço, e seus descendentes se foram com ele independentemente de seu próprio display. visibility: hidden gera a caixa normalmente, então ocupa seu espaço completo em fluxo e apenas suprime a pintura; um descendente pode até definir visibility: visible para reaparecer dentro de um ancestral de outra forma oculto, o que display: none nunca permite.

As consequências de acessibilidade e comportamento são a razão para escolher deliberadamente. Tanto display: none quanto visibility: hidden removem o elemento da árvore de acessibilidade, então um leitor de tela não anunciará nenhum dos dois. Isso os torna errados para conteúdo que você quer visualmente desaparecido mas ainda lido em voz alta, o caso clássico sendo um link "pular para conteúdo" ou um rótulo exclusivo para leitor de tela; esses precisam de um padrão visually-hidden que recorte a caixa para um pixel enquanto a mantém na árvore de acessibilidade, não nenhuma propriedade aqui. Duas notas práticas adicionais: display: none não pode ser transicionado ou animado entre estados da forma que opacity e visibility podem, e um elemento definido para display: none não é focalizável e seus controles de formulário não são enviados, enquanto um controle visibility: hidden também é pulado mas seu espaço é mantido. Escolha display: none para remover completamente, visibility: hidden para ocultar enquanto mantém o layout firme, e um utilitário de recorte quando tecnologia assistiva ainda deve alcançá-lo.

css
.dropdown[aria-expanded="false"] .menu {
  display: none;          /* completamente removido: sem caixa, sem espaço, não focalizável */
}
.avatar-slot {
  visibility: hidden;     /* caixa e espaço mantidos, pintura suprimida */
}
JunoOcultando coisas: display none versus visibility hidden Duas formas de ocultar: display: none remove o elemento e não deixa lacuna, visibility: hidden o torna invisível mas mantém seu espaço. Escolha display: none quando você quer que o espaço desapareça também, como um menu fechado. Escolha visibility: hidden quando você não quer que o layout pule.
JunoOcultando coisas: display none versus visibility hiddendisplay: none tira o elemento do fluxo para que nada reserve seu espaço; visibility: hidden mantém a caixa e seu espaço e apenas oculta a pintura. Ambos também ocultam o elemento de leitores de tela, então se você quer algo visualmente desaparecido mas ainda anunciado, nenhum está certo. Esse trabalho pertence a uma classe utilitária visually-hidden.
JunoOcultando coisas: display none versus visibility hiddendisplay: none não gera caixa e não ocupa espaço; visibility: hidden mantém a caixa e o espaço e apenas suprime a pintura, e um filho pode definir visibility: visible para reaparecer. Ambos saem da árvore de acessibilidade, então um link pular ou rótulo de leitor de tela precisa de um utilitário de recorte, não nenhum desses. Lembre-se que display: none não é animável e seus controles não são focalizáveis ou enviados.

Como display muda o layout interno

Você viu display mudar um elemento entre bloco e inline. Ele faz mais que isso no nível mais profundo. A mesma propriedade é o que transforma um contêiner em um flexbox ou um grid, que são as duas ferramentas modernas para organizar filhos em linhas e colunas. Por enquanto, a coisa para manter é que display é o único controle que decide como uma caixa se organiza e como seus filhos se organizam dentro dela.

Layout não é um grande interruptor que você liga uma vez. Você muda display nos contêineres específicos que precisam de uma disposição diferente, e tudo o que você deixa em paz fica no fluxo normal. Os capítulos flexbox e posicionamento continuam daqui.

display realmente controla duas coisas ao mesmo tempo: como a caixa se senta entre seus irmãos e como a caixa organiza seus próprios filhos. display: block e display: inline principalmente falam sobre o primeiro. display: flex e display: grid mudam o segundo: o contêiner ainda participa do fluxo normal como um bloco, mas dentro dele, os filhos são organizados por regras flex ou grid em vez de fluxo de bloco e inline.

É por isso que passar para flexbox não joga fora tudo o que você sabe sobre fluxo. Um contêiner flex ainda é uma caixa de bloco no fluxo normal de seu pai; apenas seus filhos mudam o modo de layout. O fluxo normal permanece o padrão ao seu redor, e você opta pelo flex ou grid nos contêineres específicos que precisam dele. O capítulo posicionamento cobre a outra forma de deixar o fluxo, tirando uma caixa completamente dele em vez de mudar como os filhos se organizam.

Um valor display é realmente dois tipos ao mesmo tempo: um tipo externo que diz como a caixa participa do layout de seu pai, e um tipo interno que diz como a caixa organiza seus próprios filhos. display: block é externo de bloco, fluxo interno; display: flex é externo de bloco, flexo interno; display: inline-flex é externo inline, flexo interno. Esse modelo de duas partes é por que um contêiner flex ainda fica no fluxo normal como um bloco enquanto seus filhos seguem regras flex: você mudou o tipo interno, não o externo.

Um valor mais merece um lugar aqui: display: flow-root. Ele dá a uma caixa um fluxo interno normal mas a força a estabelecer um novo contexto de formatação em bloco (um BFC: uma região de layout autossuficiente cujos interiores não interagem com o exterior, então floats dentro dele são contidos e margens dentro dele não colapsa pela sua borda). Antes de flow-root existir, as pessoas acionavam um BFC com overflow: hidden ou um hack clearfix para conter filhos flutuantes; flow-root é a forma explícita e livre de efeitos colaterais de dizer "contenha isto". Também para o colapso de margem de pai e filho descrito no modelo de caixa. Quando você move um contêiner para display: flex ou display: grid em flexbox, você está igualmente estabelecendo um novo contexto de formatação, que é parte do motivo pelo qual as margens se comportam de forma mais previsível dentro de layouts modernos do que dentro de layouts da era float.

css
.media {
  display: flow-root;     /* contém quaisquer filhos flutuantes, sem hack clearfix */
}
.gallery {
  display: flex;          /* externo de bloco em fluxo normal, flexo interno para filhos */
}
JunoComo display muda o layout interno A mesma propriedade display que muda entre bloco e inline é também o que transforma um contêiner em um flexbox ou um grid para organizar filhos. Layout não é um interruptor que você liga uma vez; você muda display nos contêineres que precisam e deixa o resto no fluxo normal. Os capítulos flexbox e posicionamento continuam daqui.
JunoComo display muda o layout internodisplay governa tanto como uma caixa se senta entre seus irmãos quanto como ela organiza seus próprios filhos. display: flex e display: grid mudam o segundo, então um contêiner flex ainda é um bloco no fluxo normal enquanto seus filhos mudam para regras flex. É por isso que aprender flexbox se constrói sobre o fluxo em vez de substituí-lo.
JunoComo display muda o layout interno Um valor display carrega um tipo externo, como a caixa entra em seu pai, e um tipo interno, como ela organiza filhos, o que é por que um contêiner flex permanece um bloco em fluxo enquanto seus filhos vão flex. display: flow-root mantém o fluxo interno normal mas inicia um novo contexto de formatação em bloco, então contém floats e para o colapso de margem sem os antigos hacks overflow ou clearfix. Contêineres flex e grid também estabelecem seu próprio contexto, o que é por que as margens se comportam de forma mais previsível dentro deles.