Ein Einblick in den Prozess und die Tools, die für die Erstellung des Designcember-Designs im Stil eines Feiertagskalenders verwendet wurden.
Im Dezember und in Anlehnung an die vielen Kalender, mit denen Nutzer den Countdown bis zum Fest herunterzählen und feiern, möchten wir Webinhalte aus der Community und vom Chrome-Team hervorheben. Jeden Tag haben wir einen UI-Entwicklungs- und designbezogenen Inhalt hervorgehoben. Insgesamt waren das 31 Highlights, darunter 26 neue Demo-Websites, Tools, Ankündigungen, Podcasts, Videos, Artikel und Fallstudien.
Die vollständige Version finden Sie unter designcember.com.
Übersicht
Unser Ziel war es, eine barrierefreie, skurrile, moderne und responsive Website mit möglichst wenigen Byte zu erstellen. Wir wollten neue responsive APIs wie Containerabfragen hervorheben und ein schönes Beispiel für einen dunklen Modus auf einer designorientierten und assetreichen Website zeigen. Dazu haben wir unter anderem Dateien komprimiert, mehrere Formate angeboten, Build-Tools verwendet, die für die Erstellung statischer Websites optimiert sind, und eine neue Polyfill eingeführt.
Mit einer Laune beginnen
Die Idee hinter der Designcember-Kalenderwebsite war es, ein Schaufenster für alle Arbeiten zu sein, die wir im Dezember hervorheben wollten, und gleichzeitig als Demo-Website zu dienen. Wir haben uns für ein responsives Wohnhaus entschieden, das höher und schmaler oder kürzer und breiter werden kann, mit Fenstern, die sich innerhalb des Frames neu anordnen. Jedes Fenster entsprach einem Tag (und damit einem Inhalt). Wir haben mit der Illustratorin Alice Lee zusammengearbeitet, um unsere Vision zu verwirklichen.
Alice war inspirierend und teilte Prozesse und Skizzen, die schon in ihren ersten Konzepten spannend waren. Während sie an den Bildern arbeitete, haben wir an der Architektur gefeilt. Die ersten Diskussionen drehten sich um das Makro-Layout, das Gebäude und seine Fenster. Wie würden sich die Fenster an eine, zwei oder drei Spalten anpassen, wenn mehr Ansichtsraum verfügbar wäre? Wie weit könnten sie schrumpfen oder gedehnt werden? Wie groß darf das Gebäude maximal sein? Wie stark würden sich die Fenster verschieben?
Hier sehen Sie eine Vorschau eines responsiven Prototyps mit grid-auto-flow: dense
, der zeigt, wie Fenster automatisch durch den Rasteralgorithmus platziert werden können. Wir haben schnell festgestellt, dass diese Raster zwar gut geeignet sind, um Artwork zu präsentieren, aber nicht die Möglichkeit bieten, die Fenster in einem nicht einheitlichen verfügbaren Bereich zu vergrößern und zu verkleinern und die Vorteile von Containerabfragen zu demonstrieren.
Sobald das allgemeine Raster relativ stabil war und eine gewisse Richtung für die Reaktionsfähigkeit des Gebäudes und seiner Fenster vermittelte, konnten wir uns auf ein einzelnes Fenster konzentrieren. Einige Fenster wurden mehr als andere im Raster gedehnt, verkleinert, zusammengepresst, vergrößert und neu zusammengesetzt.
Jedes Fenster müsste mit einer gewissen Unruhe beim Ändern der Größe umgehen können. Unten sehen Sie einen Prototyp eines Fensters, der seine Reaktion auf Turbulenzen veranschaulicht. Er zeigt, wie stark sich jedes interaktive Fenster anpassen könnte.
Fensteranimation mit Spritesheets
Einige Fenster haben Animationen, die die Interaktion verbessern. Die Animationen werden in Photoshop von Hand und Frame für Frame gezeichnet. Jeder Frame wird exportiert, mit diesem Spritesheet-Generator in ein Spritesheet umgewandelt und dann mit Squoosh optimiert. In der CSS-Animation werden dann background-position-x
und animation-timing-function
verwendet, wie im folgenden Beispiel gezeigt.
.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%; }
}
Einige Animationen, wie die Spardose von Tag 6, waren schrittweise CSS-Animationen.
Wir haben diesen Effekt mit einer ähnlichen Technik mit steps()
erzielt, mit dem Unterschied, dass die keyframes CSS-Transformierungspositionen anstelle von Hintergrundpositionen waren.
CSS-Maskierung
Einige Fenster hatten eine einzigartige Form. Wir haben
Masken und
aspect-ratio
verwendet, um ein skalierbares, individuell geformtes und anpassbares Fenster zu erstellen.
Um eine Maske wie diese für Windows 8 zu erstellen, waren einige klassische Photoshop-Kenntnisse sowie ein wenig Wissen darüber erforderlich, wie Masken im Web funktionieren. Sehen wir uns das Fenster für Tag 8 an.
Damit die innere Form, die einem Kleeblatt ähnelt, als Maske verwendet werden kann, muss sie als eigene Form isoliert und mit der Farbe Weiß gefüllt werden. Weiße Bereiche geben dem CSS an, welche Inhalte erhalten bleiben sollen und welche nicht. In Photoshop wurde das Innere des Fensters ausgewählt, um 1 Pixel ausgefranst (um Aliasing-Probleme zu beseitigen), dann weiß gefüllt und mit der gleichen Höhe und Breite wie der Fensterrahmen exportiert. So konnten Frame und Maske direkt übereinander gelegt werden, sodass der innere Inhalt innerhalb des Frames wie erwartet angezeigt wurde.
Danach kann der Inhalt des Fensters geändert werden und bleibt immer innerhalb des benutzerdefinierten Frames. Das folgende Bild zeigt die Version des Fensters im Dunkelmodus mit einem anderen Hintergrundverlauf und einem CSS-Glühen-Filter, der auf die Lampe angewendet wird.
Die Maskierung unterstützt auch responsive, containerabfragebasierte Fenster. In Fenster 9 ist eine Figur zu sehen, die hinter einer Maske verborgen ist, bis das Fenster eine schmalere Größe hat. Damit der Nutzer das Bild nicht außerhalb des Frames anpassen kann, hat Alice die gesamte Figur für uns fertiggestellt. Die Figur ist im Fenster maskiert, die Pflanzen jedoch nicht. Eine weitere Herausforderung bestand darin, maskierte Elemente mit nicht maskierten Ebenen zu überlagern und dafür zu sorgen, dass sie alle gut zusammen skaliert werden.
Das folgende Bild zeigt, wie es ohne die Maske am Fenster und am Charakter aussehen würde.
Bild verkleinern
Um die Genauigkeit der Illustration beizubehalten und zu verhindern, dass die Bilder auf High-Definition-Bildschirmen unscharf werden, arbeitete Alice mit einem 3-fachen Pixelverhältnis. Wir wollten imgix verwenden und optimierte Bilder und Formate auf dem Server bereitstellen. Wir haben jedoch festgestellt, dass wir mit manuellen Anpassungen mit dem Squoosh-Tool 50% oder mehr einsparen konnten.
Bei der Komprimierung von Illustrationen gibt es besondere Herausforderungen, insbesondere bei Pinselstrichen und dem von Alice verwendeten Stil mit transparenten, rauen Kanten. Wir haben jedes der dreimal aus Photoshop exportierten PNG-Bilder mit Squoosh in ein kleineres PNG-, WEBP- und AVIF-Bild umgewandelt. Für jeden Dateityp gibt es spezielle Komprimierungsfunktionen. Es dauerte mehr als 50 Komprimierungen, bis wir einige gängige Optimierungseinstellungen gefunden hatten.
Die Squoosh-Befehlszeile war entscheidend, da über 200 Bilder optimiert werden mussten. Die manuelle Optimierung hätte Tage gedauert. Nachdem wir die gemeinsamen Optimierungseinstellungen festgelegt hatten, haben wir sie als Befehlszeilenanweisungen bereitgestellt und ganze Ordner mit PNG-Bildern in ihre komprimierten WebP- und AVIF-Äquivalente umgewandelt.
Hier ist ein Beispiel für einen verwendeten AVIF-Befehl in der Squoosh-Befehlszeile:
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
Nachdem das optimierte Artwork in das Repository eingecheckt wurde, konnten wir es über HTML laden:
<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>
Das Schreiben des Bildquellcodes war repetitiv. Deshalb haben wir eine Astro-Komponente entwickelt, mit der Bilder mit einer Codezeile eingebettet werden können.
<Pic filename="day1/inner-frame" role="presentation" />
Nutzer von Screenreadern und Tastaturen
Ein Großteil des Designcember-Erlebnisses besteht aus Kunst und interaktiven Fenstern. Uns war es wichtig, dass Nutzer mit Tastatur die Website verwenden und in Fenster schauen können und dass Screenreader-Nutzer eine gute Sprachausgabe erhalten.
Beim Einbetten der Bilder haben wir beispielsweise role="presentation"
verwendet, um das Bild für Screenreader als Präsentationselement zu kennzeichnen. Wir waren der Meinung, dass eine Nutzererfahrung mit 5 bis 12 zerbrochenen alt
-Beschreibungen nicht optimal ist. Deshalb haben wir die Bilder als Präsentationselemente gekennzeichnet und eine allgemeine Fensterbeschreibung hinzugefügt. Das Wechseln zwischen den Fenstern mit einem Screenreader hat dann einen schönen narrativen Charakter, was uns hoffentlich dabei helfen wird, die Verspieltheit und den Spaß zu vermitteln, die die Website vermitteln möchte.
Im folgenden Video sehen Sie eine Demo der Tastatur. Mit der Tabulatortaste, der Eingabetaste, der Leertaste und der Esc-Taste können Sie den Fokus zwischen den Pop-up-Fenster und den Fenstern verschieben.
Für Screenreader gibt es spezielle ARIA-Attribute, die für Klarheit bei den Inhalten sorgen. Die Links für die Tage enthalten beispielsweise nur „Eins“ oder „Zwei“. Mithilfe von ARIA werden sie jedoch als „Tag 1“ und „Tag 2“ angesagt. Außerdem werden alle Bilder in einem einzigen Label zusammengefasst, sodass jedes Fenster eine Beschreibung hat.
Astro, ein komponentenbasierter Website-Generator, der zuerst statische Seiten erstellt
Astro erleichterte es dem Team, gemeinsam an der Website zu arbeiten. Das Komponentenmodell war sowohl Angular- als auch React-Entwicklern vertraut, während das System mit dem benutzerdefinierten Klassennamenstil jedem Entwickler verdeutlichte, dass seine Arbeit an einem Fenster nicht mit der anderer Entwickler kollidiert.
Tage als Komponenten
Jeder Tag war eine Komponente, die den Status aus einem Build-Time-Datenspeicher abgerufen hat. So konnten wir die Vorlagenlogik ausführen, bevor die HTML-Daten den Browser erreichten. Die Logik würde bestimmen, ob für den Tag eine Kurzinfo angezeigt werden soll oder nicht, da für inaktive Tage keine Pop-ups angezeigt werden.
Builds werden stündlich ausgeführt und der Datenspeicher für die Buildzeit würde einen neuen Tag entsperren, wenn der Buildserver nach Mitternacht war. Diese selbst aktualisierenden und autarken kleinen Systeme halten die Website auf dem neuesten Stand.
Stilblöcke und Open Props
Astro hat Stile für die Kameraobjektive in seinem Komponentenmodell geschrieben, was die Verteilung der Arbeitslast auf viele Teammitglieder erleichterte und die Verwendung von Open Props unterhaltsam machte. Die Stile Open Props normalize.css waren für das adaptive (helle und dunkle) Design sehr nützlich und halfen auch bei der Formatierung von Inhalten wie Absätzen und Überschriften.
Als frühe Nutzer von Astro sind wir auf einige Probleme mit PostCSS gestoßen. So konnten wir beispielsweise aufgrund zu vieler Build-Probleme nicht auf die aktuelle Astro-Version aktualisieren. Hier könnte mehr Zeit für die Optimierung der Build- und Entwickler-Workflows aufgewendet werden.
Flexible Container
Einige Fenster werden vergrößert oder verkleinert, wobei das Seitenverhältnis beibehalten wird, um die Kunstwerke zu erhalten. In einigen anderen Fenstern haben wir die Leistungsfähigkeit der komponentenbasierten Architektur mit Containerabfragen demonstriert. Containerabfragen bedeuteten, dass Fenster ihre eigenen individuellen responsiven Stilinformationen haben und sich anhand ihrer eigenen Größe anpassen konnten. Einige Fenster wurden von schmal zu breit und es musste die Größe der darin enthaltenen Medien sowie deren Platzierung angepasst werden.
Wenn mehr Platz für ein Fenster verfügbar ist, können wir die Größe oder die untergeordneten Elemente des Fensters entsprechend anpassen. Es stellte sich heraus, dass Containerabfragen nicht nur eine gute Möglichkeit sind, die adaptiven Fenster zu implementieren, sondern auch erforderlich sind, um die Orchestrierung bestimmter Layouts drastisch zu vereinfachen.
.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;
}
}
Dieser Ansatz unterscheidet sich vom Beibehalten eines Seitenverhältnisses. Sie bietet mehr Kontrolle und mehr Möglichkeiten. Ab einer bestimmten Größe rücken viele Kinder um, um sich an ein neues Layout anzupassen.
Containerabfragen ermöglichten uns auch die Unterstützung der Blockrichtung (vertikale Begrenzung). Wenn ein Fenster also länger wurde, konnten wir die Stile entsprechend anpassen. Das ist bei den absatzbasierten Abfragen zu sehen, die wir eigenständig und zusätzlich zu den breitenbasierten Abfragen verwendet haben:
.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);
}
}
Außerdem haben wir Containerabfragen verwendet, um Details ein- und auszublenden, da die Grafik bei kleineren Größen immer überladener und bei größeren leerer wurde. Fenster 9 ist ein gutes Beispiel dafür:
Browserübergreifende Unterstützung
Um eine moderne, plattformübergreifende Erfahrung zu schaffen, insbesondere für experimentelle APIs wie Containerabfragen, benötigen wir eine gute polyfill. Wir haben unser Team um Hilfe gebeten und Surma hat die Leitung für den Build einer neuen Containerabfrage-Polyfill übernommen. Die Polyfill-Funktion setzt ResizeObserver, MutationObserver und die CSS-Funktion :is() voraus. Daher wird die Polyfill von allen modernen Browsern unterstützt, insbesondere von Chrome und Edge ab Version 88, Firefox ab Version 78 und Safari ab Version 14. Mit der Polyfill-Funktion sind die folgenden Syntaxen zulässig:
/* These are all equivalent */
@container (min-width: 200px) {
/* ... */
}
@container (width >= 200px) {
/* ... */
}
@container size(width >= 200px) {
/* ... */
}
Dunkler Modus
Ein letzter wichtiger Punkt für die Designcember-Website war ein schönes dunkles Design. Wir wollten zeigen, wie Sie mit Kunst einen Dark Mode gestalten können, der Ihnen gefällt. Dazu haben wir die Hintergrundstile der einzelnen Fenster programmatisch angepasst und beim Erstellen des Artworks so viel CSS wie sinnvoll verwendet. Die meisten Hintergründe waren CSS-Gradienten, damit die Farbwerte leichter angepasst werden konnten. Darauf haben wir dann die Grafiken gelegt.
Weitere Ostereier
Persönliche Details
Wir haben der Seite einige persönliche Elemente hinzugefügt, um ihr mehr Persönlichkeit zu verleihen. Das erste war die Besetzung der Charaktere, die von unserem Team inspiriert wurde. Außerdem haben wir einen Cursor im Retro-Stil für inaktive Tage hinzugefügt und mit dem Favicon-Stil experimentiert.
Funktionelle Elemente
Eine der zusätzlichen Funktionen ist die Funktion „Zu heute springen“, die durch einen Vogel auf dem Dach des Gebäudes dargestellt wird. Wenn du auf diesen Vogel klickst oder die Eingabetaste drückst, gelangst du auf der Seite zum aktuellen Tag des Monats, sodass du schnell zu den neuesten Produktveröffentlichungen gelangst.
Designcember.com hat auch ein spezielles Druck-Stylesheet, in dem wir im Grunde ein bestimmtes Bild bereitstellen, das am besten auf Papier im Format 21,6 × 27,9 cm funktioniert.So können Sie den Kalender selbst ausdrucken und das ganze Jahr über festlich feiern.
Insgesamt war viel Arbeit erforderlich, um eine unterhaltsame, skurrile und moderne Weboberfläche zu erstellen, die den ganzen Dezember lang die UI-Entwicklung feiert. Wir hoffen, es hat Ihnen gefallen.