GODRICH
#cssアニメーション#ボタン#ローディング#トランジション#スクロール#ダッシュボード#実用ui#デザイントレンド

css 日付選択 9選 — ポップオーバーで開閉する9つの方式

css 日付選択:9つのうち1つは入力欄の焦点値がオンになるとカレンダーがポップオーバーとして開き、1つは許可範囲外の日付の霞み値が大きくなって選べない状態が現れ、もう1つは画面幅の値が狭くなるとポップオーバーが下から上がるシートに変わります。

自動再生 · タイルを押すとその項目へ · すべて1つのzip

これら9つのデモはいずれもサーバーと通信せず、localStorage にも触れず、乱数も使いません。それぞれが1つの真偽値・文字列・数値の状態を軸に、その値の変化がどう見えるかを少数の定数だけで決めている小さな html カレンダー 日付選択 の実装です。この狙いの狭さのおかげで、焦点・範囲・モード・幅のどの値が切り替わるのかを先に確認すれば、コードを開く前にパターンの名前が自然と分かります。

9つのパターンの解剖 — どの値がいつ変わるか

9つのうち requestAnimationFrame ループを使うのは2つだけです。05番の pulseAt() は指数減衰にコサイン振動を掛け合わせてフレームごとに今日リングの拡大率と不透明度、バッジ自身の小さな拍動を求め、08番の shakeAt() は同じ減衰×振動の式をセルの translateX に使います。他の7つは単一のCSSトランジションで収まるため、STAGGER・FADE_STEP・SHAKE_ZETA のような定数は、フレームごとに再計算される値ではなく意図した質感を表すだけです。9つのうち4つは描画前に実際のレイアウトを実測します。01番の measureAnchor() は入力欄の getBoundingClientRect() を読み、その実測した下端から ANCHOR_GAP 分だけ下にポップオーバーを置きます。02番の slideTo() はビューポートの実測幅を読んで月送りのスライド距離を決め、03番の moveRingTo() はフォーカスされたセルの位置を読んでキーボードリングをそこへ動かし、07番の measureMode() はビューポートの実測幅を THRESHOLD と比べてポップオーバーかシートかを選びます。残りの04・05・06・08・09番は固定定数だけで動きます(FADE_STEP/FADE_FLOOR、DUR/ZETA/FREQ、PRESETS/STAGGER、SHAKE_ZETA/BANNER_MS、単純な真偽値の切替)。DOM実測は一度も呼ばれないため、実測する4つのようにビューポートのサイズに応じて計算が変わることはありません。リスナーはどれも実際の操作に答えます。04・06・07・08・09番は click だけを聞き、01番は入力欄の click に加えて Escape 用の keydown と、ポップオーバー外をクリックしたときに閉じるdocument側の click を組み合わせ、02番はヘッダーとナビゲーションの click に左右矢印キー用の keydown を組み合わせ、03番は focusin・左右矢印で1、上下矢印で7動かす keydown・click を組み合わせ、05番はバッジの click に keydown を組み合わせます。9つのどれも new Date() を使わず、01・03・04・05・06・08番は固定の BASE = { y: 2026, m: 3, d: 14 } を基準にし、02番は同じ考え方の YEAR = 2026 を基準にします(07番と09番は今日の値そのものを持たない仕組みです)。そのため、ページをいつ開いても「今日」は変わりません。

パターン別コード

01入力ポップオーバー切替 — 入力欄の焦点値がオンになるとカレンダーがポップオーバーとして開き、オフになると閉じる方式

入力欄の焦点値がオンになると、カレンダーが入力欄の直下にポップオーバーとして開き、高さがわずかに目標値を超えてから収まります。オフになると同じポップオーバーが閉じます。予約フォームの日付欄や、絞り込みパネルの期間入力に向く方式で、ポップオーバー自身がどの入力欄から開いたのかを見た目で示す必要がある場面に合います。

