Design de edifícios

Uma olhada no processo e nas ferramentas usadas para criar a experiência de datas comemorativas da Designcember.

No clima de dezembro e das muitas agendas que as pessoas usam para fazer contagem regressiva e comemorar, queríamos destacar o conteúdo da web da comunidade e da equipe do Google Chrome. Todos os dias, destacamos um conteúdo relacionado a design e desenvolvimento da interface, totalizando 31 destaques, incluindo 26 novos sites de demonstração, ferramentas, anúncios, podcasts, vídeos, artigos e estudos de caso.

Veja a experiência completa em designcember.com.

O site da Designcember.

Visão geral

Nosso objetivo era proporcionar uma experiência na Web acessível, extravagante, moderna e responsiva em poucos bytes. Queríamos destacar novas APIs responsivas, como consultas de contêiner, e incluir um belo exemplo de modo escuro em um site focado em design e com muitos recursos. Para conseguir isso, compactamos arquivos, oferecemos vários formatos, usamos ferramentas de criação otimizadas para a geração de sites estáticos, enviamos um novo polyfill e muito mais.

Começando com capricho

A ideia em torno do site do calendário da Designcember era funcionar como uma vitrine de todo o trabalho que queríamos destacar durante todo o mês de dezembro, agindo como um próprio site de demonstração. Decidimos construir um edifício de apartamentos responsivo que poderia ficar mais alto e mais estreito ou mais curto e mais largo, com janelas que se reorganizavam dentro do quadro. Cada janela representa um dia (e, portanto, uma parte do conteúdo). Trabalhamos com a ilustradora Alice Lee para dar vida à nossa visão.

Esboços do esqueleto da página da Designcember.

Alice foi uma inspiração e compartilhou processos e esboços que eram empolgantes até mesmo nos primeiros conceitos. Enquanto ela trabalhava na arte, hackeamos a arquitetura. As primeiras discussões foram sobre o layout do macro, o prédio e suas janelas. Como as janelas se adaptariam a uma, duas ou três colunas à medida que mais espaço da janela de visualização ficasse disponível? Até onde eles poderiam encolher ou esticar? Qual seria o tamanho máximo do edifício? Quanto as janelas mudariam?

Confira uma prévia de um protótipo responsivo usando o grid-auto-flow: dense (link em inglês) mostrando como as janelas podem ser colocadas automaticamente pelo algoritmo de grade. Percebemos rapidamente que, embora as grades de proporção tenham um ótimo desempenho para mostrar arte, elas não ofereciam a oportunidade de deixar as janelas crescerem e encolherem em um espaço disponível não uniforme e mostrar o poder das consultas de contêiner.

Animação que mostra como este wireframe responde a diferentes tamanhos de tela.
Confira esta demonstração do CodePen.

Quando a grade geral ficou relativamente estável e comunicava um senso de direção para a capacidade de resposta do edifício e das janelas, poderíamos nos concentrar em uma única janela. Algumas janelas esticaram, encolhiam, apertaram, cresceram e se recomporam mais do que outras na grade.

Wireframes mostrando como as janelas são exibidas em diferentes pontos de interrupção.

Cada janela precisaria lidar com uma certa turbulência de redimensionamento. Abaixo está o protótipo de uma janela demonstrando sua capacidade de resposta à turbulência, mostrando quanto podemos esperar que cada janela interativa seja ajustada.

Animação de janela com spritesheets

Algumas janelas têm animações para aumentar a interação. As animações são desenhadas à mão, frame a frame, no Photoshop. Cada frame é exportado, transformado em uma Folha de sprite com este gerador de folhas de sprite e otimizado com o Squoosh. A animação CSS usa background-position-x e animation-timing-function, conforme mostrado no exemplo a seguir.

.una
  background: url("/day1/una_sprite.webp") 0% 0%;
  background-size: 400% auto;
}

.day:is(:hover, :focus-within) .una {
  animation: una-wave .5s steps(1) alternate infinite;
}

@keyframes una-wave {
  0%  { background-position-x: 0%; }
  25% { background-position-x: 300%; }
  50% { background-position-x: 200%; }
  75% { background-position-x: 100%; }
}

Animação mostrando a janela do primeiro dia.

Algumas animações, como o cofrinho do sexto dia, eram animações CSS baseadas em etapas. Esse efeito foi alcançado com uma técnica semelhante, usando steps(). A diferença é que os frames-chave eram posições de transformação do CSS, e não posições em segundo plano.

Mascaramento de CSS

Algumas janelas tinham formas exclusivas. Usamos máscaras e aspect-ratio para criar uma janela adaptável, adaptável e de forma exclusiva.

Para criar uma máscara, como esta para a janela 8, eram necessárias algumas habilidades clássicas no Photoshop, além de um pouco de conhecimento sobre como as máscaras funcionam na Web. Vamos conferir a janela do oitavo dia.

Janela para o oitavo dia.

Para se tornar uma máscara, a forma interna do tipo trevo de quatro folhas precisa ser isolada como uma forma própria e preenchida com a cor branca. O branco informa ao CSS qual conteúdo permanece, e tudo o que está fora de branco não. No Photoshop, a parte interna da janela foi selecionada, com a plumagem de 1 px (para remover problemas de distorção), depois preenchida com branco e exportada com a mesma altura e largura do frame da janela. Dessa forma, a moldura e a máscara podem ser colocadas em camadas diretamente uma sobre a outra, mostrando o conteúdo interno dentro do frame conforme esperado.

Imagem da máscara de trevo

Depois de concluído, o conteúdo da janela pode ser modificado e sempre parece permanecer dentro do frame personalizado. A imagem a seguir mostra a versão do modo escuro da janela, com um gradiente de plano de fundo diferente e um filtro CSS de brilho aplicado à luz.

Janela do oitavo dia no modo escuro.

O mascaramento também oferece suporte a janelas responsivas baseadas em consultas de contêiner. Na janela nove, há um personagem que fica escondido atrás de uma máscara até que a janela fique em um tamanho mais estreito. Para garantir que o usuário não possa ajustar a imagem para fora do enquadramento, Alice completou o caractere completo para nós. O personagem é mascarado dentro da janela, mas as plantas não estão, então outro desafio que enfrentamos foi sobrepor elementos mascarados com camadas não mascaradas e garantir que todos eles dimensionem bem juntos.

A imagem abaixo mostra a aparência sem a máscara na janela e no personagem.

Imagem da janela nove sem a máscara.

Brinquendo com a arte

Para manter a fidelidade da ilustração e garantir que telas de alta definição não tenham uma experiência de usuário desfocada, Alice trabalhou com uma proporção de 3x pixels. O plano era usar o imgix e fornecer imagens e formatos otimizados em seu servidor, mas descobrimos que o ajuste manual com a ferramenta Squoosh poderia nos poupar 50% ou mais.

Como usar o Squoosh para compactar imagens.

A ilustração tem desafios únicos para compressão, especialmente o pincelada e o estilo transparente de borda áspera usada por Alice. Escolhemos Squoosh cada 3x imagens png exportadas do Photoshop para um png, uma webp e um avif menores. Cada tipo de arquivo possui seus próprios recursos de compactação especiais, e foi necessário compactar mais de 50 imagens para encontrar algumas configurações de otimização comuns.

A CLI Squoosh se tornou fundamental, com mais de 200 imagens para otimizar. Fazer tudo isso manualmente levaria dias. Depois de criar as configurações comuns de otimização, nós as fornecemos como instruções de linha de comando e processamos em lote pastas inteiras de imagens PNG nos formatos WebP e AVIF compactados.

Veja um exemplo do comando squoosh da CLI AVIF usado:

npx @squoosh/cli --quant '{"enabled":true,"zx":0,"maxNumColors":256,"dither":1}' --avif '{"cqLevel":19,"cqAlphaLevel":17,"subsample":1,"tileColsLog2":0,"tileRowsLog2":0,"speed":6,"chromaDeltaQ":false,"sharpness":5,"denoiseLevel":0,"tune":0}' image-1.png image-2.png image-3.png

Com a arte otimizada incluída no repositório, podemos começar a carregá-la de HTML:

