O elemento <picture>
não renderiza nada sozinho, mas atua como um mecanismo de decisão para um elemento <img>
interno,
informando o que será renderizado. <picture>
segue um precedente já definido pelos elementos <audio>
e <video>
: um elemento wrapper
que contém elementos <source>
individuais.
<picture>
<source …>
<source …>
<img …>
</picture …>
Esse <img>
interno também fornece um padrão substituto confiável para navegadores mais antigos sem suporte a imagens responsivas:
se o elemento <picture>
não for reconhecido pelo navegador do usuário, ele será ignorado. Os elementos <source>
também são descartados,
já que o navegador não os reconhecerá ou não terá contexto significativo sem um pai <video>
ou <audio>
.
No entanto, o elemento <img>
interno será reconhecido por qualquer navegador, e a fonte especificada no src
será renderizada conforme o esperado.
Imagens com "direção de arte" com <picture>
Fazer alterações no conteúdo ou na proporção de uma imagem com base no tamanho dela na página normalmente é chamado de imagens responsivas "direcionadas à arte". srcset
e sizes
foram projetados para funcionar de modo invisível, trocando as origens de acordo com as necessidades do navegador do usuário.
No entanto, há momentos em que você quer alterar as origens nos pontos de interrupção para destacar melhor o conteúdo, da mesma forma que adapta os layouts das páginas.
Por exemplo: uma imagem de cabeçalho de largura total com um pequeno foco central pode funcionar bem em uma janela de visualização grande:
Mas, quando reduzida para se adequar a janelas de visualização pequenas, o foco central da imagem pode ser perdido:
![Imagem com a largura do cabeçalho de uma flor azul-lavanda, reduzida. A abelha quase não está visível.](https://web.dev/static/learn/images/prescriptive/image/a-header-width-image-a-p-a272cd48c084e.png?authuser=6&hl=pt-br)
O assunto dessas origens de imagem é o mesmo. No entanto, para focar melhor esse assunto visualmente, as proporções da origem da imagem precisam mudar nos pontos de interrupção. Por exemplo, um zoom mais restrito no centro da imagem e alguns detalhes nas bordas são cortados:
Esse tipo de "corte" pode ser feito com CSS, mas faria com que o usuário solicitasse todos os dados que compõem a imagem, mesmo que nunca a vejam.
Cada elemento source
tem atributos que definem as condições para a seleção desse source
: media
, que aceita uma
consulta de mídia, e type
, que aceita um tipo de mídia (anteriormente conhecido como "tipo MIME"). O primeiro <source>
na ordem
de origem para corresponder ao contexto de navegação atual do usuário é selecionado, e o conteúdo do atributo srcset
nessa source
será usado para determinar os candidatos certos para esse contexto. Neste exemplo, a primeira source
com um atributo media
que corresponde ao tamanho da janela de visualização do usuário será selecionada:
<picture>
<source media="(min-width: 1200px)" srcset="wide-crop.jpg">
<img src="close-crop.jpg" alt="…">
</picture>
É necessário sempre especificar o img
interno por último na ordem. Se nenhum dos elementos source
corresponder aos critérios media
ou type
, a imagem atuará como uma fonte "padrão". Se você estiver usando consultas de mídia min-width
, é recomendável ter as maiores
origens primeiro, conforme mostrado no código anterior. Ao usar consultas de mídia max-width
, coloque a menor origem primeiro.
<picture>
<source media="(max-width: 400px)" srcset="mid-bp.jpg">
<source media="(max-width: 800px)" srcset="high-bp.jpg">
<img src="highest-bp.jpg" alt="…">
</picture>
Quando uma fonte é escolhida com base nos critérios especificados, o atributo srcset
em source
é transmitido para o
<img>
como se tivesse sido definido na própria <img>
. Isso significa que você pode usar sizes
para otimizar também
origens de imagens direcionadas à arte.
<picture>
<source media="(min-width: 800px)" srcset="high-bp-1600.jpg 1600w, high-bp-1000.jpg 1000w">
<source srcset="lower-bp-1200.jpg 1200w, lower-bp-800.jpg 800w">
<img src="fallback.jpg" alt="…" sizes="calc(100vw - 2em)">
</picture>
Obviamente, uma imagem com proporções que podem variar dependendo do elemento <source>
selecionado gera um problema de desempenho:
<img>
oferece suporte apenas a um único atributo width
e height
, mas omitir esses atributos pode levar a uma experiência do usuário consideravelmente pior.
Para isso, uma adição relativamente recente,
com suporte,
à especificação HTML permite o uso dos atributos height
e width
nos elementos <source>
. Elas trabalham para reduzir as mudanças de layout da mesma forma
que fazem em <img>
, com o espaço adequado reservado no layout para qualquer elemento <source>
que estiver selecionado.
<picture>
<source
media="(min-width: 800px)"
srcset="high-bp-1600.jpg 1600w, high-bp-1000.jpg 1000w"
width="1600"
height="800">
<img src="fallback.jpg"
srcset="lower-bp-1200.jpg 1200w, lower-bp-800.jpg 800w"
sizes="calc(100vw - 2em)"
width="1200"
height="750"
alt="…">
</picture>
É importante observar que a direção de arte pode ser usada para mais do que decisões baseadas no tamanho da janela de visualização. Isso seria necessário, já que
a maioria desses casos pode ser processada de maneira mais eficiente com srcset
/sizes
. Por exemplo, selecionar uma fonte de imagem mais adequada
ao esquema de cores ditado pela preferência do usuário:
<picture>
<source media="(prefers-color-scheme: dark)" srcset="hero-dark.jpg">
<img srcset="hero-light.jpg">
</picture>
O atributo type
O atributo type
permite que você use o mecanismo de decisão de solicitação única do elemento <picture>
para veicular formatos de imagem
apenas para navegadores com suporte a eles.
Como você aprendeu em Formatos e compactação de imagens, uma codificação que o navegador não puder analisar nem será reconhecida como dados de imagem.
Antes da introdução do elemento <picture>
, as soluções de front-end mais viáveis para exibir novos formatos de imagem exigiam
que o navegador solicitasse e tentasse analisar um arquivo de imagem antes de determinar se ele seria descartado e carregasse um substituto. Um exemplo comum foi um script com estas linhas:
<img src="image.webp"
data-fallback="image.jpg"
onerror="this.src=this.getAttribute('data-fallback'); this.onerror=null;"
alt="...">
Com esse padrão, uma solicitação de image.webp
ainda seria feita em todos os navegadores, o que significa uma transferência desperdiçada para navegadores
sem suporte ao WebP. Os navegadores que não conseguiam analisar a codificação WebP gerariam um evento onerror
e trocariam
o valor data-fallback
por src
. Era uma solução dispendiosa, mas, novamente, abordagens como essa eram a única opção
disponível no front-end. Lembre-se de que o navegador começa a fazer solicitações de imagens antes que qualquer script personalizado possa ser executado ou até mesmo analisado. Portanto, não foi possível forçar a interrupção desse processo.
O elemento <picture>
foi projetado explicitamente para evitar essas solicitações redundantes. Embora ainda não haja como um navegador
reconhecer um formato incompatível sem solicitá-lo, o atributo type
avisa o navegador sobre as codificações
de origem antecipadamente para que ele possa decidir se vai fazer uma solicitação ou não.
No atributo type
, forneça o tipo de mídia (anteriormente, tipo MIME)
da origem da imagem especificada no atributo srcset
de cada <source>
. Isso fornece ao navegador todas as informações
necessárias para determinar imediatamente se a imagem candidata a imagem fornecida por source
pode ser decodificada sem fazer solicitações
externas. Se o tipo de mídia não for reconhecido, o <source>
e todos os candidatos serão desconsiderados, e o navegador vai avançar.
<picture>
<source type="image/webp" srcset="pic.webp">
<img src="pic.jpg" alt="...">
</picture>
Aqui, qualquer navegador compatível com a codificação WebP reconhecerá o tipo de mídia image/webp
especificado no atributo type
do elemento <source>
, selecione esse <source>
e, como fornecemos apenas um candidato em srcset
, instruirá o
<img>
interno a solicitar, transferir e renderizar pic.webp
. Qualquer navegador sem suporte para WebP desconsiderará o source
e
ausente qualquer instrução em contrário, o <img>
renderizará o conteúdo de src
da mesma forma que vem sendo feito desde 1992.
Não é necessário especificar um segundo elemento <source>
com type="image/jpeg"
aqui. Você pode presumir que o suporte universal para JPEG seja oferecido.
Independentemente do contexto de navegação do usuário, tudo isso é feito com uma única transferência de arquivo, sem desperdício de largura de banda em
origens de imagem que não podem ser renderizadas. Isso também é inovador: uma vez que formatos de arquivo mais novos e eficientes virão
com os próprios tipos de mídia, e poderemos aproveitá-los graças ao picture
, sem JavaScript, dependências
do servidor e toda a velocidade do <img>
.
O futuro das imagens responsivas
Todos os padrões de marcação discutidos aqui foram um grande aumento em termos de padronização: mudar a funcionalidade de
algo estabelecido e central na Web como o <img>
não foi um trabalho fácil e o conjunto de problemas que essas mudanças visavam
resolver eram abrangentes para dizer o mínimo. Se você já se pegou pensando que há muito espaço para melhorar com esses padrões de marcação, você está certo. Desde o início, esses padrões tinham como objetivo fornecer uma linha de base para a criação de
tecnologias futuras.
Todas essas soluções dependiam necessariamente da marcação, para serem incluídas no payload inicial do servidor
e chegarem a tempo para o navegador solicitar origens de imagem, uma limitação que levava ao atributo sizes
claramente difícil de administrar.
No entanto, como esses recursos foram introduzidos à plataforma Web, um método nativo de adiar solicitações de imagem foi introduzido.
Elementos <img>
com o atributo loading="lazy"
não são solicitados até que o layout da página seja conhecido para adiar
solicitações de imagens fora da janela de visualização inicial do usuário até mais tarde no processo de renderização da página, possivelmente evitando
solicitações desnecessárias. Como o navegador entende totalmente o layout da página no momento em que essas solicitações são feitas, um
atributo sizes="auto"
foi proposto como uma adição à especificação HTML
para evitar a tarefa de criar atributos sizes
escritos manualmente nesses casos.
Também fizemos adições ao elemento <picture>
no horizonte para corresponder a algumas mudanças excepcionalmente interessantes
na forma como estilizamos os layouts de página. Embora as informações da janela de visualização sejam uma base sólida para decisões de layout de alto nível, elas
impedem uma abordagem de desenvolvimento totalmente de componente, ou seja, um componente que pode ser inserido em
qualquer parte de um layout de página, com estilos que respondem ao espaço que o próprio componente ocupa. Essa preocupação levou
à criação de consultas de contêiner, um método de definir o estilo dos elementos
com base no tamanho do contêiner pai, e não apenas na janela de visualização.
Embora a sintaxe de consulta do contêiner tenha apenas se estabilizado e o suporte ao navegador seja muito limitado, até o momento deste artigo, a adição das tecnologias de navegador que a ativam fornece ao elemento <picture>
uma forma de fazer a mesma coisa: um possível atributo container
que permite critérios de seleção <source>
com base no espaço que o <img>
do elemento <picture>
ocupa, em vez de se basear no tamanho da janela de visualização.
Se isso parece um pouco vago, bem, há um bom motivo: essas discussões sobre padrões da Web estão em andamento, mas estão longe de serem resolvidas. Ainda não é possível usá-las.
Embora a marcação de imagem responsiva prometa apenas ficar mais fácil de trabalhar com o tempo, como qualquer tecnologia da Web, há vários serviços, tecnologias e frameworks para ajudar a aliviar o fardo de escrever à mão essa marcação disponível. No próximo módulo, veremos como integrar tudo o que aprendemos sobre formatos de imagem, compactação e imagens responsivas em um fluxo de trabalho de desenvolvimento moderno.