Acredito que não há dúvidas de que o design responsivo veio pra ficar e que não está mais apenas na moda. Mais do que ficar pensando em tamanhos específicos de telas ou em mobile e tablet, minha opinião é que esqueçamos isso. Com a variedade de smartphones diferentes que existem hoje, acho difícil separarmos o que é mobile do que é tablet ou desktop. Um exemplo disso é o Viewport sizes, que traz uma lista completa com os tamanhos dos viewports de vários dispositivos diferentes. Mas isso é só a minha opinião.
Acredito que o principal é fazer com que o seu conteúdo, independente de resolução ou tela, seja acessível pro usuário; afinal, e muitas vezes esquecemos disso, é exatamente isso que importa: que o usuário encontre a informação que procura. Quem aqui nunca entrou em algum site para procurar algo e por um motivo xis não conseguiu acessar aquela informação, seja por ela não estar disposta de forma correta, ou por algum problema cross-browser e por aí vai…
Adaptando seu conteúdo
Pra mim, uma das principais vertentes que o design responsivo trouxe foi a priorização de volta no conteúdo. Mais que qualquer coisa, devemos focar na informação que deve ser passada e garantir que ela seja acessada independente de dispositivo ou resolução.
E nesse caminho das pedras, uma hora ou outra teremos que trabalhar com um tipo de conteúdo que pode variar. E aí, como fazer? Nesses dias cai numa situação desse tipo e vi que há diversos caminhos para resolver esse problema.
O problema do conteúdo variável
Jogo rápido: imaginem uma lista disposta horizontalmente com 5 itens. Podemos pensar então que em uma determinada resolução em que cada item teria 20% de largura da lista e em um determinado breakpoint cada item ficaria com a largura total da lista (ou se formos pelo lado do mobile first, cada item teria por padrão a largura inteira da lista e, só a partir de um determinado breakpoint que ele ficaria com a nova largura de 20%).
.list li { width: 20%; float: left; } @media screen and (max-width: 768px) { width: 100%; float: none; }
Ou, se pensarmos numa abordagem mobile first (apenas a encargo de exemplo):
@media screen and (min-width: 768px) { width: 20%; float: left; }
Beleza, matou! Mas, e se a quantidade de itens variar? Por exemplo entre 3 e 5? Me deparei com uma situação semelhante alguns dias atrás e meu primeiro pensamento foi: antes da renderização dos elementos na página eu vejo quantos itens tem ali e, dependendo do resultado, coloco uma classe na lista. Algo mais ou menos assim:
.list li { float: left; } .list-3 li { width: 33.3%; } .list-4 li { width: 25%; } .list-5 li { width: 20%; }
Resolve o problema? Resolve. Mas nem sempre temos essa opção, de contar por exemplo com o lado do servidor para nos retornar o número de itens. Aí nesse caso, uma outra solução seria via JavaScript, seguindo o mesmo pensamento: contar os elementos e de acordo com o resultado, aplicar uma classe na lista.
E tem ainda uma outra coisa: nesse caso, nem estamos pensando ainda em breakpoints e variações de resolução. Paramos ainda no primeiro ponto que é simplesmente que o seu conteúdo esteja bem disposto numa resolução qualquer; para depois disso, podermos pensar na estratégia a ser seguida.
Dando uma pesquisada na Barsa da Internet, vi que daria para resolver esse problema apenas com o velho e bom CSS.
Contando os elementos
A ideia básica é, através do CSS, descobrirmos quantos itens estão presentes na lista e a partir daí aplicarmos a largura correta para cada item. Mas, como contar? Podemos usar a magia negra dos pseudo seletores pra nos ajudar com isso.
O cara nth-last-child
Esse brother aí, nada mais faz do que contar o elemento partindo do seu último item. Então, se quiséssemos, por exemplo, selecionar o segundo item da lista, mas iniciando a contagem do fim, faríamos algo assim:
.list li:nth-last-child(2) { border: solid 1px red; }
Uma representação bem simples do item selecionado:
- item 1 (selecionado)
- item 2 (selecionado)
- item 3 (selecionado)
- item 4 (selecionado)
- item 5
Tendo ideia de como selecionar um elemento, podemos estabelecer a seguinte linha de raciocínio:
- temos que saber exatamente quantos itens temos, chegando no primeiro elemento da lista.
- selecionar todos os elementos irmãos.
Vamos por parte… Conseguimos matar o primeiro item utilizando o que vimos no exemplo anterior. Então, partindo de uma lista de 5 itens, poderíamos fazer algo assim:
.list li:nth-last-child(5), .list li:nth-last-child(5) ~ li { width: 20%; // \o/ }
E shaaazam! Conseguimos teoricamente contar quantos elementos temos na lista. Agora é só aplicarmos as demais variações.
list li:nth-last-child(3), .list li:nth-last-child(3) ~ li { width: 33.3%; } .list li:nth-last-child(4), .list li:nth-last-child(4) ~ li { width: 25%; } .list li:nth-last-child(5), .list li:nth-last-child(5) ~ li { width: 20%; }
Fiz um exemplo rápido no CodePen com o que falamos aqui.
HTML
<ul class="list"> <li>1</li> <li>2</li> <li>3</li> </ul> <ul class="list"> <li>1</li> <li>2</li> <li>3</li> <li>4</li> </ul> <ul class="list"> <li>1</li> <li>2</li> <li>3</li> <li>4</li> <li>5</li> </ul>
CSS
* { box-sizing: border-box; } .list { background-color: #f5f5f5; height: 50px; margin: 10px 0; list-style-type: none; padding: 0; } .list li { background-color: #bbb; color: #fff; text-align: center; height: 50px; float: left; line-height: 40px; font-size: 24px; border: solid 5px #aaa; } .list li:nth-last-child(3), .list li:nth-last-child(3) ~ li { width: 33.3%; } .list li:nth-last-child(4), .list li:nth-last-child(4) ~ li { width: 25%; } .list li:nth-last-child(5), .list li:nth-last-child(5) ~ li { width: 20%; }
RESULT
Algumas referências e links legais:
Gostou? Escrevi alguma groselha? Quer melhorar? Abra uma issue mencionando o post e vamos conversar.
***
Artigo originalmente publicado em: http://www.raphaelfabeni.com.br/contando-elementos-nth-last-child/