入力ポップオーバー切替 — 入力欄の焦点値がオンになるとカレンダーがポップオーバーとして開き、オフになると閉じる方式
新しいタブで開く

01 · 入力ポップオーバー切替 — 入力欄の焦点値がオンになるとカレンダーがポップオーバーとして開き、オフになると閉じる方式 — 計測 累積面積 25.682% · 動いたフレーム 8/23GODRICH オリジナル · SCSS と React は zip に同梱 · パスワードを見る

measureAnchor()ANCHOR_GAP$ease-elastic
  function measureAnchor() {
    // 計算層: 実測位置 — 入力欄の実際のレンダー矩形を読み、その位置にポップオーバーを固定する
    var fr = field.getBoundingClientRect();
    var pr = dp.getBoundingClientRect();
    pop.style.left = (fr.left - pr.left) + 'px';
    pop.style.top = (fr.bottom - pr.top + ANCHOR_GAP) + 'px';
    pop.style.width = fr.width + 'px';
  }

  function setOpen(v) {
    dp.classList.toggle('dp--open', v);
    field.setAttribute('aria-expanded', v ? 'true' : 'false');
    pop.setAttribute('aria-hidden', v ? 'false' : 'true');
    if (v) measureAnchor();
  }

数値が語ること

01番は累積面積25.68%・平均強度84.3を23サンプル中8フレームで示し、目標値をわずかに超えてから収まるポップオーバーの高さの動きが、単純な表示・非表示の切替に一拍加えています。

02月年単位切替 — 表示単位の値が月から年に変わると複数年を一度に飛ばせる方式

中央のラベル値を操作するたびに表示単位の値が月と年の間で切り替わり、年モードでのジャンプは一度に大きな期間を移動します。生年月日の入力や、古い記録まで遡る期間選択に役立つ方式で、何十年も前の日付まで月ごとにページ送りする手間を省きます。

月年単位切替 — 表示単位の値が月から年に変わると複数年を一度に飛ばせる方式
新しいタブで開く

02 · 月年単位切替 — 表示単位の値が月から年に変わると複数年を一度に飛ばせる方式 — 計測 累積面積 5.122% · 動いたフレーム 19/23GODRICH オリジナル · SCSS と React は zip に同梱 · パスワードを見る

AUTO_SEQCELL_TOTALmode
  function stepMonth(delta) {
    var target = current + delta;
    if (target < 1) target = 12;
    if (target > 12) target = 1;
    slideTo(target);
  }

  function toggleYear() {
    mode = mode === 'year' ? 'month' : 'year';
    root.classList.toggle('mj--year', mode === 'year');
    if (mode === 'year') renderYear(current);
  }

数値が語ること

02番は累積面積5.12%・平均強度109.6を23サンプル中19フレームで示し、月表示のスライドと年グリッドへの切替が、1フレームあたりの面積は小さくてもほぼ全サンプルにわたって動きを保っています。

03キーボード移動切替 — 方向値が変わるたびハイライトセルの値がグリッド上を移動する方式

方向値が変わるたびにハイライトセルの値が隣のセルへ移動し、行の端では次の行へ滑らかに折り返します。キーボード操作を主とする入力フォームや、アクセシビリティを重視するダッシュボードに向く方式で、マウスに触れずグリッド上のどの日付にも到達できます。

キーボード移動切替 — 方向値が変わるたびハイライトセルの値がグリッド上を移動する方式
新しいタブで開く

03 · キーボード移動切替 — 方向値が変わるたびハイライトセルの値がグリッド上を移動する方式 — 計測 累積面積 2.131% · 動いたフレーム 8/23GODRICH オリジナル · SCSS と React は zip に同梱 · パスワードを見る