<picture>
  <source srcset="/day1/inner-frame.avif" type="image/avif">
  <source srcset="/day1/inner-frame.webp" type="image/webp">
  <img alt="" decoding="async" role="presentation" src="/day1/inner-frame.png">
</picture>

Escrever o código-fonte da imagem foi repetitivo, então criamos um componente Asstro para incorporar imagens com uma linha de código.

<Pic filename="day1/inner-frame" role="presentation" />

Usuários de leitores de tela e teclado

Grande parte da experiência da DesignCember é pela arte e janelas interativas. Era importante para nós que um usuário de teclado pudesse acessar o site e abrir as janelas, e que os usuários de leitores de tela tivessem uma boa experiência narrada.

Por exemplo, ao incorporar as imagens, usamos role="presentation" para marcar a imagem como apresentação para leitores de tela. Achamos que uma experiência do usuário de 5 a 12 descrições de alt quebradas seria uma experiência ruim. Assim, marcamos as imagens como de apresentação e oferecemos uma narração geral da janela. Navegar pelas janelas em um leitor de tela proporciona uma boa narrativa, e esperávamos que fosse mais divertido que o site pudesse ser compartilhado.

O vídeo a seguir mostra uma demonstração da experiência com o teclado. As teclas Tab, Enter, barra de espaço e Esc são usadas para orquestrar o foco de/para os pop-ups e as janelas.

A experiência do leitor de tela tem atributos ARIA especiais que trazem clareza ao conteúdo. Por exemplo, os links para os dias dizem apenas "um" ou "dois", mas com alguns ARIA adicionados, eles são anunciados como "Dia um" e "Dia dois". Além disso, todas as imagens são resumidas em um único rótulo para que cada janela tenha uma descrição.

Astro, gerador de sites estático em primeiro lugar

O Astro facilitou o trabalho em equipe no site. Os desenvolvedores do Angular e do React já conheciam o modelo do componente, e o sistema de estilo de nome de classe com escopo ajudava cada desenvolvedor a saber que trabalhar em uma janela não entraria em conflito com mais ninguém.

Dias como componentes

Cada dia era um componente que buscava o status em um armazenamento de dados de tempo de build. Isso nos permitiu executar a lógica do modelo antes que o HTML chegasse ao navegador. A lógica determina se o dia deve mostrar a dica ou não, já que os dias inativos não têm pop-ups.

Os builds são executados a cada hora, e o repositório de dados de tempo de build desbloqueia um novo dia quando o servidor de build passava da meia-noite. Esses pequenos sistemas autossuficientes e com atualização automática mantêm o site atualizado.

Estilos com escopo e objetos abertos

O Astro estilos de escopo escritos dentro do seu modelo de componente, o que facilitou a distribuição da carga de trabalho entre vários membros da equipe e também tornou divertido o uso de disposições abertas. Os estilos Open Props normalize.css foram úteis com o tema adaptável (claro e escuro), além de ajudar a organizar conteúdos, como parágrafos e cabeçalhos.

Como usuário inicial do Astro, encontramos alguns problemas com o PostCSS. Por exemplo, não foi possível atualizar para a versão mais recente do Astro devido a muitos problemas de build. Você poderia dedicar mais tempo a esse processo, otimizando os fluxos de trabalho de criação e desenvolvimento.

Contêineres flexíveis

Algumas janelas aumentam e encolhem, mantendo a proporção para preservar a arte. Usamos outras janelas para demonstrar o poder da arquitetura baseada em componentes com consultas de contêiner. Com as consultas de contêiner, as janelas poderiam ter as próprias informações de estilo responsivo e reajustadas com base nos próprios tamanhos. Algumas janelas passaram de estreitas a amplas, e era necessário ajustar o tamanho da mídia dentro delas, bem como o posicionamento dessa mídia.

Uma demonstração de como as janelas mudam conforme têm mais espaço.

Conforme mais espaço fica disponível para uma janela, podemos adaptar o tamanho ou os elementos filhos dela. Aconteceu que, para atender às janelas adaptáveis, as consultas de contêiner não seriam apenas divertidas de mostrar, elas seriam necessárias e simplificaria muito a orquestração de determinados layouts.

