ホリデー カレンダー スタイルの Designcember の作成に使用されたプロセスとツールをご紹介します。
12 月と、カウントダウンやお祝いに使用されるさまざまなカレンダーにちなんで、コミュニティと Chrome チームのウェブ コンテンツをご紹介します。毎日、UI 開発とデザインに関連するコンテンツを 1 つ紹介し、合計 31 件のハイライトを掲載しました。そのうち、26 件は新しいデモサイト、ツール、お知らせ、ポッドキャスト、動画、記事、ケーススタディでした。
詳細については、designcember.com をご覧ください。
概要
目標は、できるだけ少ないバイト数で、アクセスしやすく、風変わりで、モダンで、レスポンシブなウェブ エクスペリエンスを提供することでした。コンテナ クエリなどの新しいレスポンシブ API を強調し、デザイン重視でアセットが多いウェブサイトにダークモードの美しい例を掲載したいと考えました。これを実現するため、ファイルの圧縮、複数の形式の提供、静的サイト生成用に最適化されたビルドツールの使用、新しいポリフィルの提供などを行いました。
気まぐれから始める
Designcember カレンダー サイトは、12 月を通して注目を集めたいすべての作品を展示するショーケースとして機能し、同時にデモサイトとしても機能することを目的としています。私たちは、高く狭くしたり、低く広くしたりできる、フレーム内で窓が再配置されるレスポンシブなアパートビルを建設することにしました。各ウィンドウは 1 日(つまり 1 つのコンテンツ)を表します。このビジョンを実現するため、イラストレーターの Alice Lee に協力を依頼しました。
アリスは、初期のコンセプトでもワクワクするプロセスとスケッチを共有し、刺激を与えてくれました。彼女がアート制作に取り組んでいる間、私たちはアーキテクチャをハックしました。初期の議論では、マクロ レイアウト、建物、窓について話し合いました。ビューポートのスペースが広がると、ウィンドウは 1 列、2 列、3 列のいずれに適応しますか?縮小または拡大できる範囲はどのくらいですか?建物の最大サイズはどれくらいですか?窓はどのくらい移動しますか?
grid-auto-flow: dense
を使用したレスポンシブ プロトタイプのプレビューを次に示します。グリッド アルゴリズムによってウィンドウが自動的に配置される仕組みを説明しています。アートを美しく表示するアスペクト比グリッドは優れたパフォーマンスを発揮するものの、ウィンドウを非均一な使用可能なスペースに拡大または縮小してコンテナ クエリの威力を発揮する機会はありませんでした。
全体的なグリッドが比較的安定し、建物とその窓の反応性について方向性を示すことができました。次に、1 つの窓に焦点を当てました。グリッド内の一部のウィンドウは、他のウィンドウよりも伸び縮み、圧縮、拡大、再構成が頻繁に行われていました。
各ウィンドウは、一定のサイズ変更の乱流を処理する必要があります。以下は、乱気流に対する応答性を示すウィンドウのプロトタイプです。各インタラクティブ ウィンドウがどの程度調整されるかを示すものです。
スプライトシートを使用したウィンドウ アニメーション
一部のウィンドウには、操作性を高めるためのアニメーションが含まれています。アニメーションは、Photoshop でフレームごとに手描きされています。各フレームはエクスポートされ、このスプライトシート ジェネレータでスプライトシートに変換され、Squoosh で最適化されます。次の例に示すように、CSS アニメーションは background-position-x
と animation-timing-function
を使用します。
.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%; }
}
6 日目の貯金箱などのアニメーションは、ステップベースの CSS アニメーションでした。Google は、steps()
を使用して同様の手法でこの効果を実現しました。ただし、キーフレームは背景の位置ではなく CSS 変換位置でした。
CSS マスク
窓の形状が独特なものもありました。マスクと aspect-ratio
を使用して、スケーラブルで独自の形状のアダプティブ ウィンドウを作成しました。
ウィンドウ 8 のマスクなど、このようなマスクを作成するには、従来の Photoshop のスキルと、ウェブ上のマスクの仕組みに関する知識が必要でした。8 日目の期間を見てみましょう。
マスクにするには、内側の四葉のクローバー型の図形を独自の図形として分離し、白色で塗りつぶす必要があります。白色は、残すコンテンツを CSS に指示します。白色の外側にあるコンテンツはすべて削除されます。Photoshop で、ウィンドウの内側を選択し、1 ピクセルのフェザリングを適用して(エイリアシングの問題を解消するため)、白で塗りつぶし、ウィンドウ枠と同じ高さと幅でエクスポートしました。これにより、フレームとマスクを直接重ねて、フレーム内の内部コンテンツを想定どおりに表示できます。
完了すると、ウィンドウの内容を変更でき、カスタム フレーム内に常に表示されます。次の画像は、背景のグラデーションを変更し、光にグロー CSS フィルタを適用した、ダークモードのバージョンのウィンドウを示しています。
マスキングは、レスポンシブなコンテナ クエリベースのウィンドウもサポートしています。ウィンドウ 9 では、ウィンドウのサイズが狭くなるまで、マスクの背後に隠れているキャラクターがいます。ユーザーが画像をフレーム外に調整できないようにするため、アリスは文字全体を完成させました。キャラクターはウィンドウ内でマスクされていますが、植物はマスクされていないため、マスクされた要素をマスクされていないレイヤと重ねて、すべてが一緒に適切にスケーリングされるようにするという課題もありました。
次の画像は、窓と文字にマスクを適用していない状態を示しています。
アートを圧縮する
イラストの忠実度を維持し、高解像度画面でぼやけたユーザー エクスペリエンスにならないようにするため、アリスは 3x ピクセル比で作業しました。当初は imgix を使用して、最適化された画像と形式をサーバーで提供する予定でしたが、Squoosh ツールで手動で調整することで 50% 以上削減できることがわかりました。
イラストには、特にアリスが使用したブラシストロークのスタイルや透明な粗いエッジのスタイルなど、圧縮に関する独自の課題があります。3x の Photoshop でエクスポートされた PNG 画像を、Squoosh で小さい PNG、WebP、AVIF に変換しました。各ファイル形式には独自の特別な圧縮機能があり、50 枚以上の画像を圧縮して、共通の最適化設定を見つけました。
200 枚を超える画像を最適化するには、Squoosh CLI が不可欠でした。手動で行うには数日かかっていたでしょう。共通の最適化設定をコマンドライン インストラクションとして提供し、PNG 画像のフォルダ全体をバッチ処理して、WebP と AVIF で圧縮された画像に変換しました。
以下に、使用される AVIF CLI squoosh コマンドの例を示します。
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
最適化されたアートワークがリポジトリにチェックインされたので、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>
画像のソースコードを記述するのは繰り返し作業になるため、Astro コンポーネントを作成して、1 行のコードで画像を埋め込むようにしました。
<Pic filename="day1/inner-frame" role="presentation" />
スクリーン リーダーとキーボードを使用するユーザー
Designcember の体験の多くは、アートやインタラクティブなウィンドウを通じて行われます。キーボード ユーザーがサイトを使用してウィンドウを覗き見できること、スクリーン リーダー ユーザーがナレーション付きで快適に利用できることを重視しました。
たとえば、画像を埋め込む際に role="presentation"
を使用して、スクリーン リーダー向けに画像をプレゼンテーション用としてマークしました。5 ~ 12 個に分割された alt
の説明文は、ユーザー エクスペリエンスの低下につながると考えました。そのため、画像をプレゼンテーション用としてマークし、全体的なウィンドウのナレーションを提供しました。スクリーン リーダーでウィンドウを移動すると、ナラティブな感覚が生まれます。これは、サイトが伝えたい気まぐれで楽しい雰囲気を演出するのに役立つと考えています。
次の動画は、キーボード エクスペリエンスのデモを示しています。Tab キー、Enter キー、Space キー、Esc キーはすべて、ウィンドウのポップアップとウィンドウとの間でフォーカスを移動するために使用されます。
スクリーン リーダー エクスペリエンスには、コンテンツを明確にする特別な ARIA 属性があります。たとえば、日付のリンクには「1」または「2」としか表示されませんが、ARIA を追加すると「1 日目」と「2 日目」と読み上げられます。さらに、すべての画像が 1 つのラベルにまとめられるため、各ウィンドウに説明が表示されます。
Astro: 静的ファースト、コンポーネント ドリブンのサイト ジェネレータ
Astro により、チームがサイト上で共同作業を簡単に行うことができました。コンポーネント モデルは Angular と React の両方のデベロッパーにとって馴染み深いものでした。また、スコープ付きクラス名スタイルのシステムにより、各デベロッパーはウィンドウでの作業が他のデベロッパーと競合しないことを把握できました。
日数をコンポーネントとして扱う
各日はコンポーネントで、ビルド時のデータストアからステータスを取得していました。これにより、HTML がブラウザに到達する前にテンプレート ロジックを実行できます。無効な日にはポップアップが表示されないため、その日のトゥイップルを表示するかどうかはロジックによって判断されます。
ビルドは 1 時間ごとに実行され、ビルドサーバーが午前 0 時を過ぎると、ビルド時間データストアは新しい日をロック解除します。これらの自己更新型の自己完結型の小さなシステムにより、サイトは常に最新の状態に保たれます。
スコープ設定されたスタイルと Open Props
Astro は、コンポーネント モデル内に記述されたスタイルをスコープします。これにより、多くのチームメンバーにワークロードを分散しやすくなり、Open Props の使用も楽しくなりました。Open Props normalize.css スタイルは、アダプティブ(ライトモードとダークモード)のテーマで役立ち、段落やヘッダーなどのコンテンツの整理にも役立ちました。
Astro の早期導入者として、PostCSS でいくつかの問題に直面しました。たとえば、ビルドの問題が多すぎるため、最新の Astro バージョンに更新できませんでした。ビルドとデベロッパー ワークフローの最適化に時間を割くことができます。
柔軟なコンテナ
一部のウィンドウは、アートを維持するためにアスペクト比を維持しながら拡大または縮小されます。他のウィンドウを使用して、コンテナクエリを備えたコンポーネントベースのアーキテクチャの強みを示しました。コンテナクエリにより、ウィンドウは個別のレスポンシブ スタイル設定情報を所有し、独自のサイズに基づいて再調整できるようになりました。一部のウィンドウは狭いサイズから広いサイズに変更されたため、ウィンドウ内のメディアのサイズとそのメディアの配置を調整する必要がありました。
ウィンドウに使用できるスペースが増えたら、ウィンドウのサイズまたは子要素を調整して収まるようにします。結果として、コンテナクエリは、アダプティブ ウィンドウを実現するために必要なだけでなく、特定のレイアウトのオケストレーションを大幅に簡素化できることがわかりました。
.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;
}
}
このアプローチは、アスペクト比を維持するアプローチとは異なります。より細かく管理でき、より多くの機会が得られます。ある程度の大きさになると、多くの子どもは新しいレイアウトに適応するために移動します。
コンテナクエリにより、ブロック方向(垂直)の制限をサポートできるようになったため、ウィンドウの長さが長くなるにつれて、スタイルを調整して適切に収まるようにできました。これは、単独で使用した高さベースのクエリと、幅ベースのクエリに加えて使用した高さベースのクエリで確認できます。
.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);
}
}
また、コンテナクエリを使用して、サイズが小さい場合はアートが増え、サイズが大きい場合はアートが少なくなるように、詳細を表示したり非表示にしたりしました。ウィンドウ 9 は、この機能が活用された好例です。
クロスブラウザのサポート
特にコンテナ クエリなどの試験運用版 API で、優れた最新のクロスブラウザ エクスペリエンスを実現するには、優れたポリフィルが必要です。チームに呼びかけ、Surma が新しいコンテナクエリ ポリフィルのビルドを主導しました。このポリフィルは、ResizeObserver、MutationObserver、CSS の :is() 関数に依存しています。そのため、すべての最新ブラウザ(特に Chrome と Edge のバージョン 88、Firefox のバージョン 78、Safari のバージョン 14)がポリフィルをサポートしています。ポリフィルを使用すると、次のいずれかの構文を使用できます。
/* These are all equivalent */
@container (min-width: 200px) {
/* ... */
}
@container (width >= 200px) {
/* ... */
}
@container size(width >= 200px) {
/* ... */
}
ダークモード
Designcember ウェブサイトに欠かせなかった最後の仕上げは、美しいダークモードでした。アート自体を活用して、優れたダークモード エクスペリエンスの作成に積極的に参加してもらう方法を示すことを目的としています。そのため、各ウィンドウの背景スタイルをプログラムで調整し、ウィンドウアートを作成する際に適切な CSS をできるだけ多く使用しました。背景のほとんどは CSS グラデーションだったので、色値を簡単に調整できました。その後、その上にアートを重ねました。
その他のイースター エッグ
パーソナライズ
サイトに個性を出すため、ページにいくつかのパーソナライズを加えました。1 つ目は、チームからインスピレーションを得たキャラクター キャストです。また、非アクティブな日には懐かしいスタイルのカーソルを追加し、ファビコンのスタイルを変更しました。
機能的なタップ
追加された機能のひとつが、建物の上に鳥が止まっている「今日にジャンプ」機能です。この鳥をクリックするか、Enter キーを押すと、ページがその月の現在の日付まで下にスクロールされ、最新のリリースにすぐにアクセスできます。
Designcember.com には、特別な印刷用スタイルシートもあります。8.5 x 11 インチの紙に最適な特定の画像が提供されるため、カレンダーを自分で印刷して、1 年中お祝い気分を味わうことができます。
12 月は UI 開発を祝うため、楽しくて風変わりな最新のウェブ エクスペリエンスを作成するために、多くの作業が行われました。ご視聴いただきありがとうございました。