FOCUS_SEQmoveRingTo()focusDay()
  grid.addEventListener('keydown', function (e) {
    var delta = 0;
    if (e.key === 'ArrowRight') delta = 1;
    else if (e.key === 'ArrowLeft') delta = -1;
    else if (e.key === 'ArrowDown') delta = 7;
    else if (e.key === 'ArrowUp') delta = -7;
    else return;
    e.preventDefault();
    human();
    focusDay(focusedDay + delta);
  });
  grid.addEventListener('click', function (e) {
    var cellEl = e.target.closest('.kb__cell');
    if (!cellEl || !cellEl.dataset.day) return;
    human();
    focusDay(parseInt(cellEl.dataset.day, 10));
  });

数値が語ること

03番は累積面積2.13%・平均強度111.3を23サンプル中8フレームで示し、リングがセルからセルへ移るだけでグリッド自体は再描画されないため、面積は薄く保たれます。

04範囲外霞み切替 — 許可範囲の値を外れた日付の霞み値が大きくなり選べない状態に変わる方式

許可範囲の値を外れたセルは霞み値が上がり、押下時の反応値も失って他のセルから浮き上がります。予約可能期間が限られた予約ピッカーや、有効期間内に限られるクーポン利用日に向く方式で、範囲外の日付が一目で選べない状態だと分かる必要がある場面に合います。

範囲外霞み切替 — 許可範囲の値を外れた日付の霞み値が大きくなり選べない状態に変わる方式
新しいタブで開く

04 · 範囲外霞み切替 — 許可範囲の値を外れた日付の霞み値が大きくなり選べない状態に変わる方式 — 計測 累積面積 4.213% · 動いたフレーム 14/23GODRICH オリジナル · SCSS と React は zip に同梱 · パスワードを見る

FADE_STEPFADE_FLOORrecompute()
  function recompute() {
    // 計算層: 範囲外の各セルは境界からの距離に応じて不透明度を下げる
    for (var day = 1; day <= n; day++) {
      var c = cellByDay[day];
      var distOut = day < min ? (min - day) : (day > max ? (day - max) : 0);
      var opacity = distOut === 0 ? 1 : Math.max(FADE_FLOOR, 1 - distOut * FADE_STEP);
      c.style.opacity = String(opacity);
      c.classList.toggle('mf__cell--bound', day === min || day === max);
      c.classList.toggle('mf__cell--out-range', distOut > 0);
    }
  }

数値が語ること

04番は累積面積4.21%・平均強度83.8を23サンプル中14フレームで示し、範囲の最小値か最大値が変わるたびに霞みの再計算が新たに範囲外になったセルだけでなく月内のすべての日を触れています。

05今日表示切替 — 今日の値を持つマスの周りでリングが周期的に広がりながら薄くなる方式

今日の値を持つマスの周りでリングが緩やかな周期で広がって薄くなり、バッジ自身もわずかに拡大率が拍動しますが、選択値と重なっても紛れません。出勤確認カレンダーや、締切日近くの日程確認に役立つ方式で、今日を選択日と誤認させずに目立たせる必要がある場面に合います。

今日表示切替 — 今日の値を持つマスの周りでリングが周期的に広がりながら薄くなる方式
新しいタブで開く

05 · 今日表示切替 — 今日の値を持つマスの周りでリングが周期的に広がりながら薄くなる方式 — 計測 累積面積 3.242% · 動いたフレーム 16/23GODRICH オリジナル · SCSS と React は zip に同梱 · パスワードを見る

pulseAt()DURZETA
  function pulseAt(t) {
    // 計算層: 指数減衰 × コサイン振動 — スプリングが収まる物理量をそのまま計算する
    if (t < 0 || t > DUR) return { ring: 0, ringAlpha: 0, badge: 1 };
    var x = t / DUR;
    var amp = Math.exp(-ZETA * x);
    var osc = Math.cos(FREQ * t);
    var ringScale = 1 + 1.9 * (1 - amp);
    var ringAlpha = Math.max(0, amp * .55);
    var badgeScale = 1 + .16 * amp * osc;
    return { ring: ringScale, ringAlpha: ringAlpha, badge: badgeScale };
  }

