導入
WebサイトでPinterestのような「高さの異なる画像をタイル状に敷き詰めるレイアウト(Masonryレイアウト)」を実装する場合、一般的にはクライアントサイドのJavaScriptライブラリを利用します。しかし、SEOを重視する場合や、JavaScriptの実行コストを抑えたい環境では、PHPによるサーバーサイドでの事前計算が有効な選択肢となります。今回は、PHPを使って画像の高さ合計を算出し、各カラムのバランスを保ちながらタイル状に配置するロジックを解説します。
基礎知識
この実装の核となるアルゴリズムは「最小値選択」です。画像を配置する際、現在存在する各カラムの「合計の高さ」を比較し、最も高さが低いカラムを特定してそこに画像を追加します。これを繰り返すことで、各カラムの総高さを極力均等に近づけることができます。使用する関数は、ファイル一覧を取得する「scandir」と、画像情報を取得する「getimagesize」が重要です。
実装/解決策
実装のポイントは、カラムごとの高さの合計を保持する配列を用意し、ループごとに「asort」関数でソートして、常に最も高さが低いインデックス(キー)を抽出することです。これにより、画像が特定のカラムに偏るのを防ぎます。
サンプルプログラム
/
function renderGallery($files, $columnCount, $imgWidth) {
// 各カラムの合計高さを保持する配列(初期値0)
$heightTotals = array_fill(0, $columnCount, 0);
// 各カラムに振り分けられた画像リスト
$columns = array_fill(0, $columnCount, []);
foreach ($files as $file) {
// 現在の高さ合計が最小のカラムを特定
asort($heightTotals);
$targetIndex = key($heightTotals);
// 画像の実際の高さを取得
$size = getimagesize($file);
$height = $size[1] ?? 0;
// 指定したカラムに画像を追加し、高さを加算
$columns[$targetIndex][] = $file;
$heightTotals[$targetIndex] += $height;
}
// HTML出力
foreach ($columns as $columnItems) {
echo “
foreach ($columnItems as $item) {
echo “
}
echo “
\n”;
}
}
// 実行例
$dir = “images/”;
$files = glob($dir . “.{jpg,png,gif}”, GLOB_BRACE); // 画像のみ取得
?>
応用・注意点
注意点1:キャッシュ戦略
画像が多い場合、毎回「getimagesize」を実行するとサーバー負荷が高まります。実務では、画像サイズをDBに保持しておくか、計算結果をキャッシュ(Redisやファイルキャッシュ)しておくことが必須です。
注意点2:レスポンシブ対応
本手法はPHPでHTMLを生成するため、ブラウザの幅変更に合わせて再配置するような「リキッドレイアウト」には不向きです。ウィンドウサイズに応じてカラム数を動的に変えたい場合は、CSSの「column-count」プロパティを使用するか、素直にJavaScriptライブラリを検討してください。
注意点3:画像読み込みの順序
このロジックは「ファイル名の順序」で配置されます。特定の並び順が必要な場合は、事前に配列をソートしておくことを忘れないようにしましょう。