Fundamentos da criação de layouts com CSS
Aprenda CSS e seu funcionamento, para construir layouts complexos sem dificuldades.
Box Model
Os elementos HTML são divididos em 4 partes:
- Margin - Espaço entre os elementos
- Border - Borda na qual pode ser aplicado cores
- Padding - Espaço interno do elemento
- Content - Conteúdo do elemento
Por padrão o Box Model aplica altura e largura no Content Box. Isso causa inconsistências na criação do layout. Isso porque quando você declara os tamanhos de um elemento, ele vai se comportar diferente para um elemento que possuí padding e border.
Para resolver isso a primeira coisa que temos que fazer é adicionar o seguinte estilo:
* { box-sizing: border-box;}
Nele nós usamos o seletor asterisco ” * ” para declarar que todos os elementos do site devem respeitar o modelo de dimensionamento na borda. O que comparando com o modelo padrão fica assim:
Flow Layout
HTML é uma linguagem de marcação que foi pensada para documentos, por isso o posicionamento padrão dos elementos é vertical. Esse modelo é conhecido como Flow Layout, e nele os elementos flutuam para o canto superior esquerdo e se ajustam para ocupar o espaço do seu conteúdo.
Por causa desse modelo padrão tanto o elemento html, quanto o elemento body, não se ajustam 100% da altura da tela, o que prejudica a estilização baseada em valores relativos a altura. Por isso temos que adicionar o seguinte estilo:
html,body { width: 100%; height: 100dvh;}
Com isso garantimos a consistência da largura, através da porcentagem, e da altura, através da unidade medida dvh (Altura Dinâmica da Viewport).
A viewport é o termo técnico para a janela do seu navegador, ou seja, tudo que não for barra de ferramentas é a viewport. Ela está como dinâmica porque no mobile a barra de navegação se altera a medida que o usuário rola na página.
Flexbox
Flexbox, ou para os íntimos flex, é um modelo unidirecional para a construção de layouts. Nele são definidos dois eixos o principal e cruzado.
Eixos
O eixo principal é aquele que cruza todos os elementos filhos de um contêiner. O eixo cruzado é aquele que cruza os elementos de maneira individual.
Por padrão o eixo principal é horizontal, mas isso pode ser alterado com esse estilo estilo:
.class { display: flex; flex-direction: column;}
Alinhamento horizontal e vertical
Para alinhar os elementos do eixo principal use a propriedade justify-items
.
.class { display: flex; justify-items: center;}
Para alinhar os elementos do eixo cruzado use a propriedade align-items
.
.class { display: flex; align-items: center;}
ATENÇÃO!! Quando se muda a direção do eixo, a referência do que é vertical e horizontal também muda.
Para alinhar os elementos do eixo cruzado use a propriedade align-items
.
.class { display: flex; flex-direction: column; align-items: center;}
Para alinhar os elementos do eixo principal use a propriedade justify-items
.
.class { display: flex; flex-direction: column; justify-items: center;}
Quebra de posicionamento de elementos
Outra funcionalidade do modelo flexbox é a possibilidade de quebrar o posicionamento de elementos, caso não exista espaço suficiente no contêiner pai.
.class { display: flex; flex-wrap: wrap;}
Espaço entre os elementos
Outra propriedade, não exclusiva do modelo flexbox, é o gap que é um espaçamento que pode ser adicionado entre os elementos.
.class { display: flex; gap: 1rem;}
Mas ai você pode se perguntar “Por que não usar uma margem, para dar o espaço?”. Isso é porque a margin não funcionaria corretamente com a quebra de posicionamento do flex-wrap
.
.class { display: flex; flex-wrap: wrap; gap: 1rem;}
Fator de crescimento do elemento
Nem sempre queremos que os elementos se dimensionem baseado em seu conteúdo, mas usar unidades de medida relativas, como porcentagens, para fazer isso pode ser uma dor de cabeça. Principalmente envolvendo quebras de elemento e alinhamento vertical e horizontal.
Por isso temos a propriedade flex-grow
, com ela podemos definir pesos dos elementos para eles se ajustarem e crescerem de acordo com nossa necessidade. Geralmente nós adicionamos essa propriedade diretamente no elemento que queremos que cresça e com o valor “1”.
.flex { display: flex;}
.grow { flex-grow: 1;}
Grid
Grid Layout é um modelo bidirecional para construção de layouts, ou seja, diferente do flex foca em mais de uma direção ao mesmo tempo. Com ele regiões da tela são definidas e os elementos podem sem manipuladas para ocuparem uma ou mais regiões.
.class { display: grid;}
Espaço entre os elementos
Outra propriedade, não exclusiva do modelo grid layout, é o gap que é um espaçamento que pode ser adicionado entre os elementos.
.class { display: grid; gap: 1rem;}
Linhas e colunas
Assim como uma tabela o grid também trabalha com linhas e colunas, mas a diferença é que existe uma unidade de medida especial fracionada (fr), que pode ser usada em conjunto com unidades.
.class { display: grid; gap: 1rem; grid-template-columns: 1fr 1fr; grid-template-rows: 1fr 1fr 1fr;}
Funções do Grid Layout
Como o grid layout introduz novos conceitos, ele também provém algumas funções para sanar alguns cenários: repeat()
, minmax()
e fit-content()
.
repeat()
como o nome já diz é para repetir os tamanhos das linhas ou colunas.
.class { grid-template-rows: 1fr 1fr 1fr 1fr 1fr 1fr;}
Utilizando a função repeat()
esse seria o equivalente a código acima:
.class { grid-template-rows: repeat(6, 1fr);}
minmax()
define os tamanhos máximos e mínimos das linhas ou colunas.
.class { grid-template-rows: minmax(20px, auto);}
fit-content()
funciona como oauto
, mas definindo um tamanho fixo que pode ser maior.
.class { grid-template-rows: fit-content(200px);}
Grid área
Como dito acima, o grid trabalha com linhas e colunas como uma tabela. Você deve estar se perguntando: “Tá, mas por que só não usar uma tabela?”. Ai que vem o pulo do gato no Grid Layout um elemento pode ocupar mais de uma célula.
Para fazer isso existe mais de uma maneira, mas eu recomendo o uso da grid área. Com ela podemos definir apelidos para os contêineres da nossa página, com a propriedade grid-area
, e criar um paralelo um para um com o uso da propriedade grid-template-areas
.
.grid { display: grid; gap: 1rem; grid-template-columns: repeat(2, 1fr); grid-template-rows: repeat(3, 1fr); grid-template-areas: "GRID_ITEM" "GRID_ITEM" "GRID_ITEM";}
.grid__item { grid-area: GRID_ITEM;}
No exemplo acima podemos ver que na classe .grid-item
é declarado o apelido, enquanto no contêiner principal os espaços onde GRID_ITEM
deve ocupar. Os contêineres em que não foi definida a grid-area
se encaixam com o comportamento padrão de uma célula.
Agora imagina que você tem uma tela com os seguintes elementos:
Agora vamos aplicar as grid áreas no formato que esperamos que nosso layout se ajuste:
.header { grid-area: HEADER;}
.aside { grid-area: ASIDE;}
.main { grid-area: MAIN;}
.footer { grid-area: FOOTER;}
.grid { display: grid; gap: 1rem; grid-template-areas: "HEADER HEADER" "ASIDE MAIN" "FOOTER FOOTER";}
Nesse cenário eu nem precisei declarar o número de linhas e colunas, mas eu poderia dizer que a coluna do aside
é para se ajustar automágicamente.
.grid { display: grid; gap: 1rem; grid-template-areas: "HEADER HEADER" "ASIDE MAIN" "FOOTER FOOTER"; grid-template-columns: auto 1fr;}
Grid span
Nem sempre nossos contêineres tem valor semântico para que o uso da grid área seja justificado. É ai que nós podemos declarar quantas linhas e colunas o nosso elemento irá ocupar, através das propriedades grid-row
e grid-column
juntamente com a palavra reservada span
, com ela não precisamos definir qual o ponto de início ou fim do alcance do elemento, assumindo a posição atual como referência.
.grid { display: grid; gap: 1rem; grid-template-columns: repeat(3, 1fr); grid-template-rows: repeat(3, 1fr);}
.grid__item { grid-column: span 2 / span 2; grid-row: span 3 / span 3;}