数値が語ること

05番は累積面積3.24%・平均強度38.3を23サンプル中16フレームで示します。バッジ大のエフェクトなので面積が小さいのは想定どおりで、フレーム数が多いのは実際に広く再描画しているからではなく、pulseAt() が1,100msの全サイクルにわたって減衰×振動の式を計算し続けているためです。

06クイック選択切替 — チップの値を選ぶと格子を経ずに日付の値が直接決まる方式

チップの値をオンにすると格子に触れずに日付の値が直接決まり、そのチップの背景値だけが塗られて選択を示します。レポートの期間クイック選択や、検索フィルターの直近期間ショートカットに向く方式で、範囲の両端をクリックするより言葉で期間を指定する方が速い場面に合います。

クイック選択切替 — チップの値を選ぶと格子を経ずに日付の値が直接決まる方式
新しいタブで開く

06 · クイック選択切替 — チップの値を選ぶと格子を経ずに日付の値が直接決まる方式 — 計測 累積面積 11.493% · 動いたフレーム 18/23GODRICH オリジナル · SCSS と React は zip に同梱 · パスワードを見る

PRESETSSTAGGERapplyPreset()
  function applyPreset(idx) {
    // 計算層: 選択範囲の開始日からの位置(pos)分だけ遷移を遅らせ、順番に塗る動きを作る
    var p = PRESETS[idx];
    for (var day = 1; day <= n; day++) {
      var c = cellByDay[day];
      var inRange = day >= p.start && day <= p.end;
      if (inRange) {
        var pos = day - p.start;
        c.style.transitionDelay = (pos * STAGGER) + 'ms';
      } else {
        c.style.transitionDelay = '0ms';
      }
      c.classList.toggle('ps__cell--on', inRange);
    }
    chipEls.forEach(function (el, i2) { el.classList.toggle('ps__chip--active', i2 === idx); });
  }

数値が語ること

06番は累積面積11.49%・平均強度63.8を23サンプル中18フレームで示し、applyPreset() のセルごとの遷移遅延が、背景の塗りを一度に終わらせず、ほぼ全サンプルにわたって動きを広げています。

07シート切替 — 画面幅の値が狭くなるとポップオーバーの値が下から上がるシートの値に変わる方式

画面幅の値がしきい値を下回ると、同じカレンダーがポップオーバーではなく下から上がるシートとして現れ、ボタンを操作すると幅の値が切り替わります。モバイル予約アプリの日付選択や、狭い画面での絞り込みパネルに向く方式で、中央固定のポップオーバーが小さな画面の端からはみ出す事態を避けられます。

シート切替 — 画面幅の値が狭くなるとポップオーバーの値が下から上がるシートの値に変わる方式
新しいタブで開く

07 · シート切替 — 画面幅の値が狭くなるとポップオーバーの値が下から上がるシートの値に変わる方式 — 計測 累積面積 17.928% · 動いたフレーム 15/23GODRICH オリジナル · SCSS と React は zip に同梱 · パスワードを見る

THRESHOLDmeasureMode()viewport
  function measureMode() {
    // 計算層: ビューポート要素の実際のレンダー幅を実測してポップオーバーかシートかを選ぶ
    var w = viewport.getBoundingClientRect().width;
    return w < THRESHOLD ? 'sheet' : 'popover';
  }

  function render() {
    var mode = measureMode();
    panel.classList.toggle('ms--open', open);
    panel.classList.toggle('ms__panel--sheet', mode === 'sheet');
    panel.classList.toggle('ms__panel--popover', mode === 'popover');
  }

  function human() {
    ms.classList.remove('is-demo');
    stopAutoplay();
  }

  field.addEventListener('click', function () {
    human();
    open = !open;
    render();
  });

数値が語ること

