Solucionando Problemas com Grade do CSS e Flexbox: A Interface de Cartão
Portuguese (Português) translation by Erick Patrick (you can also view the original English article)
O padrão "cartão" (card) tem tido muito sucesso recentemente, mas sua construção ainda é limitada pelo CSS atual. Até agora. Ao combinar Grades do CSS com Flexbox, podemos criar cartões alinhados perfeitamente, responsivos e adaptáveis ao seus conteúdos. Vejamos como!
O Que Iremos Construir
Construiremos essa interface de cartão (veja a página completa para uma ideia melhor):
Em vários pontos de parada o posicionamento do cartão mudará assim:
Grades CSS x Flexbox
Quando o Flexbox chegou à cena CSS, vários agradeceram aos céus: finalmente tínhamos um módulo de layout para acabar com os problemas de flutuação (float). Mas não foi bem assim. O Flexbox funciona bem para distribuir elementos em um único eixo, seja horizontal (linha) ou vertical (coluna). Construir uma grade realmente fluida com Flexbox é difícil.
A Grade, por outro lado, foi feita para posicionar elementos nos doi eixos (ou dimensões): horizontalmente e verticalmente. Nesse tutorial usaremos os dois para aquilo que foram criados, obtendo uma solução realmente sólida. Comecemos!
Inspiração
Recentemente bbc.co.uk lançou (em beta) sua última iteração, bem limpa e espaçosa com a interface de cartões. Fora os títulos, isso está ótimo.



Os cartões do topo foram criados e alinhados em linha com Flexbox mas expandiremos o layout usando a Grade.



