条件付き書式(行の色分け)

にメンテナンス済み

Excel や Google スプレッドシートでは「条件付き書式」で特定の条件に合致するセルの色を変えることができますが、kintone の一覧画面にはこの機能が標準では用意されていません。

しかし、JavaScript カスタマイズを使えば、ステータスや期限、数値などの条件に応じて行の背景色を動的に変更し、一覧画面をより見やすくカスタマイズできます。

この記事では、一覧画面で行の色を条件に応じて変更する条件付き書式の実装方法を、複数のパターンに分けて解説します。

基本: ステータスに応じた行の色分け

ドロップダウンの値で行の背景色を変更

一覧表示時に各レコードのフィールド値を判定し、行の背景色を動的に変更する基本パターンです。

conditional-row-color.js
(() => {
  'use strict';

  // ステータスごとの背景色定義
  const STATUS_COLORS = {
    '未対応': '#fff3cd',    // 黄色(注意)
    '対応中': '#d1ecf1',    // 水色(作業中)
    '完了': '#d4edda',      // 緑色(完了)
    '保留': '#e2e3e5',      // グレー(保留)
    '却下': '#f8d7da',      // 赤色(却下)
  };

  const events = [
    'app.record.index.show',
    'mobile.app.record.index.show',
  ];

  kintone.events.on(events, (event) => {
    const records = event.records;

    // 一覧のテーブル行要素を取得
    const rows = document.querySelectorAll('.recordlist-row-gaia');

    records.forEach((record, index) => {
      const status = record['対応ステータス'].value;
      const color = STATUS_COLORS[status];

      if (color && rows[index]) {
        rows[index].style.backgroundColor = color;
      }
    });

    return event;
  });
})();
DOM セレクタの注意点

kintone の DOM 構造(クラス名 .recordlist-row-gaia など)は kintone のアップデートによって変更される可能性があります。フロントエンド刷新の影響を受ける場合もあるため、定期的に動作確認を行うことを推奨します。

期限に応じた色分け

期限切れ・期限間近のレコードを強調

日付フィールドを使って、期限の残り日数に応じた色分けを行うパターンです。

deadline-color.js
(() => {
  'use strict';

  /**
   * 期限までの残り日数を計算する
   * @param { string } dateString - YYYY-MM-DD 形式の日付文字列
   * @returns { number } 残り日数(負の値は期限超過)
   */
  const getDaysUntil = (dateString) => {
    if (!dateString) return Infinity;
    const deadline = new Date(dateString);
    const today = new Date();
    today.setHours(0, 0, 0, 0);
    deadline.setHours(0, 0, 0, 0);
    return Math.ceil((deadline - today) / (1000 * 60 * 60 * 24));
  };

  const events = ['app.record.index.show'];

  kintone.events.on(events, (event) => {
    const records = event.records;
    const rows = document.querySelectorAll('.recordlist-row-gaia');

    records.forEach((record, index) => {
      const days = getDaysUntil(record['期限日'].value);
      const status = record['対応ステータス'].value;

      // 完了済みのレコードは色付けしない
      if (status === '完了') return;

      if (!rows[index]) return;

      if (days < 0) {
        // 期限超過: 赤色
        rows[index].style.backgroundColor = '#f8d7da';
        rows[index].style.fontWeight = 'bold';
      } else if (days <= 3) {
        // 3日以内: オレンジ色
        rows[index].style.backgroundColor = '#fff3cd';
      } else if (days <= 7) {
        // 7日以内: 薄い黄色
        rows[index].style.backgroundColor = '#fefce8';
      }
    });

    return event;
  });
})();
チェック

期限切れのレコードには fontWeight: 'bold' を追加することで、背景色だけでなく文字の太さでも視覚的に強調しています。複数のスタイルプロパティを組み合わせると、より効果的な視認性を実現できます。

数値の範囲に応じた色分け

売上金額のヒートマップ的な色分け

数値の大小に応じてグラデーション的に色を変えるパターンです。

numeric-color.js
(() => {
  'use strict';

  /**
   * 数値の範囲に応じた背景色を返す
   * @param { number } value - 対象の数値
   * @param { Object[] } ranges - 範囲定義の配列(min, max, color)
   * @returns { string | null } 背景色、該当なしの場合 null
   */
  const getColorByRange = (value, ranges) => {
    for (const range of ranges) {
      if (value >= range.min && value < range.max) {
        return range.color;
      }
    }
    return null;
  };

  // 金額の範囲に応じた色定義
  const AMOUNT_RANGES = [
    { min: 0, max: 100000, color: '#f8f9fa' },          // 10万未満: ほぼ白
    { min: 100000, max: 500000, color: '#d1ecf1' },     // 10万〜50万: 薄い青
    { min: 500000, max: 1000000, color: '#bee5eb' },     // 50万〜100万: 青
    { min: 1000000, max: Infinity, color: '#b8daff' },   // 100万以上: 濃い青
  ];

  const events = ['app.record.index.show'];

  kintone.events.on(events, (event) => {
    const records = event.records;
    const rows = document.querySelectorAll('.recordlist-row-gaia');

    records.forEach((record, index) => {
      const amount = Number(record['金額'].value) || 0;
      const color = getColorByRange(amount, AMOUNT_RANGES);

      if (color && rows[index]) {
        rows[index].style.backgroundColor = color;
      }
    });

    return event;
  });
})();

複数条件の組み合わせ

優先度 × ステータスのマトリクス色分け

複数のフィールドの値を組み合わせて色を決定するパターンです。

multi-condition-color.js
(() => {
  'use strict';

  /**
   * 複数条件に基づいて背景色を決定する
   * @param { Object } record - kintone のレコードオブジェクト
   * @returns { Object | null } スタイル情報 { backgroundColor, color }
   */
  const getRowStyle = (record) => {
    const priority = record['優先度'].value;
    const status = record['対応ステータス'].value;

    // 完了済みは薄いグレー
    if (status === '完了') {
      return { backgroundColor: '#f8f9fa', color: '#6c757d' };
    }

    // 優先度「高」かつ未対応は赤色強調
    if (priority === '高' && status === '未対応') {
      return { backgroundColor: '#f8d7da', color: '#721c24' };
    }

    // 優先度「高」はオレンジ
    if (priority === '高') {
      return { backgroundColor: '#fff3cd', color: '#856404' };
    }

    // 優先度「中」
    if (priority === '中') {
      return { backgroundColor: '#d1ecf1', color: '#0c5460' };
    }

    // 優先度「低」はデフォルト
    return null;
  };

  const events = ['app.record.index.show'];

  kintone.events.on(events, (event) => {
    const records = event.records;
    const rows = document.querySelectorAll('.recordlist-row-gaia');

    records.forEach((record, index) => {
      const style = getRowStyle(record);

      if (style && rows[index]) {
        rows[index].style.backgroundColor = style.backgroundColor;

        // テキストの色も変更
        const cells = rows[index].querySelectorAll('td');
        cells.forEach((cell) => {
          cell.style.color = style.color;
        });
      }
    });

    return event;
  });
})();

CSS ファイルとの組み合わせ

クラスベースのスタイル適用

JavaScript で直接スタイルを設定する代わりに、CSS クラスを付与してスタイルを管理する方法です。スタイルの変更が容易で、メンテナンス性が向上します。

conditional-format.css
/* kintone 一覧画面の条件付き書式 */
.row-status-overdue {
  background-color: #f8d7da !important;
}

.row-status-overdue td {
  color: #721c24 !important;
  font-weight: bold;
}

.row-status-warning {
  background-color: #fff3cd !important;
}

.row-status-completed {
  background-color: #d4edda !important;
}

.row-status-completed td {
  color: #6c757d !important;
}

.row-priority-high {
  border-left: 4px solid #dc3545 !important;
}

.row-priority-medium {
  border-left: 4px solid #ffc107 !important;
}

.row-priority-low {
  border-left: 4px solid #28a745 !important;
}
conditional-format.js
(() => {
  'use strict';

  const events = ['app.record.index.show'];

  kintone.events.on(events, (event) => {
    const records = event.records;
    const rows = document.querySelectorAll('.recordlist-row-gaia');

    records.forEach((record, index) => {
      if (!rows[index]) return;

      const row = rows[index];
      const status = record['対応ステータス'].value;
      const priority = record['優先度'].value;
      const deadline = record['期限日'].value;

      // ステータスに応じたクラスを付与
      if (status === '完了') {
        row.classList.add('row-status-completed');
      } else if (deadline) {
        const today = new Date();
        today.setHours(0, 0, 0, 0);
        const deadlineDate = new Date(deadline);
        if (deadlineDate < today) {
          row.classList.add('row-status-overdue');
        } else if ((deadlineDate - today) / (1000 * 60 * 60 * 24) <= 3) {
          row.classList.add('row-status-warning');
        }
      }

      // 優先度に応じた左ボーダーを付与
      if (priority === '高') {
        row.classList.add('row-priority-high');
      } else if (priority === '中') {
        row.classList.add('row-priority-medium');
      } else if (priority === '低') {
        row.classList.add('row-priority-low');
      }
    });

    return event;
  });
})();
チェック

CSS クラスベースのアプローチでは、JavaScript はクラスの付与のみを担当し、スタイルの詳細は CSS ファイルで管理します。デザインの微調整時に JavaScript を修正する必要がなく、CSS ファイルだけで対応できます。

!important の使用について

kintone の標準スタイルを上書きするために !important を使用しています。可能であれば、より詳細度の高いセレクタ(例: .recordlist-row-gaia.row-status-overdue)を使って !important の使用を最小限にすることを推奨します。

凡例の表示

一覧画面に色の意味を示す凡例(レジェンド)を表示し、ユーザーが色の意味を理解できるようにするパターンです。

color-legend.js
(() => {
  'use strict';

  const LEGEND_ITEMS = [
    { label: '期限超過', color: '#f8d7da' },
    { label: '期限間近(3日以内)', color: '#fff3cd' },
    { label: '完了', color: '#d4edda' },
    { label: '通常', color: '#ffffff' },
  ];

  const events = ['app.record.index.show'];

  kintone.events.on(events, (event) => {
    const headerSpace = kintone.app.getHeaderMenuSpaceElement();
    if (!headerSpace || document.getElementById('color-legend')) return event;

    const legend = document.createElement('div');
    legend.id = 'color-legend';
    legend.style.cssText = `
      display: flex; gap: 16px; align-items: center;
      padding: 8px 12px; font-size: 12px;
    `;

    LEGEND_ITEMS.forEach((item) => {
      const chip = document.createElement('span');
      chip.style.cssText = `
        display: inline-flex; align-items: center; gap: 4px;
      `;

      const dot = document.createElement('span');
      dot.style.cssText = `
        display: inline-block; width: 12px; height: 12px;
        border-radius: 2px; background: ${item.color};
        border: 1px solid #ddd;
      `;

      const label = document.createElement('span');
      label.textContent = item.label;
      label.style.color = '#666';

      chip.appendChild(dot);
      chip.appendChild(label);
      legend.appendChild(chip);
    });

    headerSpace.appendChild(legend);
    return event;
  });
})();

まとめ

  • 一覧画面の行色分けは app.record.index.show イベントと DOM 操作で実現できる
  • ステータス・期限日・数値・優先度など、さまざまな条件で色を変更できる
  • 複数条件を組み合わせる場合は、専用の判定関数を定義すると見通しが良くなる
  • CSS クラスベースのアプローチは JavaScript と CSS の責務を分離でき、メンテナンス性が高い
  • kintone の DOM クラス名(.recordlist-row-gaia など)はアップデートで変更される可能性がある
  • 色の意味をユーザーに伝えるために、凡例(レジェンド)の表示も併せて実装するとよい

関連記事

サンプル集 - app.record.index.show
kintoneのJavaScriptカスタマイズについての情報は多く存在しますが、「じゃあ、結局やりたいことを実現させるためにはどうすればいいの?」という問題を簡単に解決することが難しいように感じました。今回はいくつかのサンプルコードを使っ
CSSカスタマイズの基本
kintone の CSS カスタマイズの基本を解説します。フィールドやヘッダーの見た目を変更する方法から、条件に応じた行の背景色変更、フィールドの非表示、レスポンシブ対応まで幅広く紹介します。
フィールドの表示/非表示
kintone JavaScript カスタマイズで、フィールドの表示・非表示を動的に切り替える方法を解説します。setFieldShown を使った基本的な使い方から、条件に応じた制御、グループフィールドやテーブルとの組み合わせまで紹介し

練習問題

kintone の一覧画面で行の背景色を変更する際に使用するイベントはどれですか?

CSS クラスベースで条件付き書式を実装するメリットとして最も適切なものはどれですか?

#kintone #JavaScript #CSS