07番は累積面積17.93%・平均強度106.2を23サンプル中15フレームで示し、下から上がるシートの動きは、01番のポップオーバー表示を除けばこの9つの中で1フレームあたりの面積が最も広い動きです。

08拒否振動切替 — ブロックされた値に触れるとそのマスの位置の値が短く左右に揺れる方式

ブロックされた値に触れるとそのマスの位置の値が短く左右に揺れ、通知バナーの不透明度の値も一瞬上がってから消えます。既に予約済みの日付の再選択を防ぐ場合や、受付終了日を示す場合に向く方式で、揺れが特定のクリックへの直接的な返答として読み取れます。

拒否振動切替 — ブロックされた値に触れるとそのマスの位置の値が短く左右に揺れる方式
新しいタブで開く

08 · 拒否振動切替 — ブロックされた値に触れるとそのマスの位置の値が短く左右に揺れる方式 — 計測 累積面積 3.376% · 動いたフレーム 16/23GODRICH オリジナル · SCSS と React は zip に同梱 · パスワードを見る

shakeAt()SHAKE_ZETABANNER_MS
  function shakeAt(t) {
    // 計算層: 指数減衰 × コサイン振動をピクセルのオフセットに変換する
    if (t < 0 || t > SHAKE_DUR) return 0;
    var x = t / SHAKE_DUR;
    var amp = Math.exp(-SHAKE_ZETA * x);
    return SHAKE_AMP * amp * Math.cos(SHAKE_FREQ * t);
  }

  function loop(ts) {
    if (shakeTarget) {
      var elapsed = ts - shakeStart;
      if (elapsed > SHAKE_DUR) {
        shakeTarget.style.transform = '';
        shakeTarget = null;
      } else {
        shakeTarget.style.transform = 'translateX(' + shakeAt(elapsed).toFixed(2) + 'px)';
      }
    }
    rafId = requestAnimationFrame(loop);
  }

数値が語ること

08番は累積面積3.38%・平均強度39.3を23サンプル中16フレームで示し、05番と近い数字になるのも同じ理由です。shakeAt() は1つのセルの translateX とバナーの不透明度しか動かさないため、バネのように減衰する物理演算が広い面積を必要とせずにサイクル全体を通して走ります。

09モーション削減代替切替 — モーション削減の値がオンになるとポップオーバー・シート・振動の値が即座に切り替わる方式

モーション削減の値がオンになると、前の8つのパターンにあった動きや揺れの値がすべて外れ、瞬時の表示・非表示の値だけが残ります。モーションを抑える設定を有効にしている利用者や、省電力デバイスの入力画面がまさにこの方式の対象で、他の8つが何に切り替わるかを示すためだけに作られた項目です。

モーション削減代替切替 — モーション削減の値がオンになるとポップオーバー・シート・振動の値が即座に切り替わる方式
新しいタブで開く

09 · モーション削減代替切替 — モーション削減の値がオンになるとポップオーバー・シート・振動の値が即座に切り替わる方式 — 計測 累積面積 3.151% · 動いたフレーム 15/23GODRICH オリジナル · SCSS と React は zip に同梱 · パスワードを見る

rm__pop--normalrm__pop--reducedprefers-reduced-motion
.rm__pop {
  position: absolute; top: 100%; left: 0; right: 0; margin-top: $sp-1;
  box-sizing: border-box; padding: $sp-1; border-radius: $r-sm;
  background: $stage-paper; box-shadow: $shadow-raised;
  opacity: 0; pointer-events: none;
}
.rm__pop--normal {
  transform: scale(.8);
  transform-origin: top center;
  transition: transform $dur-enter $ease-elastic, opacity $dur-quick $ease-out;
}
.rm__pop--normal.is-open { transform: scale(1); opacity: 1; pointer-events: auto; }
.rm__pop--reduced {
  transition: opacity $dur-quick $ease-out;
}
.rm__pop--reduced.is-open { opacity: 1; pointer-events: auto; }

