はじめに:CSSだけでランダムUIは実現できるのか

Webデザインにおいて「ランダム性」は想像以上に強力なツールです。紙吹雪エフェクト、きらめく星空の背景、ランダムカラーのグリッドなど、ユーザー体験を豊かにする要素があります。しかし、このランダム性をCSSだけで実装するには、これまでJavaScriptに依存せざるを得ませんでした。

2025年後半、Safariがrandom()関数をいち早くサポートし、状況が変わりました。しかし問題は他のブラウザではまだ使用できないという点です。ChromeとFirefoxも開発中の兆候はありますが、いつ安定して使えるようになるかは不明です。

本記事では、CSS random()ポリフィルを実装し、実際のデモに適用する方法を段階的に共有します。Safariユーザーでなくても、ランダムUIを今すぐ実務に適用できる実践ガイドです。

なお、本記事は根拠資料を基に再構成しています。

Developer writing CSS random() polyfill code in a text editor on a laptop System Abstract Visual

核心:ポリフィルの動作原理とコード

ポリフィルの核心となるアイデアはシンプルです。ブラウザがrandom()をサポートしていなければ、JavaScriptで計算してインラインスタイルとして注入するというものです。

1. ネイティブサポートの検出

if (!CSS.supports("width", "random(0px, 100px)")) {
  // ポリフィル実行
}

2. --randomプレフィックス付きカスタムプロパティの収集

CSSカスタムプロパティは構文が非常に寛容です。ブラウザがrandom()を理解できなくても、値は文字列としてパースされ、JavaScriptから読み取ることができます。

.star {
  --random-star-size: random(1px, 7px, 1px);
  width: var(--random-star-size);
}

3. JavaScriptによる値の計算と注入

import { calc } from "@csstools/css-calc";

const calcFn = calc;

if (!CSS.supports("width", "random(0px, 100px)")) {
  // ちらつき防止のため一時的に非表示
  const styleTag = document.createElement("style");
  styleTag.textContent = ".randomized { display: none; }";
  document.head.appendChild(styleTag);

  const elementIDs = new WeakMap();
  const documentID = crypto.randomUUID();

  document.querySelectorAll(".randomized").forEach((element) => {
    const styles = getComputedStyle(element);
    [...styles]
      .filter((property) => property.startsWith("--random"))
      .forEach((propertyName) => {
        const css = styles.getPropertyValue(propertyName);
        const value = resolveRandom(css, {
          element,
          propertyName,
          documentID,
          elementIDs,
          calcFn,
          crypto,
        });
        element.style.setProperty(propertyName, value);
      });
  });

  // 非表示解除
  if (styleTag.parentNode) {
    styleTag.parentNode.removeChild(styleTag);
  }
}

function resolveRandom(css, { element, propertyName, documentID, elementIDs, calcFn, crypto }) {
  // base値がない場合は固定ランダム値を注入(均等分布の補正)
  const patchedCss = css.replace(
    /random\(\s*(?!(?:[^,]*\b(?:shared|scoped)\b|fixed\b|--))([^,]+),/gi,
    (_, expression) => `random(fixed ${Math.random()}, ${expression},`
  );

  return calcFn(patchedCss, {
    precision: 5,
    toCanonicalUnits: true,
    randomCaching: {
      documentID,
      elementID: elementIDs.getOrInsert(element, `element-${crypto.randomUUID()}`),
      propertyName,
    },
  });
}

4. HTMLにマーカークラスを追加

ポリフィル対象の要素にrandomizedクラスを付与すれば完了です。

<div class="star randomized"></div>

この方式の最大の利点は、ネイティブサポートが始まったらスクリプトを削除するだけという点です。CSSはそのまま維持されるため、マイグレーションの負担がほとんどありません。

Cross-browser CSS random() polyfill demo showing randomly scattered stars on a dark background

注意事項と発展的なTips

⚠️ 注意:ポリフィルの限界

  • 動的変更は非対応:現在の実装はページロード時点のcomputed styleのみを処理します。DOM変更やスタイルの動的変更には反応しません。
  • random-item()は未対応:リストからランダム選択するrandom-item()は、まだどのブラウザも実装していません(Safariプレビューを除く)。
  • 仕様変更の可能性:random()はまだEditor's Draft段階であり、主要なbreaking changeが予想されます。プロダクション適用時は注意が必要です。

💡 発展:random-item()の模倣

ChromiumのCSSカスタム関数(@function)とインライン条件文を組み合わせれば、random-item()に近い機能を実装できます。

@function --item(--index,
  --arg-1: , --arg-2: , --arg-3: , --arg-4: , --arg-5: ,
  --arg-6: , --arg-7: , --arg-8: , --arg-9: , --arg-10: ) {
  result: if(
    style(--index: 1): var(--arg-1);
    style(--index: 2): var(--arg-2);
    style(--index: 3): var(--arg-3);
    style(--index: 4): var(--arg-4);
    style(--index: 5): var(--arg-5);
    style(--index: 6): var(--arg-6);
    style(--index: 7): var(--arg-7);
    style(--index: 8): var(--arg-8);
    style(--index: 9): var(--arg-9);
    else: var(--arg-10);
  );
}

.square {
  --random-index: random(element-shared, 1, 5, 1);
  --random-color: --item(var(--random-index), aqua, purple, pink, grey, green);
  background-color: var(--random-color);
}

このアプローチは特定のデータ型に限定されず、CSS標準を意図された方法で活用するという点でハックではありません。

🇯🇵 日本の開発エコシステムにおける適用文脈

日本のWeb開発現場では、QiitaやZennなどのコミュニティでEmergent CSS機能の議論が活発です。特にフロントエンド領域では、Next.jsやAstroなどのモダンフレームワークと組み合わせたCSS機能の活用事例が頻繁に共有されています。ポリフィル自体がJavaScript依存を追加するため、「CSSだけで解決」という当初の目標とは若干の乖離が生じますが、インタラクティブなマーケティングページやプロトタイプ段階での活用が現実的です。

CSS random() polyfill code snippet with JavaScript and custom properties displayed on a monitor Developer Related Image

まとめ:今すぐ試すべきこと

CSS random()は確かに魅力的な機能です。しかしネイティブサポートがbaselineに到達するまでには時間がかかるでしょう。ポリフィルはその空白を埋める実用的なツールです。

実務適用のためのチェックリスト:

  1. ✅ ランダムUIが本当に必要かまず検討(過ぎたるは及ばざるが如し)
  2. ✅ ポリフィル適用時の初期ロード性能への影響を測定
  3. ✅ ネイティブサポート開始時のポリフィル削除計画を策定
  4. ✅ 仕様変更の可能性に備え抽象化レイヤーを維持

次のステップ学習方向:

  • CSS Values and Units Module Level 5仕様書の精読
  • @functionやインライン条件文などEmergent CSS機能の探求
  • @csstools/css-calcライブラリのソースコード分析

合わせて読みたい記事

ランダムなUIが必要なとき、JavaScriptなしでも十分エレガントな解決策があることを覚えておいてください。ハッピー・ランダマイジング! 🎲

本コンテンツは、信頼性の高い情報源をもとにAIツールを活用して作成され、編集者によるレビューを経て公開されています。専門家によるアドバイスの代替となるものではありません。