Days Elapsed


一年を「面」で見る

一年は365日。数字で見ると多いけど、並べてみると案外少ない。

12ヶ月を並べて、過去を塗りつぶして、今日を光らせる。それだけのカレンダーを作った。進捗バーが「一次元」なら、これは「二次元」の進捗表示。

Year Progress
一年は50週ちょっとしかない 2026年を週で数えると、52週とちょっと。 カレンダーで見ると長そうなのに、週で数えると急に短くなる。そんな感覚を形にしたくて、このページの上の方に進捗バーを置いた。 やっていることは単純で、「今年が何%進んだか」をリアルタイムで表示しているだけ。 なぜ作ったか 理由は3つある。 1. 時間を「量」として見たかった ── イベントや予定ではなく、単純に「どれだけ経ったか」を数値で見たかった。 2. 目に見える形にしたかった ── 抽象的な「一年」を、動く数字に落とすとどう感じるか試したかった。 3. 自分の場所に置きたかった ── 誰かのツールを借りるのではなく、自分のブログに自分で作ったものを置きたかった。 実装の話 せっかく作るなら、それなりに丁寧にやりたかった。 * Web Components で実装。ブログのCSSやDOMを汚さず、どこにでも持っていける。 * requestAnimationFrame で描画。固定間隔のタイマーではなく、画面更新に同期させることで滑らかさとリソース

これは一年の進捗バー


なぜ作ったか

進捗バーでは「どれだけ進んだか」はわかる。でも「今どこにいるか」は見えない。

  • 空間で把握したかった ── 線ではなく面で。12月がどこにあるか、今が年のどのあたりか、一目でわかるようにしたかった。
  • 月の重みを感じたかった ── 1月も12月も同じ1マス。でも並べると、過ぎた月と残った月の差が目に見える。
  • GitHubの草が好きだった ── あの「塗りつぶされていく感覚」を、一年単位で味わいたかった。

設計の話

レスポンシブは妥協しない

最初は GitHub 風の「7行 × 53列」で作った。見た目は良かったけど、スマホで横スクロールが発生して使い物にならなかった。

解決策は「月ベースのレイアウト」。12ヶ月を並べて、画面幅に応じて 4列 → 3列 → 2列 と自動で切り替わる。Container Queries を使って、親要素の幅に反応するようにした。

@container (min-width: 600px) {
  .year { grid-template-columns: repeat(4, 1fr); }
}
@container (min-width: 400px) and (max-width: 599px) {
  .year { grid-template-columns: repeat(3, 1fr); }
}

どの画面でも横スクロールは発生しない。

日付変更を正確に検知する

0時0分0秒に「今日」が移動する。そのタイミングを逃さないために、次の0時までの残り時間を計算して setTimeout をセットしている。

タブがバックグラウンドにあると JavaScript のタイマーは信用できないから、visibilitychange で復帰時に再チェックする仕組みも入れた。

色はすべて oklch()

従来の hsl() は、同じ彩度・明度でも色相によって見た目の明るさが変わる。oklch() は知覚的に均一な色空間で、hue を変えるだけで一貫した見た目が保てる。

--_past: oklch(55% 0.15 var(--_hue));
--_today: oklch(65% 0.22 var(--_hue));

緑でも青でも紫でも、--calendar-hue を変えるだけでテーマが変わる。


アクセシビリティ

派手なアニメーションは人を選ぶ。

  • prefers-reduced-motion ── アニメーションを無効化。今日のセルも静的な強調に切り替わる。
  • forced-colors ── Windows のハイコントラストモードでも、過去・今日・未来が区別できるようにした。
  • aria-label ── スクリーンリーダーには「2025: 364/365 (99.7%)」のように進捗を読み上げる。

見た目だけじゃなく、見えない人にも情報が届くようにした。


年末に眺める

今、このカレンダーを見ると、ほとんど塗りつぶされている。残っているのは数日だけ。

来年の1月1日になったら、すべてが空になる。そしてまた少しずつ埋まっていく。

その繰り返し。

Read more

Boids

群れに指揮者はいない 鳥の群れは、誰かが指示を出しているわけではない。魚の群れも同じ。それぞれが周囲を見て、少しだけ動く。その繰り返しが、全体として秩序ある動きを生む。 これを1986年にCraig Reynoldsがコードで再現した。名前は Boids(bird + oid)。個体に与えるルールは3つだけ。 1. Separation ── 近すぎたら離れる 2. Alignment ── 周囲と同じ方向を向く 3. Cohesion ── 群れの中心に寄る これだけで、群れは群れらしく動く。 なぜ作ったか 群れの動きは、見ていて飽きない。 * 単純なルールから複雑な動きが生まれる ── 創発(emergence)の典型例。設計していないのに、設計したかのように見える。 * 自分のブログに置きたかった ── 静的なページに、動くものがあると空気が変わる。 * Web Components で作りたかった ── どこにでも持っていける部品として。 設計の話 見えないときは止める 画面外でアニメーションを回し続けるのは無駄。Inte

By Sakashita Yasunobu

Year Progress

一年は50週ちょっとしかない 一年を週で数えると、52週とちょっと。 カレンダーで見ると長そうなのに、週で数えると急に短くなる。そんな感覚を形にしたくて、このページの上の方に進捗バーを置いた。 やっていることは単純で、「今年が何%進んだか」をリアルタイムで表示しているだけ。 なぜ作ったか 理由は3つある。 1. 時間を「量」として見たかった ── イベントや予定ではなく、単純に「どれだけ経ったか」を数値で見たかった。 2. 目に見える形にしたかった ── 抽象的な「一年」を、動く数字に落とすとどう感じるか試したかった。 3. 自分の場所に置きたかった ── 誰かのツールを借りるのではなく、自分のブログに自分で作ったものを置きたかった。 実装の話 せっかく作るなら、それなりに丁寧にやりたかった。 * Web Components で実装。ブログのCSSやDOMを汚さず、どこにでも持っていける。 * requestAnimationFrame で描画。固定間隔のタイマーではなく、画面更新に同期させることで滑らかさとリソース効率を両立。 *

By Sakashita Yasunobu
AVIFを使っていこうと思った話

AVIFを使っていこうと思った話

以前の記事の振り返り 以前、ブログで使うWeb用の画像のフォーマットについて検討するで「Web用の画像フォーマット」を比較して、当時は WebPがいちばん現実的という結論にしていた。 ブログで使うWeb用の画像のフォーマットについて検討する背景と目的 普段から写真撮影を行っていると、画像ファイルが占める容量は無視できない規模になる。現在はNASとAmazon Photosに保存しているため、容量的な制約は少ないものの、ファイルサイズが小さくできるのであれば小さくしておく方が合理的だ。特にWeb公開を前提とする場合、ファイルサイズはアップロード・ダウンロード、そしてページ表示時間に直結するため、可能な限り小さい方が望ましい。 これまでは現像ソフトからJPEG品質100で出力し、Web用途など容量削減が望ましいケースではWebPに変換してきた。RAWファイルは別途バックアップしてアーカイブとして保存している。目視で画質劣化が認められないのであれば、全てWebPで保存しても問題ないのではないかと考えたが、より優れたフォーマットが存在する可能性があるため、現在利用可能な画像フォーマットにつ

By Sakashita Yasunobu