数値が語ること

09番は累積面積3.15%・平均強度76.6を23サンプル中15フレームで示し、この横並び比較はどちらもカレンダー全体ではなく2つの小さなポップオーバーだけを動かしています。

値がポップオーバーを開閉する基準 — 焦点値・範囲値・幅の基準

01番の入力欄クリックと ANCHOR_GAP 8px — 入力欄を操作した瞬間にカレンダーがポップオーバーとして開き、measureAnchor() が実測した入力欄の下端からちょうど ANCHOR_GAP ピクセル下に固定します。ポップオーバーの外側をクリックするか Escape を押すと再び閉じます。

04番の FADE_STEP .12 と FADE_FLOOR .15 — min 〜 max の範囲を外れた日付の不透明度がどれだけ急に落ちるかを決めます。recompute() は月内のすべての日を調べ、境界からの距離1日ごとに不透明度を .12 ずつ下げ、.15 の下限で止めます。

07番の THRESHOLD 140px — この方式の中で唯一、細部ではなくピッカー全体の形を変える値です。measureMode() がビューポートの実測幅を読み、140 を下回った瞬間、同じカレンダーが入力欄に固定されたポップオーバーから、別のボタンで上げ下げするシートに切り替わります。この閾値の設計こそ、日付選択 ui スマホ の使い勝手を左右する要になります。

この記事以外にも、カレンダー 選択 UI 9選 — コピペOK は別の軸で動きます。同じような月グリッドの上で、1つの値のために1つの入力欄が1つのポップオーバーを開くのではなく、2回のクリックで開始日と終了日の間を塗りつぶします。カレンダー css デザイン 9選 — 実際に月が動く は入力欄もポップオーバーも取り払い、カレンダーグリッド自体を目的地として扱います。この記事のグリッドは、その同じ月の計算を入力欄に紐づけて使った一形態にすぎません。タイムピッカー ui 9選 — 一点から区間まで はカレンダーを時計の文字盤と期間コントロールに置き換えるため、値は日や週ではなく時間や分の軸で動きます。この3つをこの記事と比べれば、CSSを1行も書く前に、ある 日付選択 ui がどの軸に属するのか最も早く見極められます。

どこで壊れるか — 狭い画面・範囲外入力・モーション削減

9つのうちどれも、入力欄をネイティブな <input type="date"> として作っていません。すべてがポップオーバーやシートを独自に操作するボタンかdivであり、それによってブラウザ標準のピッカーがどんな見た目になるかに任せるのではなく、カレンダーの開き方そのものを自分で決められます。

範囲の境界を日付が越える瞬間

04番の recompute() は min か max が変わったとき——このデモではグリッドのクリックか自動再生の tick() のときだけ——動きます。外部のフォーム欄から min/max を操作する実装につなぐ場合は、変更のたびに recompute() 自身を呼び直す必要があり、そうしないと範囲を新たに外れた日付が、次にたまたま再描画を起こすクリックまで元の不透明な見た目のまま残ります。

狭い画面

9つすべてがSCSSに @media (max-width: 340px) を持っていますが、07番だけはその幅よりずっと手前でレイアウトの形自体を変えられます。measureMode() の THRESHOLD 判定はビューポート幅140pxで popover と sheet のクラスを切り替え、これは他の8つが余白や文字サイズのために使う共通の340pxのルールとは無関係な、独自のブレークポイントです。この9つのソース全部は上のzipに入っていて、2s5u3jbfを入力すれば開きます。

モーション削減

9つすべてがJavaScript側で matchMedia('(prefers-reduced-motion: reduce)') を自動ループを始める前に確認し、すべてがCSS側にも @media (prefers-reduced-motion: reduce) を用意しています。09番はこの違いを並べて示すためだけに作られた項目です。rm__pop--normal は transform と opacity の両方をトランジションさせ、rm__pop--reduced は opacity だけをトランジションさせ、モーション削減用のメディアブロックは通常側もその同じopacityだけのトランジションまで削ります。そのため、モーション削減を有効にした利用者には比較の両側が同じ瞬時のフェードに見えます。