Nota: para acompanhar, é preciso um navegador que suporte a Grade. Veja mais informações sobre isso.
O Código do Cartão
Comecemos com a grade <div class="band">
, alguns itens de grade para posicionarmos <div class="item">
e algumas âncoras (cada uma delas será um cartão):
<div class="band"> <!-- grid item, containing a card --> <div class="item-1"> <a href="" class="card"> <div class="thumb"></div> <article> <h1>Post title</h1> <span>Author</span> </article> </a> </div> <!-- grid item, containing a card --> <div class="item-2"> ... </div> <!-- grid item, containing a card --> <div class="item-3"> ... </div> </div>
Coloque quantos cartões quiser: estamos usando sete aqui. Cada um tem uma minitatura <div class="thumb">
a qual daremos um plano de fundo mais tarde. E temos um <article>
que guarda um <h1>
, um <span>
para o autor e até um <p>
caso tenha mais informações.
Básico das Grades
Agora, usemos alguns estilos, arranjando cada um dos items em uma grade.
Nota: se for sua primeira mexida com Grades, talvez queira inteirar-se lendo a série inicial de tutoriais: Entendendo Layout em Grade do CSS.
Começaremos com o mobile, assim o recipiente receberá os primeiros estilos para largura, centralização e regras de Grade:
.band { width: 90%; max-width: 1240px; margin: 0 auto; display: grid; grid-template-columns: 1fr; grid-template-rows: auto; grid-gap: 20px; }
O mais importante, criamos a grade em .band
com display: grid;
. Ao declaramos grid-template-columns
de 1fr
, dizemos para cada coluna tomar uma fração igual do espaço disponível. Apenas declaramos uma, por hora, assim cada coluna preencherá toda a largura.
E adicionamos grid-template-rows: auto;
. Esse é o valor padrão e poderíamos omitir a propriedade. Com esse valor, as alturas serão determinadas puramente pelo conteúdo.
Por último, definiremos grid-gap
de 20px
, dando-nos o espaçamento entre as colunas e linhas.
Consultas de Mídia "Numero Uno"
Em resoluções mais largas (500px é totalmente arbitrário), mudaremos grid-template-columns
para termos até dois cartões por linha. Agora, temos duas colunas, cada uma tomando 1 fração d'um total de duas frações.
@media only screen and (min-width: 500px) { .band { grid-template-columns: 1fr 1fr; } }
Consultas de Mídia "Numero Dos"
Por último, para resoluções maiores, teremos quatro colunas.
@media only screen and (min-width: 850px) { .band { grid-template-columns: 1fr 1fr 1fr 1fr; } }
Aqui, poderíamos ter escrito, também, repeat(4, 1fr)
ao invés de 1fr 1fr 1fr 1fr
. Para mais informações sobre a unidade fr
, leia: Layout em Grade do CSS: Colunas Fluidas e Espaçamento Melhorado.
E o que isso nos gerou?
Estilizando os Cartões
Deu-nos um layout em grade bem sólido e, caso seja fã do brutalismo, pode deixar as coisas assim, mas para as outras pessoas, é bom melhorarmos a apresentação dos cartões.
Começaremos com isso:
.card { background: white; text-decoration: none; color: #444; box-shadow: 0 2px 5px rgba(0,0,0,0.1); display: flex; flex-direction: column; min-height: 100%; }
Isso nos dá os estilos básicos: plano de fundo branco, texto sem sublinhado, cor cinza e uma box-shadow
bacana para gerar profundidade.
Depois, atribuímos dispaly: flex;
ao cartão. Isso é importante–alinharemos o conteúdo dos cartões verticalmente, com Flexbox. Assim, também atribuiremos flex-direction: column;
para termos o eixo vertical. Por último, declaramos min-height: 100%;
para todos os cartões preencherem a altura do pai (item da grade). Bom trabalho! Agora temos:



Estado Sobreposto
Façamos dois outros aprimoramentos antes de continuar com Flexbox. Adicione position: relative;
e transition
para que movamos o cartão ao sobrepolo com o mouse.
position: relative; top: 0; transition: all .1s ease-in;
Então, ao sobrepor o mouse, mova um pouco o cartão e torne a sombra mais acentuada:
.card:hover { top: -2px; box-shadow: 0 4px 5px rgba(0,0,0,0.2); }
Tipografia
Agora, adicionaremos alguns estilos gerais para a tipografia, alterando as cores e espaçamento.
.card article { padding: 20px; } /* typography */ .card h1 { font-size: 20px; margin: 0; color: #333; } .card p { line-height: 1.4; } .card span { font-size: 12px; font-weight: bold; color: #999; text-transform: uppercase; letter-spacing: .05em; margin: 2em 0 0 0; }
Eis o que deveríamos ter:
Miniaturas
Cada miniatura será aplicada como imagem de plano de fundo, logo adicionaremos códigos para isso, assim:
<div class="thumb" style="background-image: url(thumb.jpg);"></div>
Agora, garantiremos que as divs .thumb
possuem dimensões e que as imagens de planos de fundo preenchem apropriadamente.
.card .thumb { padding-bottom: 60%; background-size: cover; background-position: center center; }
Bom trabalho. Com isso obtemos:
Artigo Flexbox
Agora, queremos o nome do autor alinhado ao rodapé do cartão, independente de quanto conteúdo tiver acima dele. É aqui que o Flexbox entra em ação:
.card article { padding: 20px; flex: 1; display: flex; flex-direction: column; justify-content: space-between; }
Usamos a versão compacta flex: 1;
para dizer que esse item flex (que ainda é um filho do container flex original) deve crescer para tomar todo o espaço disponível.
Então, declaramos que o artigo também é um artigo flex em si e, de novo, declararemos flex-direction: column;
para obter distribuição vertical. Por último, justify-content: space-between;
diz que todos os items flex internos deveriam espalhar-se pelo eixo, com espaçamento igual entre eles.
Tudo ótimo, mas o que obtemos são esses parágrafos estranhos no meio dos nossos cartões.



Para alinhá-los apropriadamente, adicionemos flex-grow: 1;
(ou apenas flex: 1;
) neles, para que preencham todo o espaço vertical restante, alinhando-se ao topo.
.card p { flex: 1; /* make p grow to fill available space*/ line-height: 1.4; }
Bem melhor!



Alterando a Grade
Nesse ponto, temos quase tudo pronto, mas algo que a Grade permite fazer agora é mudar completamente o layout ao posicionar nossos items de grade onde quisermos e em qualquer tamanho que quisermos. Para essa demonstração, queremos que o primeiro cartão (chamemo-no de "cartão destaque") tenha largura de duas colunas em todas as resoluções exceto a menor.
Em nossa primeira consulta de mídia, façamos isso:
@media only screen and (min-width: 500px) { ... .item-1 { grid-column: 1/ span 2; } }
Voltando ao tutorial introdutório sobre grades, aqui dizemos que além dos 500px o primeiro item deve começar na linha de grade 1 e tomar duas trilhas. O resto dos itens de grade preencherão o resto automaticamente.



Ainda na mesma consulta de mídia, também aumentamos font-size
do cabeçalho do nosso cartão destaque.
Conclusão
Esse foi um ótimo exercício em como usar Grades com Flexbox: a Grade lidou com o layout bi-dimensional e o Flexbox lidou com a distribuição vertical dos elementos dentro dos cartões. Divirta-se brincando com ele!
Leitura Adicional
- Série de tutoriais Entendendo Layout em Grade do CSS
- Devo usar Grades ou Flexbox? por Rachel Andrew
- Projetando Interfaces de Usuários Baseadas em Cartões, na Smashing Magazine
- Página inicial beta da bbc.co.uk
- Dica rápida: Adicione um Arquivo CSS com @support às Suas Demonstrações no CodePen