Conception de bâtiments

Découvrez le processus et les outils utilisés pour créer l'expérience de Designcember, qui s'inspire du calendrier des fêtes.

Dans l'esprit de décembre et des nombreux calendriers que les internautes utilisent pour compter les jours avant les fêtes, nous souhaitons mettre en avant les contenus Web de la communauté et de l'équipe Chrome. Chaque jour, nous avons mis en avant un contenu lié au développement et à la conception d'UI, pour un total de 31 articles, parmi lesquels 26 nouveaux sites de démonstration, outils, annonces, podcasts, vidéos, articles et études de cas.

Pour découvrir l'expérience complète, consultez designcember.com.

Site Designcember

Présentation

Notre objectif était de proposer une expérience Web accessible, fantaisiste, moderne et responsive avec le moins d'octets possible. Nous voulions mettre en avant de nouvelles API responsives telles que les requêtes de conteneur, et inclure un bel exemple de mode sombre sur un site Web axé sur la conception et riche en éléments. Pour ce faire, nous avons compressé des fichiers, proposé plusieurs formats, utilisé des outils de compilation optimisés pour la génération de sites statiques, publié un nouveau polyfill, et plus encore.

Commencer par l'imagination

L'idée du site du calendrier Designcember était de servir de vitrine à tous les travaux que nous souhaitions mettre en avant tout au long du mois de décembre, tout en agissant comme un site de démonstration. Nous avons décidé de créer un immeuble d'appartements responsif qui pouvait être plus haut et plus étroit, ou plus court et plus large, avec des fenêtres qui se réorganisaient dans le cadre. Chaque fenêtre représentait un jour (et donc un contenu). Nous avons travaillé avec l'illustratrice Alice Lee pour donner vie à notre vision.

Croquis du squelette de la page Designcember.

Alice a été inspirante, en partageant des processus et des esquisses passionnants, même dans leurs premiers concepts. Pendant qu'elle travaillait sur l'illustration, nous avons travaillé sur l'architecture. Les premières discussions portaient sur la mise en page macro, le bâtiment et ses fenêtres. Comment les fenêtres s'adaptent-elles à une, deux ou trois colonnes à mesure que l'espace de la fenêtre d'affichage devient disponible ? Jusqu'à quel point peuvent-elles se rétracter ou s'étendre ? Quelle est la taille maximale du bâtiment ? De combien les fenêtres vont-elles se déplacer ?

Voici un aperçu d'un prototype responsif utilisant grid-auto-flow: dense, qui montre comment les fenêtres peuvent être placées automatiquement par l'algorithme de grille. Nous avons rapidement compris que, bien que les grilles de format soient très efficaces pour présenter des illustrations, elles ne permettaient pas de faire varier la taille des fenêtres dans un espace disponible non uniforme et de mettre en avant la puissance des requêtes de conteneur.

Animation montrant comment cette maquette fonctionnelle réagit à différentes tailles d'écran.
Découvrez cette démonstration sur CodePen.

Une fois que la grille générale était relativement stable et qu'elle communiquait une direction pour la réactivité du bâtiment et de ses fenêtres, nous avons pu nous concentrer sur une seule fenêtre. Certaines fenêtres se sont étirées, rétrécies, compressées, agrandies et recomposées plus que d'autres dans la grille.

Maquettes fonctionnelles montrant comment les fenêtres s'affichent à différents points d'arrêt.

Chaque fenêtre devrait gérer une certaine turbulence de redimensionnement. Vous trouverez ci-dessous un prototype de fenêtre illustrant sa réactivité aux turbulences et indiquant dans quelle mesure chaque fenêtre interactive peut s'ajuster.

Animation de fenêtre avec des feuilles d'images

Certaines fenêtres comportent des animations pour enrichir l'expérience. Les animations sont dessinées à la main, frame par frame, dans Photoshop. Chaque frame est exporté, transformé en spritesheet avec ce générateur de spritesheet, puis optimisé avec Squoosh. L'animation CSS utilise ensuite background-position-x et animation-timing-function, comme illustré dans l'exemple suivant.

.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%; }
}

Animation montrant la fenêtre pour le premier jour.

Certaines animations, comme la tirelire du jour 6, étaient des animations CSS par étapes. Nous avons obtenu cet effet à l'aide d'une technique similaire, à l'aide de steps(), à la différence que les images clés étaient des positions de transformation CSS au lieu de positions d'arrière-plan.

Masquage CSS

Certaines fenêtres avaient des formes uniques. Nous avons utilisé des masques et aspect-ratio pour créer une fenêtre évolutive, de forme unique et adaptative.

Pour créer un masque, comme celui-ci pour la fenêtre 8, il a fallu quelques compétences classiques de Photoshop, ainsi qu'un peu de connaissances sur le fonctionnement des masques sur le Web. Examinons la fenêtre du huitième jour.

Fenêtre du huitième jour.

Pour devenir un masque, la forme intérieure en trèfle à quatre feuilles doit être isolée en tant que forme distincte et remplie de blanc. La couleur blanche indique au CSS les contenus qui restent et ceux qui ne le font pas. Dans Photoshop, l'intérieur de la fenêtre a été sélectionné, flouté de 1 pixel (pour supprimer les problèmes d'aliasing), puis rempli de blanc et exporté à la même hauteur et largeur que le cadre de la fenêtre. De cette façon, le frame et le masque peuvent être superposés directement, ce qui permet d'afficher le contenu interne dans le frame comme prévu.

Image du masque Clover

Une fois la fenêtre créée, son contenu peut être modifié et semble toujours rester dans le cadre personnalisé. L'image suivante montre la version du mode sombre de la fenêtre, avec un dégradé d'arrière-plan différent et un filtre CSS de lueur appliqué à la lumière.

Fenêtre du huitième jour en mode sombre.

Le masquage est également compatible avec les fenêtres responsives basées sur les requêtes de conteneur. Dans la neuvième fenêtre, un personnage est masqué jusqu'à ce que la fenêtre soit plus étroite. Pour s'assurer que l'utilisateur ne peut pas ajuster l'image en dehors du cadre, Alice a terminé le personnage dans son intégralité. Le personnage est masqué dans la fenêtre, mais les plantes ne le sont pas. Nous avons donc dû superposer des éléments masqués à des calques non masqués et nous assurer qu'ils étaient tous bien mis à l'échelle.

L'image suivante montre à quoi ressemble la scène sans le masque sur la fenêtre et le personnage.

Image de la fenêtre 9 sans le masque.

Squooshing l'art

Pour préserver la fidélité de l'illustration et s'assurer que les écrans haute définition n'offrent pas une expérience utilisateur floue, Alice a travaillé avec un format de 3 x pixels. Le plan était d'utiliser imgix et de diffuser des images et des formats optimisés sur son serveur, mais nous avons constaté que les ajustements manuels avec l'outil Squoosh pouvaient nous faire économiser 50% ou plus.

Utiliser Squoosh pour compresser des images

La compression des illustrations pose des défis uniques, en particulier pour les traits de pinceau et le style de bords bruts transparents utilisés par Alice. Nous avons choisi de réduire chaque image PNG exportée par Photoshop en 3 x à une image PNG, WebP et AVIF plus petite. Chaque type de fichier possède ses propres capacités de compression spéciales. Nous avons dû compresser plus de 50 images pour trouver des paramètres d'optimisation courants.

La CLI Squish s'est révélée indispensable avec plus de 200 images à optimiser. Il aurait fallu des jours pour les optimiser manuellement. Une fois que nous avons obtenu les paramètres d'optimisation courants, nous les avons fournis sous forme d'instructions de ligne de commande et avons traité par lot des dossiers entiers d'images PNG en les convertissant en versions compressées WebP et AVIF.

Voici un exemple de commande squoosh de la CLI AVIF:

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

Une fois les illustrations optimisées enregistrées dans le dépôt, nous pouvons commencer à les charger à partir du code 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>

Écrire le code source des images était répétitif. Nous avons donc créé un composant Astro pour intégrer des images avec une seule ligne de code.

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

Utilisateurs de lecteurs d'écran et de claviers

Une grande partie de l'expérience Designcember passe par les illustrations et les fenêtres interactives. Il était important pour nous qu'un utilisateur de clavier puisse utiliser le site et jeter un coup d'œil dans les fenêtres, et que les utilisateurs de lecteurs d'écran bénéficient d'une expérience agréable avec narration.

Par exemple, lorsque nous avons intégré les images, nous avons utilisé role="presentation" pour marquer l'image comme étant de présentation pour les lecteurs d'écran. Nous avons estimé que l'expérience utilisateur avec cinq à douze descriptions alt fragmentées serait mauvaise. Nous avons donc marqué les images comme étant des images de présentation et fourni une narration globale de la fenêtre. La navigation dans les fenêtres avec un lecteur d'écran offre alors une expérience narrative agréable, qui, nous l'espérons, contribuera à transmettre l'esprit fantaisiste et amusant du site.

La vidéo suivante présente une démonstration de l'expérience clavier. Les touches Tabulation, Entrée, Barre d'espace et Échap permettent d'orchestrer le focus entre les fenêtres pop-up et les fenêtres.

L'expérience avec les lecteurs d'écran comporte des attributs ARIA spéciaux qui clarifient le contenu. Par exemple, les liens des jours ne comportent que les chiffres "un" ou "deux", mais avec des éléments ARIA ajoutés, ils sont annoncés comme "Jour 1" et "Jour 2". De plus, toutes les images sont résumées dans un seul libellé, de sorte que chaque fenêtre dispose d'une description.

Astro, générateur de sites basé sur des composants et privilégiant le contenu statique

Astro a permis à l'équipe de travailler facilement sur le site. Le modèle de composant était familier aux développeurs Angular et React, tandis que le système de style de nom de classe avec portée permettait à chaque développeur de savoir que son travail sur une fenêtre ne serait pas en conflit avec celui d'un autre.

Jours en tant que composants

Chaque jour était un composant qui récupérait l'état à partir d'un entrepôt de données au moment de la compilation. Cela nous a permis d'exécuter la logique du modèle avant que le code HTML n'atteigne le navigateur. La logique déterminerait si le jour doit afficher son info-bulle ou non, car les jours inactifs n'affichent pas de pop-ups.

Les builds sont exécutés toutes les heures, et le data store de l'heure de compilation déverrouille un nouveau jour lorsque le serveur de compilation est passé minuit. Ces petits systèmes autonomes et auto-actualisants permettent de maintenir le site à jour.

Styles avec portée et composants Open

Astro définit des styles de portée dans son modèle de composant, ce qui a facilité la répartition de la charge de travail entre de nombreux membres de l'équipe et a rendu l'utilisation d'Open Props amusante. Les styles Open Props normalize.css ont été utiles avec le thème adaptatif (clair et sombre), et ont également aidé à gérer le contenu tel que les paragraphes et les en-têtes.

En tant que pionniers d'Astro, nous avons rencontré quelques problèmes avec PostCSS. Par exemple, nous n'avons pas pu passer à la dernière version d'Astro en raison d'un trop grand nombre de problèmes de compilation. Il serait possible de consacrer plus de temps à l'optimisation des workflows de compilation et de développement.

Conteneurs flexibles

Certaines fenêtres se développent et se réduisent, tout en conservant le format pour préserver leur illustration. Nous avons utilisé d'autres fenêtres pour montrer la puissance de l'architecture basée sur les composants avec les requêtes de conteneur. Les requêtes de conteneur permettaient aux fenêtres de posséder leurs propres informations de style responsif et de s'ajuster en fonction de leurs propres tailles. Certaines fenêtres sont passées d'une largeur étroite à une largeur plus large. Il a donc fallu ajuster la taille des contenus multimédias qu'elles contiennent, ainsi que leur emplacement.

Démonstration de la façon dont les fenêtres changent à mesure qu&#39;elles disposent de plus d&#39;espace.

