FE_Test / docs /css-variable-design.md
GitHub Actions
Deploy from GitHub Actions [test] - 2025-10-31 10:18:25
5f2aab6

CSS変数設計仕様書

概要

ThemeExtractionResult型の15色カラーパレットとCSS変数のマッピング設計、および既存CSS構造との統合方法を定義します。

1. ThemeExtractionResult型との対応関係

1.1 現在の15色カラーパレット構造

interface ColorTheme {
  // メインカラー
  primary_color: string;           // #RRGGBB
  secondary_color: string;         // #RRGGBB
  accent_color: string;           // #RRGGBB

  // セマンティックカラー
  success_semantic_color: string; // #RRGGBB
  warning_semantic_color: string; // #RRGGBB
  error_semantic_color: string;   // #RRGGBB
  info_semantic_color: string;    // #RRGGBB

  // 背景色
  primary_background_color: string;    // #RRGGBB
  secondary_background_color: string;  // #RRGGBB
  tertiary_background_color: string;   // #RRGGBB
  overlay_background_color: string;    // #RRGGBB

  // テキスト色
  primary_text_color: string;     // #RRGGBB
  secondary_text_color: string;   // #RRGGBB
  disabled_text_color: string;    // #RRGGBB
  inverse_text_color: string;     // #RRGGBB
}

2. CSS変数マッピング設計

2.1 基本CSS変数定義

:root {
  /* === メインカラーパレット === */
  --theme-primary-color: var(--extracted-primary-color, #5a6c7d);
  --theme-secondary-color: var(--extracted-secondary-color, #34495e);
  --theme-accent-color: var(--extracted-accent-color, #f59e0b);

  /* === セマンティックカラー === */
  --theme-success-color: var(--extracted-success-semantic-color, #28a745);
  --theme-warning-color: var(--extracted-warning-semantic-color, #f59e0b);
  --theme-error-color: var(--extracted-error-semantic-color, #dc3545);
  --theme-info-color: var(--extracted-info-semantic-color, #17a2b8);

  /* === 背景色 === */
  --theme-primary-bg: var(--extracted-primary-background-color, white);
  --theme-secondary-bg: var(--extracted-secondary-background-color, #f8f9fa);
  --theme-tertiary-bg: var(--extracted-tertiary-background-color, #222222);
  --theme-overlay-bg: var(--extracted-overlay-background-color, rgba(0,0,0,0.5));

  /* === テキスト色 === */
  --theme-primary-text: var(--extracted-primary-text-color, #222222);
  --theme-secondary-text: var(--extracted-secondary-text-color, #555555);
  --theme-disabled-text: var(--extracted-disabled-text-color, #999999);
  --theme-inverse-text: var(--extracted-inverse-text-color, white);

  /* === フォントファミリー === */
  --theme-primary-font: var(--extracted-primary-font,
    "YuGothic", "Yu Gothic Medium", "Yu Gothic", "Hiragino Sans",
    "Hiragino Kaku Gothic ProN", -apple-system, BlinkMacSystemFont,
    "Segoe UI", Roboto, "Meiryo", sans-serif);
}

2.2 既存色との後方互換マッピング

:root {
  /* === 既存色の変数化(後方互換性確保) === */

  /* 最頻出色 → テーマ色へのマッピング */
  --legacy-primary-text: var(--theme-primary-text);        /* #222222 → primary_text_color */
  --legacy-accent: var(--theme-primary-color);             /* #5a6c7d → primary_color */
  --legacy-border: var(--theme-secondary-text);            /* #e9ecef → secondary_text_color */
  --legacy-light-bg: var(--theme-secondary-bg);            /* #f8f9fa → secondary_background_color */
  --legacy-secondary-text: var(--theme-secondary-text);    /* #34495e → secondary_text_color */

  /* セクション背景色のマッピング */
  --section-white-bg: var(--theme-primary-bg);             /* white → primary_background_color */
  --section-gray-bg: var(--theme-secondary-bg);            /* #f8f9fa → secondary_background_color */
  --section-dark-bg: var(--theme-tertiary-bg);             /* #222222 → tertiary_background_color */
}

3. 段階的CSS変数導入計画

3.1 Phase 1: 低リスク基本色(即座に適用可能)

対象セレクター(特異性: 0,0,1,0 〜 0,0,1,1)

/* 基本要素の色変更 */
body {
  color: var(--legacy-primary-text, #222222);
  background-color: var(--theme-primary-bg, #f5f5f5);
  font-family: var(--theme-primary-font);
}

.container {
  color: var(--legacy-primary-text, #333);
  font-family: var(--theme-primary-font);
}

/* 単純クラスセレクター */
.global-strategy-title,
.special-offer-title,
.pricing-title,
.success-stories-title,
.use-cases-title,
.awards-main-title,
.staff-title,
.store-title {
  color: var(--legacy-primary-text, #222222);
}

3.2 Phase 2: 中リスク複合セレクター(テスト後適用)

対象セレクター(特異性: 0,0,2,0 〜 0,0,2,1)

/* カード要素の背景とボーダー */
.strategy-card,
.innovation__item,
.pricing-card,
.award-item,
.review-card,
.use-case-item,
.faq-item,
.news-item {
  background: var(--theme-primary-bg, white);
  border: 1px solid var(--legacy-border, #e9ecef);
}

/* アクセント色要素 */
.simulation-button,
.special-offer-button,
.news-more-button,
.aiPower__benefitIcon,
.comparison-icon,
.staff-avatar,
.review-avatar {
  background: var(--legacy-accent, #5a6c7d);
}

3.3 Phase 3: 高リスク nth-of-type セレクター(最終段階)

対象セレクター(特異性: 0,0,2,0 最高優先度)

/* セクション背景色の変数化 - 最も慎重に */
.section-base:nth-of-type(3n+1) {
  background: var(--section-white-bg, white) !important;
  color: var(--theme-primary-text, #222222) !important;
}

.section-base:nth-of-type(3n+2) {
  background: var(--section-gray-bg, #f8f9fa) !important;
  color: var(--theme-primary-text, #222222) !important;
}

.section-base:nth-of-type(3n) {
  background: var(--section-dark-bg, #222222) !important;
  color: var(--theme-inverse-text, white) !important;
}

4. CSS生成戦略

4.1 ベースCSS + テーマ変数の分離アーキテクチャ

interface CSSGenerationStrategy {
  baseCSS: string;      // 構造・レイアウト(1200行程度、静的)
  themeCSS: string;     // テーマ変数定義(100行程度、動的)
  totalCSS: string;     // baseCSS + themeCSS
}

4.2 動的CSS生成の実装

class ThemeCustomizer {
  generateThemeCSS(theme: ThemeExtractionResult): string {
    return `
:root {
  /* テーマ抽出結果からの動的変数生成 */
  --extracted-primary-color: ${theme.colors.primary_color};
  --extracted-secondary-color: ${theme.colors.secondary_color};
  --extracted-accent-color: ${theme.colors.accent_color};

  --extracted-success-semantic-color: ${theme.colors.success_semantic_color};
  --extracted-warning-semantic-color: ${theme.colors.warning_semantic_color};
  --extracted-error-semantic-color: ${theme.colors.error_semantic_color};
  --extracted-info-semantic-color: ${theme.colors.info_semantic_color};

  --extracted-primary-background-color: ${theme.colors.primary_background_color};
  --extracted-secondary-background-color: ${theme.colors.secondary_background_color};
  --extracted-tertiary-background-color: ${theme.colors.tertiary_background_color};
  --extracted-overlay-background-color: ${theme.colors.overlay_background_color};

  --extracted-primary-text-color: ${theme.colors.primary_text_color};
  --extracted-secondary-text-color: ${theme.colors.secondary_text_color};
  --extracted-disabled-text-color: ${theme.colors.disabled_text_color};
  --extracted-inverse-text-color: ${theme.colors.inverse_text_color};

  /* フォントファミリーの動的設定(将来拡張) */
  --extracted-primary-font: var(--theme-primary-font);
}`;
  }
}

5. 競合回避戦略

5.1 特異性優先順位の設計

/* レベル1: 基本変数定義(最低特異性) */
:root { /* 特異性: 0,0,1,0 */ }

/* レベル2: フォールバック付き基本要素(低特異性) */
body, .container { /* 特異性: 0,0,1,1 */ }

/* レベル3: 単純クラス要素(中特異性) */
.strategy-card { /* 特異性: 0,0,1,0 */ }

/* レベル4: 複合クラス要素(高特異性) */
.section-base .strategy-card { /* 特異性: 0,0,2,0 */ }

/* レベル5: nth-of-type + !important(最高特異性) */
.section-base:nth-of-type(3n+1) { /* 特異性: 0,0,2,0 + !important */ }

5.2 段階的!important戦略

/* Phase 1: !important 不使用 */
.basic-element {
  color: var(--theme-primary-text, #222222); /* フォールバック値で安全性確保 */
}

/* Phase 2: 選択的!important使用 */
.complex-element {
  color: var(--theme-primary-text, #222222) !important; /* 既存ルールをオーバーライド */
}

/* Phase 3: 必須!important使用 */
.section-base:nth-of-type(3n+1) {
  background: var(--section-white-bg, white) !important; /* 最高特異性に対抗 */
}

6. パフォーマンス最適化設計

6.1 キャッシュ戦略

interface ThemeCacheStrategy {
  // キャッシュキーの生成
  generateCacheKey(theme: ThemeExtractionResult): string;

  // CSS生成結果のキャッシュ
  cacheThemeCSS(key: string, css: string): void;

  // キャッシュからの取得
  getCachedThemeCSS(key: string): string | null;
}

6.2 差分生成最適化

interface DifferentialCSS {
  baseCSS: string;           // 一度生成、永続キャッシュ
  lastGeneratedTheme: string; // 前回のテーマCSS

  generateCSS(theme: ThemeExtractionResult): {
    fullCSS: string;      // ベース + テーマの完全版
    themeOnly: string;    // テーマ変数のみ(差分更新用)
  };
}

7. ブラウザ互換性対応

7.1 CSS変数未対応ブラウザへのフォールバック

/* 従来ブラウザ対応 */
.element {
  color: #222222;                           /* フォールバック値 */
  color: var(--theme-primary-text, #222222); /* CSS変数対応ブラウザ */
}

7.2 段階的拡張(Progressive Enhancement)

/* 基本サポート: すべてのブラウザで動作 */
.base-support {
  color: #222222;
  background: white;
}

/* 拡張サポート: CSS変数対応ブラウザのみ */
@supports (color: var(--test)) {
  .base-support {
    color: var(--theme-primary-text);
    background: var(--theme-primary-bg);
  }
}

8. テスト戦略

8.1 段階別テスト計画

interface TestStrategy {
  phase1Tests: {
    basicColorApplication: boolean;
    fontFamilyApplication: boolean;
    fallbackValueVerification: boolean;
  };

  phase2Tests: {
    cardElementStyling: boolean;
    buttonColorConsistency: boolean;
    borderColorUniformity: boolean;
  };

  phase3Tests: {
    sectionBackgroundColors: boolean;
    nthOfTypePatternIntegrity: boolean;
    textColorContrast: boolean;
  };
}

8.2 ビジュアル回帰テスト

interface VisualRegressionTest {
  // テーマ適用前後の比較
  compareBeforeAfter(originalHTML: string, themedHTML: string): boolean;

  // 異なるテーマ間の一貫性確認
  compareThemeConsistency(themes: ThemeExtractionResult[]): boolean;

  // ブラウザ間の表示確認
  crossBrowserCompatibility(): boolean;
}

9. エラーハンドリング設計

9.1 CSS変数適用失敗時の対応

/* 必須フォールバック値の設定 */
:root {
  --theme-primary-text: var(--extracted-primary-text-color, #222222);
  --theme-primary-bg: var(--extracted-primary-background-color, white);
  /* すべての変数に安全なデフォルト値を設定 */
}

9.2 色指定の妥当性検証

interface ColorValidation {
  isValidHexColor(color: string): boolean;
  ensureContrastRatio(foreground: string, background: string): boolean;
  sanitizeColorValue(color: string): string;
}

10. 実装ロードマップ

10.1 Phase 1.1 完了項目 ✅

  • CSS構造分析完了
  • 変数マッピング設計完了
  • 後方互換性戦略策定完了

10.2 Phase 1.2 次期実装項目

  1. ThemeCustomizerクラス実装

    • CSS変数生成ロジック
    • キャッシュ機能
    • バリデーション機能
  2. ベースCSS分離実装

    • 構造CSS抽出
    • 変数化CSS作成
    • 統合テスト
  3. ContentsHtmlService拡張

    • テーマパラメータ追加
    • 後方互換性確保
    • エラーハンドリング

この設計により、安全かつ効率的なテーマカスタマイズ機能の実装が可能になります。