.day {
  container: inline-size;
}

.day > .pane {
  min-block-size: 250px;

  @container (min-width: 220px) {
    min-block-size: 300px;
  }

  @container (min-width: 260px) {
    min-block-size: 310px;
  }

  @container (min-width: 360px) {
    min-block-size: 450px;
  }
}

Essa abordagem é diferente de manter uma proporção. Ele oferece mais controle e mais oportunidades. Em um determinado tamanho, muitos filhos mudam para se adaptar a um novo layout.

As consultas de contêiner também nos permitiram oferecer suporte à contenção na direção do bloco (vertical), de modo que, à medida que uma janela aumentasse, pudéssemos ajustar os estilos dela para caber de maneira adequada. Isso pode ser observado nas consultas baseadas em altura, as quais usamos de forma independente, e também nas consultas baseadas em largura:

.person {
  place-self: flex-end;
  margin-block: 25% 50%;
  margin-inline-start: -15%;
  z-index: var(--layer-1);

  @container (max-height: 350px) and (max-width: 425px) {
    place-self: center flex-end;
    inline-size: 50%;
    inset-block-end: -15%;
    margin-block-start: -2%;
    margin-block-end: -25%;
    z-index: var(--layer-2);
  }
}

Também usamos consultas de contêiner para mostrar e ocultar detalhes à medida que a arte ficava cada vez mais lotada em tamanhos menores e mais vazia em tamanhos maiores. A janela nove é um ótimo exemplo de onde isso entrou em jogo:

Suporte a vários navegadores

Para criar uma experiência incrível e moderna entre navegadores, especialmente para APIs experimentais, como consultas de contêiner, precisamos de um ótimo polyfill. Enviamos um aviso para nossa equipe, e Surma liderou a criação de um novo polyfill de consulta de contêiner (link em inglês). O polyfill depende de ResizeObserver, MutationObserver e a função:is() do CSS. Portanto, todos os navegadores mais recentes são compatíveis com o polyfill, especificamente o Chrome e o Edgefrom versão 88, o Firefox a partir da versão 78 e o Safari a partir da versão 14. O uso do polyfill permite qualquer uma das seguintes sintaxes:

/* These are all equivalent */
@container (min-width: 200px) {
  /* ... */
}
@container (width >= 200px) {
  /* ... */
}
@container size(width >= 200px) {
  /* ... */
}

Modo escuro

As versões em modo claro e escuro do site da Designcember, lado a lado.

Um último toque que foi essencial para o site da Designcember foi um lindo tema escuro. Queremos mostrar como você pode usar a própria arte para participar ativamente da criação de uma ótima experiência no modo escuro. Para isso, ajustamos programaticamente os estilos de plano de fundo de cada janela e usamos o máximo de CSS que fizesse sentido ao criar a arte da janela. A maioria dos planos de fundo eram gradientes de CSS, de modo que seria mais fácil ajustar os valores de cor. Depois, colocamos a arte em cima delas.

Outros easter eggs

Toques pessoais

Adicionamos alguns toques pessoais à página para dar mais personalidade ao site. O primeiro foi o elenco de personagens inspirados na nossa equipe. Também incluímos um cursor no estilo antigo em dias inativos e experimentamos o estilo favicon.

Estilos personalizados de cursor e opções de favicon

Toques funcionais

Um dos toques funcionais adicionais é a funcionalidade "Ir para hoje", com um pássaro no topo do prédio. Clicar ou pressionar Enter nesse pássaro leva você para baixo na página até o dia atual do mês, para que você possa acessar rapidamente os últimos lançamentos.

O Designcember.com também tem uma folha de estilo de impressão especial, na qual basicamente estamos exibindo uma imagem específica que funciona melhor em papel 8,5" x 11" para que você possa imprimir o calendário e permanecer festivo o ano todo.

Impressão do design do calendário em tamanho de pôster.
Una segurando uma cópia grande da agenda.

No geral, foi necessário muito trabalho para criar uma experiência na Web moderna e divertida e extravagante para celebrar o desenvolvimento da interface durante todo o mês de dezembro. Esperamos que tenha gostado.

Partes do calendário com anotações e observações visuais