À mesure que l'espace disponible pour une fenêtre augmente, nous pouvons adapter la taille ou les éléments enfants de la fenêtre pour qu'elle s'adapte. Il s'est avéré que, pour répondre aux fenêtres adaptatives, les requêtes de conteneur ne seraient pas seulement amusantes à présenter, mais qu'elles seraient obligatoires et simplifieraient considérablement l'orchestration de certaines mises en page.

.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;
  }
}

Cette approche est différente de la conservation d'un format. Il offre plus de contrôle et plus d'opportunités. À partir d'une certaine taille, de nombreux enfants se déplacent pour s'adapter à une nouvelle mise en page.

Les requêtes de conteneur nous ont également permis de prendre en charge la structuration en mode bloc (vertical). Ainsi, à mesure que la longueur d'une fenêtre augmentait, nous pouvions ajuster ses styles pour qu'ils s'adaptent. Cela se voit dans les requêtes basées sur la hauteur, que nous avons utilisées de manière autonome, et en plus des requêtes basées sur la largeur:

.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);
  }
}

Nous avons également utilisé des requêtes de conteneur pour afficher et masquer les détails, car les illustrations devenaient de plus en plus encombrées à de plus petites tailles et de plus en plus vides à des tailles plus grandes. La fenêtre 9 est un excellent exemple de ce qui s'est passé:

Compatibilité entre les navigateurs

Pour créer une expérience moderne multinavigateur de qualité, en particulier pour les API expérimentales telles que les requêtes de conteneur, nous avons besoin d'un excellent polyfill. Nous avons lancé un appel à notre équipe, et Surma a dirigé la création d'un nouveau polyfill de requête de conteneur. Le polyfill s'appuie sur ResizeObserver, MutationObserver et la fonction CSS:is(). Par conséquent, tous les navigateurs modernes sont compatibles avec le polyfill, en particulier Chrome et Edge à partir de la version 88, Firefox à partir de la version 78 et Safari à partir de la version 14. L'utilisation du polyfill permet l'utilisation de l'une des syntaxes suivantes:

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

Mode sombre

Versions du site Designcember en mode clair et sombre, côte à côte.

Un dernier détail était essentiel pour le site Web de Designcember : un superbe thème sombre. Nous voulions vous montrer comment utiliser l'art lui-même pour participer activement à la création d'une expérience optimale en mode sombre. Pour ce faire, nous avons ajusté les styles d'arrière-plan de chaque fenêtre de manière programmatique et utilisé autant de CSS que possible lors de la création de l'illustration de la fenêtre. La plupart des arrière-plans étaient des dégradés CSS, ce qui permettait d'ajuster plus facilement leurs valeurs de couleur. Nous avons ensuite superposé les illustrations.

Autres Easter eggs

Touches personnelles

Nous avons ajouté quelques touches personnelles à la page pour lui donner plus de personnalité. Le premier était le casting des personnages, inspiré par notre équipe. Nous avons également inclus un curseur rétro les jours d'inactivité et joué avec le style de la favicon.

Styles de curseur personnalisés et options de favicon

Touches fonctionnelles

Parmi les fonctionnalités supplémentaires, vous trouverez la fonctionnalité "Accéder à Aujourd'hui", avec un oiseau perché sur le toit du bâtiment. Cliquez sur cet oiseau ou appuyez sur Entrée pour faire défiler la page jusqu'au jour en cours du mois et accéder rapidement aux derniers lancements.

Designcember.com propose également une feuille de style d'impression spéciale dans laquelle nous diffusons essentiellement une image spécifique qui fonctionne le mieux sur du papier 8,5 x 11 pouces.Vous pouvez ainsi imprimer le calendrier vous-même et rester dans l'ambiance festive toute l'année.

Impression de la conception du calendrier en format poster.
Una tenant une grande impression du calendrier.

Au total, nous avons consacré beaucoup d'efforts à la création d'une expérience Web moderne, amusante et fantaisiste pour célébrer le développement de l'UI tout au long du mois de décembre. Nous espérons qu'elle vous a plu.

Parties du calendrier avec des annotations et des notes visuelles