はじめに

少し前、クライアントからのリクエストがありました:データをレスポンシブなグリッドで表示することです。

問題は? カラムの数がダイナミックで、データセットによって変わるということです。その上、いくつかのカラムには非常に長いテキストが含まれていて、私が試したどのレイアウトも崩れてしまいました。そして、最も厄介なのは、事前に正確なカラムを知ることができず、ただその(テキスト、数値、メール、日付、日時)だけを知っていたことです。

いくつかの既存のグリッドやテーブルライブラリを試しましたが、どれも重すぎたり、堅苦しかったり、すべてのカラムを明示的に宣言する必要がありました。どれもこのダイナミックなカラムと長いテキストの組み合わせをうまく処理できませんでした。

そこで、自分自身のソリューションを作ることに決めました。こうして、AutoFitGridが誕生しました。

問題

ダイナミックデータは予測不可能です。レイアウトをハードコーディングすることはできず、どこにでも短いテキストがあるとは限りません — 時には複数の文からなる説明が必要です。

それを普通のHTMLテーブルに入れると:

  • カラムがオーバーフローし、横スクロールを強いられます。
  • 数値のような小さな値がスペースを無駄にします。

まさにこれが私のクライアントのユースケースでした。

解決策:AutoFitGrid

AutoFitGridは、次の2つのことを見てグリッドを構築します:

  1. 各カラムの宣言された型(テキスト、数値、メール、日付、日時)。
  2. セル内の実際の値(短い内容と長い内容)。

そこから、自動的に幅を計算し、整列を適用し、コンテンツが折り返すようにしてグリッドがレスポンシブな状態を保ちます。幅を設定したり、カラムの数を事前に知ったりする必要はありません — ライブラリがそれを処理します。

長いテキストの処理方法(難しい部分)

この問題の最も難しい部分は、カラムの数がダイナミックで未知の状態で長いテキストをグリッドに収める方法を見つけることでした。

私はそれを、各カラムを長方形として扱うことで解決しました。課題は、テキストがレイアウトを崩さずにきれいに流れるための適切な幅と高さの比率を見つけることです。

ここにロジックがあります:

  1. テキスト内の単語をカウントする
  2. テキストを短い中くらい、または長いとして分類する。
  3. カテゴリーに応じてターゲット比率を選択する(短いテキスト = より狭い長方形、長いテキスト = より広い長方形)。
  4. テキストがきれいに折り返すように適切な幅と高さを計算する。

このようにして、名前のような短い値がスペースを無駄にせず、長い説明が読みやすく保たれます。

HTML/JavaScriptでの初期化

HTMLでグリッドを宣言する方法は以下の通りです。幅は指定されていないことに注意してください — 型だけです。

HTML

<div class="grid-container">
  <div class="grid-header" data-type="text">タスクの説明</div>
  <div class="grid-header" data-type="text">担当者</div>
  <div class="grid-header" data-type="email">メール</div>
  <div class="grid-header" data-type="datetime">開始日</div>
  <div class="grid-header" data-type="datetime">期限</div>
  <div class="grid-header" data-type="number">優先度</div>
  <div class="grid-header" data-type="number">推定時間</div>

  <div class="grid-item">
    グリッドレイアウトがどのように調整され、テキストが複数行にわたって動的に折り返されるかをテストするために、非常に長い説明を実装します。
  </div>
  <div class="grid-item">ジェーン・ドウ</div>
  <div class="grid-item">jane.doe@example.com</div>
  <div class="grid-item">2024-01-15 08:30:00</div>
  <div class="grid-item">2024-07-15 17:00:00</div>
  <div class="grid-item">1</div>
  <div class="grid-item">100</div>
</div>

JavaScript

マークアップが準備できたら、1回の初期化呼び出しでグリッドにインテリジェンスを与えます。

new AutoFitGrid({
  container: document.querySelector('.grid-container'),
  defaultMinWidth: 50,
  defaultMaxWidth: Infinity,
  adjustmentThreshold: 200,
  headerSelector: '.grid-header',
  columnSelector: '.grid-item',
  showDebug: false
});

showDebug: trueをオンにすると、AutoFitGridがカラムをどのように測定し、フィットさせるかのログが表示されます。

Reactでの使用

import React, { useEffect, useRef } from 'react';
import AutoFitGrid from 'auto-fit-grid';

function MyGrid() {
  const ref = useRef(null);

  useEffect(() => {
    if (ref.current) {
      new AutoFitGrid({
        container: ref.current,
        headerSelector: '.grid-header',
        columnSelector: '.grid-item'
      });
    }
  }, []);

  return (
    <div className="grid-container" ref={ref}>
      <div className="grid-header" data-type="text">名前</div>
      <div className="grid-header" data-type="email">メール</div>
      <div className="grid-header" data-type="number">スコア</div>

      <div className="grid-item">アリス・ワンダーランド</div>
      <div className="grid-item">alice@example.com</div>
      <div className="grid-item">88</div>

      <div className="grid-item">ボブ・ボブソン</div>
      <div className="grid-item">bob@example.com</div>
      <div className="grid-item">95</div>
    </div>
  );
}

インストールと試してみる

AutoFitGridはnpmからインストールできます:

npm install auto-fit-grid

または、ライブ例やドキュメントを探索してください: