Qual o tamanho dessa caixa? Entendendo o dimensionamento no layout CSS
Publicados: 2022-03-10Um recurso chave do Flexbox e do Grid Layout é que eles podem lidar com a distribuição do espaço disponível entre, ao redor e dentro de itens de grade e flex. Muitas vezes, isso simplesmente funciona e obtemos o resultado que esperávamos sem nos esforçar muito. Isso ocorre porque as especificações tentam padronizar os casos de uso mais prováveis. Às vezes, no entanto, você pode se perguntar por que algo acaba do tamanho que é. Ou talvez você queira fazer algo diferente do comportamento padrão. Para fazer isso, você precisa saber algo sobre como os algoritmos subjacentes descobrem como distribuir o espaço.
Neste artigo, vou compartilhar com vocês algumas coisas interessantes sobre dimensionamento de caixas em CSS. Escolhi algumas coisas das especificações que acredito serem vitais em termos de entender exatamente o tamanho dessa caixa. Reserve algum tempo para ler, e acho que você achará o dimensionamento no Grid muito menos misterioso!
Olhando mais de perto o BFC
Se você já fez um layout com CSS, provavelmente sabe o que é BFC. Entender por que funciona e como criar um é útil e pode ajudá-lo a entender como o layout funciona em CSS. Leia um artigo relacionado →
Unidades de comprimento
Podemos começar com o dimensionamento que provavelmente será mais familiar. As unidades de comprimento descritas na especificação do módulo CSS Values and Units. Se você vir <length>
como um valor permitido para uma propriedade CSS, isso significa um dos valores listados aqui. Esses valores são todas as distâncias e normalmente consistem em um número inteiro, mais o identificador da unidade - por exemplo 12px
ou 1em
. Se o valor for 0
, o identificador da unidade pode ser omitido. Além disso, as unidades de comprimento são divididas em comprimentos relativos e absolutos.
Comprimentos relativos
Um comprimento relativo leva o dimensionamento em relação a alguma outra coisa e, portanto, o tamanho final de algo definido usando um comprimento relativo pode ser diferente se a coisa relativa mudar.
O conjunto completo de unidades relativas é o seguinte. As primeiras quatro unidades são relativas à fonte, enquanto as quatro últimas são relativas à viewport.
-
em
-
ex
-
ch
-
rem
-
vw
-
vh
-
vmin
-
vmax
Como esses valores são relativos a algo, é importante identificar exatamente a que eles são relativos. Para a unidade relativa à fonte rem
, isso é sempre relativo ao tamanho do elemento raiz, que é um documento HTML, é o elemento html
.
No primeiro exemplo abaixo, configurei o elemento html
para ter um tamanho de fonte de 20 pixels. 1rem
é, portanto, 20 pixels. Se eu der a um elemento uma largura de 10rem
, ele terá 200 pixels de largura (como 20px multiplicado por 10 é 200).
Quando as outras unidades relativas de fonte ( em
, ex
e ch
) são usadas para o comprimento de um elemento, elas são relativas ao tamanho da fonte aplicado a esse elemento. No segundo exemplo (a largura da caixa é 10em
), a unidade em
analisa a fonte aplicada ao elemento que está dimensionando e calcula com base nisso. Portanto, essa caixa fica com 300 pixels de largura, pois o tamanho da fonte da caixa é 30px
.
Onde as unidades relativas da fonte são calculadas a partir do tamanho da fonte, as unidades relativas da janela de visualização são calculadas em relação a um retângulo conhecido como bloco contendo inicial . Em uma tela, isso tem as dimensões da viewport. A unidade vw
é 1/100 da largura da janela de visualização e vh
1/100 da altura . Uma caixa com largura de 50vw
e altura de 50vh
deve ter metade da largura e metade da altura da janela de visualização.
As unidades vmin
e vmax
são úteis porque permitem dimensionar algo em relação à dimensão maior ou menor da janela de visualização. Isso significa que você pode fazer algo 50% do lado mais longo da janela de visualização, por exemplo. Isso é especialmente útil quando alguém pode segurar um dispositivo no modo paisagem ou retrato. A unidade vmin
sempre resolve para o pequeno ou vw
ou vh
e vmax
para o maior de vw
ou vh
. Portanto, se você deseja que uma largura seja sempre 20% do lado mais longo do dispositivo, você pode usar 20vmax
. Se o dispositivo for mantido no modo retrato, 20vmax
seria o mesmo que 20vh
. Se o dispositivo for mantido no modo paisagem, seria o mesmo que 20vw
.
O exemplo abaixo compara um bloco dimensionado com vw
e vh
com um dimensionado usando vmin
e vmax
. Em um computador desktop ou telefone no modo paisagem, ambas as caixas devem aparecer do mesmo tamanho. Mude um telefone para o modo retrato ou arraste sua janela para que a largura fique menor que a altura, e você verá como o segundo bloco altera a dimensão da qual obtém o cálculo.
Unidades Absolutas
As unidades absolutas são mapeadas para dimensões físicas e não são dimensionadas em relação a outras coisas na tela. Portanto, eles são mais úteis quando o ambiente de saída é conhecido.
A lista abaixo mostra as unidades absolutas permitidas em CSS:
-
cm
-
mm
-
Q
-
in
-
pc
-
pt
-
px
Como você pode ver, muitos deles fazem pouco sentido em um contexto de tela, no entanto, se você estiver criando CSS para impressão, usar pt
ou in
pode fazer muito sentido quando você sabe o tamanho do papel.
O pixel é classificado como uma unidade de comprimento absoluto e, como saberá qualquer pessoa que tenha criado imagens para dispositivos de retina, um pixel em termos de comprimento não é o mesmo que um pixel de dispositivo. O CSS usa o conceito de pixel de referência e a especificação recomenda que a unidade de pixel se refira ao número total de pixels do dispositivo que melhor se aproximam do pixel de referência.
O pixel de referência é o ângulo visual de um pixel em um dispositivo com uma densidade de pixels de 96 dpi e uma distância do leitor do comprimento de um braço. Para um comprimento nominal de braço de 28 polegadas, o ângulo visual é, portanto, de cerca de 0,0213 graus. Para leitura no comprimento do braço, 1px corresponde a cerca de 0,26 mm (1/96 polegada ). — "Módulo de Valores e Unidades CSS Nível 3", W3C
Porcentagens
Na maioria dos casos, você pode usar uma porcentagem em vez de uma unidade de comprimento para o tamanho. Essa porcentagem precisará ser calculada em relação a algo, da mesma forma que uma unidade de comprimento relativo é resolvida, e a especificação do método de layout que você está usando indicará qual porcentagem deve ser uma porcentagem de .
Em uma especificação, onde você vê <length-percentage>
como um valor permitido para um comprimento, isso significa que a porcentagem será resolvida em um comprimento antes de ser usada. No exemplo abaixo, o elemento externo tem uma largura de 400 pixels e o primeiro elemento filho uma largura de 50%. Isso resolve para 200 pixels - 50% de 400.
O segundo elemento filho tem uma largura que usa calc
, para adicionar 50 pixels a 50%, tornando esse bloco de 250 pixels de largura. Os 50% são, portanto, resolvidos em um comprimento e, em seguida, usados no cálculo.
Aqueles de nós que trabalharam na web durante a era do design responsivo se acostumaram a usar porcentagens para criar layouts que parecem dispostos em uma grade. Trabalhar em porcentagens nos dá algum grau de controle, controle que precisamos começar a abrir mão para utilizar plenamente o poder do Grid e do Flexbox!
Dimensionamento intrínseco e extrínseco de CSS
Até agora, vimos como podemos atribuir um tamanho às caixas, definir sua largura e altura de várias maneiras, bem como usar unidades de comprimento e porcentagens. No entanto, as caixas em sua página da Web têm um tamanho, mesmo que você não tenha dado a elas um . É importante entender como os elementos são dispostos na página e esse tamanho se torna cada vez mais importante ao usar flexbox e layout de grade. Muito da flexibilidade embutida no Grid e no flexbox vem porque eles gerenciam situações em que há mais espaço do que o necessário para exibir itens, ou os itens precisam caber em menos espaço do que ocupariam se o espaço fosse infinito.
O módulo que define o tamanho das coisas e fornece maneiras adicionais de controlar esse tamanho é o Módulo de dimensionamento intrínseco e extrínseco do CSS. Nesta próxima seção, veremos o que este módulo define e por que ele é vital para sua compreensão do layout em flexbox e grid.
Palavras-chave de dimensionamento
O resumo do módulo diz:
Este módulo estende as propriedades de dimensionamento CSS com palavras-chave que representam tamanhos "intrínsecos" baseados em conteúdo e tamanhos "extrínsecos" baseados em contexto, permitindo que o CSS descreva mais facilmente caixas que se encaixam em seu conteúdo ou em um contexto de layout específico.
As palavras-chave podem ser usadas para qualquer uma das propriedades que normalmente levam um comprimento. Por exemplo width
, height
, min-width
e assim por diante, além de ser especificado para uso no dimensionamento de trilha do Grid Layout e flexbox flex-basis
. Os valores de palavra-chave conforme definido no atual rascunho do editor da especificação principal de nível 3 são:
-
max-content
-
min-content
-
fit-content(<length-percentage>)
Vamos dar uma olhada em como algumas dessas palavras-chave se comportam se as usarmos para a largura de uma div. Um div é um elemento de nível de bloco e, portanto, se você não fornecer uma largura, ele se estenderá para ser o mais largo possível na dimensão em linha. Até atingir a borda da viewport ou o bloco que o contém.
Se uma string de texto for maior que o espaço permitido, ela será colocada dentro da div e a caixa ficará mais alta para acomodá-la. Para dar ao div uma largura diferente do espaço permitido pelo bloco que o contém, você pode usar qualquer uma das unidades de comprimento discutidas anteriormente. O texto começaria a quebrar assim que atingir esse comprimento.
Em vez de restringir a caixa usando um comprimento ou atingindo as bordas do bloco que a contém, talvez você queira permitir que o conteúdo dite o tamanho. É aí que entram essas novas palavras-chave de dimensionamento baseadas em conteúdo.
conteúdo mínimo
Use width: min-content
na div, e a div agora se torna apenas tão grande quanto precisa ser, com o conteúdo se tornando o menor possível na direção inline. Com uma sequência de texto, isso significa que o texto aproveita todas as oportunidades de quebra automática que pode.
Este é o tamanho mínimo do conteúdo deste elemento. O menor que pode ficar sem que nenhum conteúdo transborde de alguma forma.
conteúdo máximo
O comportamento oposto acontece se usarmos width: max-content
. Agora, a caixa se torna maior o suficiente para conter o conteúdo se for o maior possível na dimensão embutida. Nossa string de texto agora se estende e não envolve em nada. Isso causará estouros caso se torne maior do que a largura disponível para a qual esse div deve crescer.
Essas palavras-chave de conteúdo são enviadas para os navegadores, você pode usá-las no Chrome e também prefixadas no Firefox como um valor para width
e height
. Você pode usá-los para o dimensionamento de trilhas no Grid Layout, como exploraremos abaixo, pois ainda não foram implementados para flex-basis
no flexbox. No entanto, a verdadeira razão para olhar para isso agora é entender que existe min-content
e max-content
, pois coisas com um tamanho mínimo e máximo de conteúdo são importantes quando começamos a ver como o espaço é distribuído no Flexbox e Grid.
Dimensionamento baseado em conteúdo no layout de grade CSS
O CSS Grid Layout tem uma implementação sólida das palavras-chave de conteúdo que acabamos de explorar, usadas para dimensionar faixas de grade. Isso significa que você pode fazer com que o conteúdo dite o tamanho da faixa na grade. A coisa importante a lembrar com a grade é que é um modelo de layout bidimensional. Se você estiver solicitando que uma faixa de coluna tenha o tamanho min-content
, a faixa será dimensionada com base na coisa mais larga da faixa.
conteúdo mínimo
No próximo exemplo, tenho uma grade de trilha de três colunas. As colunas são dimensionadas usando a palavra-chave min-content
. Uma das células contém mais conteúdo e você pode ver como o conteúdo é agrupado onde pode. O tamanho necessário para exibir esse conteúdo no tamanho min-content
se torna o tamanho da faixa inteira.
conteúdo máximo
Se olharmos para o mesmo exemplo de min-content
mas alterarmos as colunas para cada use max-content
, você poderá ver como a faixa que contém um item com muito texto cresceu para acomodar o texto. Isso fez com que as trilhas fossem mais largas do que o tamanho do elemento no qual definimos nossa grade, então estourou.
conteúdo adequado
Uma palavra-chave que ainda não analisamos e que foi implementada no Grid Layout é fit-content
. Essa palavra-chave tem um comprimento ou porcentagem como valor. Quando você usa fit-content
para dimensionamento de trilha, a trilha agirá como max-content
até atingir o tamanho do valor que você passou. Quando atingir esse tamanho, a trilha parará de crescer e o conteúdo será encapsulado.
Todas as três faixas de coluna no exemplo abaixo são dimensionadas usando fit-content(10em)
. Se a faixa for mais estreita que 10em, ela age como max-content
. A pista central, que seria mais longa, para de crescer quando atinge 10 em.
Observação : criei um pequeno tutorial em vídeo para demonstrar essas palavras-chave de dimensionamento de conteúdo .
Faixas de tamanho automático
Antes de cavar mais fundo na toca do coelho do dimensionamento de esteiras, também é importante entender o que significa auto
quando usado para dimensionamento de esteiras. As faixas de grade implícitas são criadas com dimensionamento auto
e você normalmente entenderá isso quando começar a usar Grid. Você especifica faixas de coluna, mas coloca o conteúdo em linhas sem uma definição explícita. As faixas de linha crescem para conter o conteúdo porque auto
verifica o tamanho do conteúdo e cria uma faixa com altura suficiente para contê-lo.
No entanto, auto
tem um significado específico nas especificações. No caso de Grid e flexbox, se você usar auto
para um tamanho de faixa ou como o valor de flex-basis
, ele verificará se há algum tamanho no item (ou em qualquer item dessa faixa para Grid) e use esse tamanho como o tamanho da trilha base ou como o valor de flex-basis
. Você pode ver isso acontecendo no CodePen abaixo. O primeiro exemplo é um Layout Grid, o segundo um layout Flex. O Layout de Grade tem três faixas de coluna, todas de tamanho auto
, cada item no layout Flex pode crescer e diminuir de uma flex-basis
de auto
.
Em ambos os layouts, o item final tem uma largura de 200px. Você pode ver como essa largura está sendo usada ao calcular o tamanho da pista. Torna-se flex-basis
como o último item e o tamanho base para as faixas de grade. Para as outras faixas de grade e itens flexíveis, não há largura e, portanto, o algoritmo usa o tamanho do conteúdo.
Voltaremos ao modo como o auto
se comporta e como ele pode ser útil em combinação com outros métodos de dimensionamento de trilhas depois de passar para outra maneira de dimensionar trilhas de grade.
fr
Unidades
Todas as unidades de comprimento discutidas no início deste artigo também podem ser usadas para dimensionamento de trilhas em layouts de grade. Temos também uma unidade adicional na unidade fr
. Isso se aplica apenas ao layout da grade e, portanto, é detalhado na especificação da grade e não em qualquer um dos módulos relacionados ao dimensionamento. A unidade fr
é um comprimento flexível ou <flex>
e representa uma fração do espaço restante no contêiner de grade.
A unidade fr
não é um comprimento e não pode ser usada com calc()
da mesma forma que uma unidade de porcentagem ou comprimento pode.
Muitas vezes você verá uma demonstração como a abaixo, onde criamos três faixas de tamanhos iguais usando a unidade fr
. O espaço no contêiner de grade foi dividido em três e atribuído a cada faixa igualmente.
A unidade fr
aqui está agindo como o Flexbox se comporta se sua flex-basis
for 0
. Grid está pegando todo o espaço no container de grid e entregando uma parte para cada trilha. No entanto, Grid não fará com que uma faixa transborde ao fazer isso. Esse comportamento pode ser confuso se você tiver a impressão de que três faixas de 1fr
sempre serão três faixas de tamanhos iguais.
Se adicionarmos uma palavra muito longa em nossa faixa do meio, que não pode ser enrolada suavemente, por exemplo Supercalifragilisticexpialidocious , não teremos três colunas de largura igual.
A grade só está compartilhando o espaço disponível depois de garantir que as faixas sejam grandes o suficiente para conter os itens. Grid analisa o tamanho que a faixa teria se usássemos min-content
. Se esse tamanho for menor do que o tamanho que será entregue à pista através da unidade fr
, o conteúdo não será levado em consideração. Se esse tamanho min-content
for maior do que a faixa seria fornecida pela unidade fr
, o tamanho min-content
será usado para essa faixa antes que o espaço restante seja compartilhado.
Portanto, a unidade fr
age como flexbox com um flex-basis
de 0
, a menos que o tamanho do min-content
dessa faixa seja maior, então ele age mais como flexbox usando um flex-basis
de auto
. Assim como em nosso exemplo de auto
na seção anterior. Vale a pena lembrar disso se suas faixas de largura igual não parecerem muito iguais. A razão provável é que há algo em uma das faixas que tem um tamanho min-content
maior do que seria entregue a ela.
Fazendo faixas iguais com minmax
Agora sabemos por que a unidade fr
pode criar faixas maiores do que desejávamos. No entanto, podemos controlar a maneira como isso se comporta trazendo outro método de dimensionamento específico da grade — a função minmax()
. No exemplo acima (a palavra longa em uma trilha forçando um tamanho min-content
maior), Grid está agindo como se estivéssemos usando a seguinte definição de dimensionamento de trilha.
.grid { display: grid; grid-template-columns: minmax(auto,1fr) minmax(auto,1fr) minmax(auto,1fr); }
A grade está olhando para o tamanho auto
que está resolvendo o tamanho do content
e usando isso como o tamanho base para a faixa antes de compartilhar qualquer espaço restante.
Se você quiser que o Grid, no exemplo acima, forçosamente faça com que a faixa do meio tenha uma parte igual da largura no contêiner da grade, mesmo que isso cause algum estouro, você pode fazer isso tornando 0
o primeiro valor em minmax()
. Como você pode ver no próximo exemplo, isso causará um estouro.
Você pode ver por que a especificação padroniza para o comportamento que ela faz. Em geral, não queremos que ocorram estouros se houver espaço para o conteúdo ser exibido, no entanto, você tem a capacidade de forçar o assunto e causar o estouro, se necessário.
A função minmax()
também é muito útil ao dimensionar linhas para evitar que uma linha caia para a altura zero quando vazia, mas ainda permitindo que ela cresça até um tamanho que permita qualquer conteúdo adicionado. No próximo exemplo, tenho grid-auto-rows
definido como minmax(50px, auto)
. As faixas na grade implícita sempre terão 50 pixels de altura, mas você pode ver que a segunda linha é mais alta devido à quantidade de conteúdo em uma célula dessa linha.
Porcentagens no layout de grade
Embora tenhamos a unidade fr
, dimensionamento baseado em conteúdo e nossas unidades de comprimento usuais no Layout de grade, você também pode querer usar porcentagens para alguns requisitos de dimensionamento. Na maioria dos casos, a unidade fr
será uma escolha melhor, no entanto, às vezes você pode querer assumir o controle do tamanho exato da porcentagem. Uma razão para fazer isso é se você estiver alinhando elementos dispostos usando Grid em um design que também usa outros métodos de layout que dependem do dimensionamento percentual.
Na maioria das vezes, o dimensionamento percentual funcionará conforme o esperado. Uma trilha de grade dimensionada usando uma porcentagem calculará a porcentagem da largura do contêiner da grade. Você também pode usar porcentagens para as propriedades de gap
, e elas também serão calculadas com base na largura do contêiner da grade. O exemplo abaixo tem três trilhas de coluna de 30% cada, mais lacunas de grade de 5% entre as trilhas.
O lugar onde o cuidado precisa ser tomado é ao usar porcentagens para margens verticais e preenchimento. Tanto no Flexbox quanto no Grid, um problema de longa data significa que a forma como as margens de porcentagem vertical e o preenchimento são calculados será diferente entre os navegadores.
Você pode ler mais sobre esse problema no meu post "Como devemos resolver margens percentuais e preenchimento em itens de grade e flex", no entanto, meu conselho e o da especificação é evitar o uso de porcentagens para margem e preenchimento superior e inferior durante o tempo sendo, pois os resultados serão inconsistentes.
Alinhamento e dimensionamento no layout de grade
O uso das propriedades de alinhamento de caixa no Layout de grade também pode alterar o tamanho das áreas em sua grade. Considere o layout a seguir com quatro faixas de coluna de 100 pixels, três faixas de linha de 50 pixels e intervalos de 20 pixels. As trilhas de grade não ocupam toda a área do contêiner de grade e, portanto, se alinham para start
em ambos os eixos. Itens que abrangem mais de uma trilha tornam-se um tamanho que é o total de todas as trilhas e lacunas que eles abrangem.
Se agora eu usar as propriedades de alinhamento de caixa align-content
e justify-content
com valores de space-between
, as faixas se espalharão à medida que as lacunas aumentarem para absorver o espaço extra. Agora, qualquer item que se estende por mais de uma trilha se tornou maior, pois contém o espaço da lacuna agora ampliada.
Distribuição de espaço no Flexbox e grade comparada
A razão pela qual eu acho que entender conceitos como min-content
max-content
é tão importante ao lidar com layout, é que eles permitem que você comece a se aprofundar nos detalhes mais sutis do layout. Vou encerrar este artigo com um bom exemplo disso, algo que descobrimos comparando o que acontece no flexbox e no Grid quando precisamos encaixar itens em um container.
O exemplo mostra um contêiner flexível com quatro itens flexíveis; abaixo dele está um contêiner de grade com quatro itens de grade. Este conteúdo é idêntico, mas o layout ligeiramente diferente, apesar de serem layouts aproximadamente comparáveis. Os itens flexíveis têm uma flex-basis
de auto
e podem ser reduzidos. A definição de grade define quatro faixas, todas com tamanho auto
.
No exemplo do flexbox, os itens mais curtos foram reduzidos ao tamanho min-content
e o item maior recebeu mais espaço.
No exemplo Grid, os itens menores são exibidos em seu tamanho max-content
, portanto, o item mais longo tem menos espaço para exibição. Quando vi esse comportamento pela primeira vez, fiquei intrigado. O motivo da diferença se resume aos algoritmos que calculam o tamanho dos itens nos métodos de layout. No Flexbox, o item começa no tamanho max-content
; como flex-shrink
é um valor positivo, o espaço começa a ser retirado de cada item. Quando os itens menores atingem o tamanho min-content
, o flexbox para de ocupar espaço para evitar que eles desapareçam ou transbordem.
A grade, no entanto, começa com os itens no tamanho min-content
e, em seguida, adiciona espaço. Nossos itens rapidamente atingem o tamanho max-content
, no qual a grade deixa de atribuir espaço a eles, pois temos um item maior que pode preencher o espaço restante. Agora que você conhece min-content
e max-content
, você poderá identificar quando faixas ou itens são exibidos dessa maneira, o que lhe dará um ponto de partida para investigar e descobrir o que está acontecendo.
Tamanho importa!
Embora trabalhar com tamanhos percentuais para alinhar as coisas nunca fosse divertido, era pelo menos algo que todos entendíamos. Isso nos deu muito controle, mesmo que significasse que tínhamos que fazer todo o trabalho. Pode ser frustrante começar a usar Flexbox e Grid, apenas para descobrir que às vezes não conseguimos o layout que esperávamos. Pode ser tentador voltar a fazer o trabalho por nós mesmos e usar porcentagens para nossa flex-basis
ou dimensionamento de trilha.
No entanto, passar algum tempo brincando com o dimensionamento, até que você se sinta confortável com o que acontece em várias situações, irá recompensá-lo no final. Você descobrirá que precisa de menos consultas de mídia e pode contar com a flexibilidade inerente dos métodos de layout.
Para ajudá-lo a começar com suas próprias explorações, tentei manter os exemplos deste artigo o mais simples possível para que você possa bifurcá-los e experimentá-los. A maioria das coisas que compartilhei neste artigo são o resultado de me perguntar o que acontecerá se eu tentar algo diferente, ou seja, tentar e descobrir por que funciona como funciona! Então, se você ficar com mais perguntas do que respostas, poste um comentário com um link para uma demonstração, e tentarei apontar para a parte da especificação que explica.