Quem já trabalha há algum tempo com CSS certamente já deve ter se deparado com uma questão: como fazer uma imagem ocupar a largura total em um layout com limite de largura? Existem diferentes técnicas para alcançar o efeito, mas a que está apresentada aqui certamente vai surpreender você!
Para conteúdos mais extensos, normalmente é uma boa idéia limitar o comprimento de linha para facilitar a legibilidade. Até então, a maneira mais fácil de fazer isso é envolver o conteúdo do post em um contêiner:
1 2 3 4 5 |
.u-containProse { margin-left: auto; margin-right: auto; max-width: 40em; } |
1 2 3 4 |
<div class="u-containProse"> <p>...</p> <p>...</p> </div> |
Mas e se for preciso que algum conteúdo se estenda para além dos limites do contêiner? Certas imagens podem ter maior impacto se preencherem toda a viewport.
Usando técnicas não tão atuais, era possível resolver a questão envolvendo tudo, exceto imagens de largura total, com a classe de contêiner:
1 2 3 4 5 6 7 8 9 |
<div class="u-containProse"> <p>...</p> </div> <img src="..." alt="..."> <div class="u-containProse"> <p>...</p> </div> |
Mas adicionar esses contêineres a cada postagem torna-se tedioso muito rapidamente — sem contar que pode ser bem complicado implementar a técnica quando sistema de gerenciamento de conteúdo estão envolvidos.
Um passo natural para tentar resolver o problema pode ser tentar limitar a largura de elementos descendentes específicos (parágrafos, listas etc.):
1 2 3 4 5 6 7 8 |
.u-containProse p, .u-containProse ul, .u-containProse ol, .u-containProse blockquote /* etc. */ { max-width: 40em; margin-left: auto; margin-right: auto; } |
Além de esse seletor dar pesadelos em muita gente, essa técnica pode causar sobreposições de largura, margens e outros problemas de comportamentos inesperados dentro dos conteúdos. Também, não resolverá o problema se o CMS usado envolver imagens soltas em parágrafos.
O problema com ambas as soluções é que elas complicam os elementos mais comuns (parágrafos e outros conteúdos) ao invés dos outliers (imagens de largura total).
Solução para imagem de largura total em layout com limite de largura
Para liberar o elemento filho de seu contêiner, é preciso saber quanto espaço há entre a borda do contêiner e o limite da viewport, o que dá metade da largura da viewport menos a metade da largura do contêiner. É possível determinar esse valor usando a função calc(), unidades de viewport e a boa e velha porcentagem (para a largura do container):
1 2 3 4 |
.u-release { margin-left: calc(-50vw + 50%); margin-right: calc(-50vw + 50%); } |
Voilà! Qualquer imagem/elemento com esta classe aplicada ocupará a largura total da tela, independentemente do tamanho do contêiner. Aqui está em ação:
See the Pen Full-width element in fixed-width container example by Tyler Sticka (@tylersticka) on CodePen.
Navegadores que não suportam calc()
ou unidades de viewport, como Opera Mini, simplesmente as ignorarão.
Um grande problema
Essa solução é demais, é tão mais inteligente, direta, previsível e concisa em comparação com outras técnicas! Mas, se não observar com cuidado, pode ser que um pequeno grande problema passe despercebido: uma barra de rolagem horizontal!
Em qualquer página com esta classe de utilidade em uso, uma barra de rolagem vertical visível sempre será acompanhada por uma barra de rolagem horizontal desagradável. As páginas mais curtas não sofrerão esse problema e os navegadores sem barras de rolagem visíveis (iOS Safari, Android Chrome etc.) também parecerão imunes.
A solução para esta degraça de barra de rolagem horizontal pode ser encontrada ao ler a especificação sobre unidades de viewport:
Os comprimentos de viewport em porcentagem são relativos ao tamanho do bloco que contém (containing block) inicial. Quando a altura ou largura do containing block inicial é alterada, eles são dimensionados de acordo. No entanto, quando o valor do overflow no elemento raiz é auto, quaisquer barras de rolagem são assumidas como não existentes. Observe que o tamanho do containing block inicialmente é afetado pela presença de barras de rolagem na viewport. (grifo nosso)
Traduzindo: unidades de viewport não levam em conta as dimensões da barra de rolagem a menos que se defina explicitamente os valores de overflow
para scroll
— mas nem isso funciona no Chrome ou no Safari (bugs aqui e aqui).
Mas existe um macete que pode ser usado:
1 2 3 4 |
html, body { overflow-x: hidden; } |
É uma pena que (no momento) isso seja mesmo necessário… Torçamos para que os bugs sejam arrumados o quanto antes.