3つのバリエーションとアクセシビリティ

今日リングの減衰比を下げる(ZETA 4.2 から 2.0) — 減衰定数を4.2から2.0に下げると、リングは一度で収まらず二、三回余分に波打つように広がって薄くなります。

拒否振動の減衰比を下げる(SHAKE_ZETA 6.5 から 3.0) — 減衰定数を6.5から3.0に下げると、振動は一度で止まらず左右に数回余分に揺れ、拒否感がより強く感じられます。

チップ塗りつぶしの伝播を遅くする(STAGGER 28 から 70) — 遅延値を28から70に伸ばすと、背景が開始日から終了日までほぼ同時に染まらず、波のように一マスずつ遅れて塗られるのが見えます。

バリエーション 変わるもの 変わらないもの
今日リングの減衰比を下げる(ZETA 4.2→2.0) 05番のリング拍動の回数だけ DUR・FREQ・バッジ自身の拡大率
拒否振動の減衰比を下げる(SHAKE_ZETA 6.5→3.0) 08番の振動回数だけ BANNER_MS・SHAKE_AMP・SHAKE_FREQ
チップ塗りつぶしの伝播を遅くする(STAGGER 28→70) 06番のセルごとの塗り遅延だけ PRESETS・アクティブチップのクラス処理

9つの中で非ネイティブのroleを使うのは01番と03番だけです。01番のパネルは role="dialog" に aria-label を持ち、aria-haspopup と aria-expanded を持つ入力欄から開きます。03番は role="grid" のdivの上に、常に1つのセルだけへフォーカスを渡すローミング tabIndex を組んでおり、矢印キーでの移動がネイティブなグリッドウィジェットの読み上げに近い挙動になります。01・02・03・04・05・06・08番は曜日見出し行に aria-hidden を設定しており(07番と09番にはこの見出し行自体がありません)、02番と03番はさらに aria-label でコントロールを説明します。9つのどれも disabled 属性を使いません。04番の範囲外の日付でさえフォーカス可能なまま不透明度だけが下がるため、範囲やモードの値によってキーボードのフォーカス順序が変わることはありません。

FAQ

なぜ日付を直接テキスト欄に入力せず「カレンダー 日付選択」で検索する人が多いのでしょうか

日付をテキストで打つと、地域やブラウザによって書式のずれや誤入力を招きやすく、この9つはどれもネイティブな <input type="date"> を使っていません。どの入力欄も単なるボタンでカレンダーを開くため、利用者がどんな書式に慣れていても選んだ値は常に一意になります。

ブラウザの幅を変えると、この9つのうちどれかは本当に下から上がるシートに変わりますか

変わるのは07番だけです。measureMode() は render() が呼ばれるたびにビューポートの実測幅を読み、THRESHOLD の140pxを下回った瞬間に ms__panel--popover から ms__panel--sheet に切り替わります。残りの8つはビューポートがどれだけ狭くなっても1つの見た目のままです。

05番の今日リングはCSSの @keyframes で動いていますか、それとも計算で作られていますか

計算で作られています。pulseAt() は指数減衰 Math.exp(-ZETA * x) にコサイン振動 Math.cos(FREQ * t) を掛け合わせて毎フレーム、リングの拡大率と不透明度、バッジ自身の小さな拍動を求めており、この動きのどの部分もCSSの @keyframes から来ていません。

Sources: MDN — Using CSS transitions · MDN — Window: requestAnimationFrame() method · MDN — prefers-reduced-motion · W3C ARIA APG — Date Picker Dialog Pattern

解凍パスワードを入力してください

パスワードはこの記事の本文の中にあります。読み進めると出てきます。