CSS-only Masonry風グリッド
column-count と break-inside: avoid だけで、高さの異なるタイルを石積み状に並べる Masonry 風ギャラリー。JSのライブラリ不要。
ライブデモ
使用例(お題: アイドルグループ Sakura)
この技法を「アイドルグループ Sakura」というテーマのダミーサイトで実際に使った例です。
HTML
<!-- Sakura フォトギャラリー:column-count の Masonry風で高さ違いの写真を石積み -->
<section class="sk-gal">
<header class="sk-gal__head">
<h2 class="sk-gal__title">🌸 Sakura フォトギャラリー</h2>
<span class="sk-gal__sub">5th LIVE「春一会」オフショット</span>
</header>
<div class="sk-gal__masonry">
<figure class="sk-card sk-card--tall">
<div class="sk-card__img" style="background-image:url('https://picsum.photos/300/420?random=51')"></div>
<figcaption>みはる|衣装あわせ</figcaption>
</figure>
<figure class="sk-card">
<div class="sk-card__img" style="background-image:url('https://picsum.photos/300/220?random=52')"></div>
<figcaption>ことね|リハ前</figcaption>
</figure>
<figure class="sk-card sk-card--mid">
<div class="sk-card__img" style="background-image:url('https://picsum.photos/300/300?random=53')"></div>
<figcaption>あおい|楽屋にて</figcaption>
</figure>
<figure class="sk-card">
<div class="sk-card__img" style="background-image:url('https://picsum.photos/300/240?random=54')"></div>
<figcaption>ゆな|笑顔ショット</figcaption>
</figure>
<figure class="sk-card sk-card--tall">
<div class="sk-card__img" style="background-image:url('https://picsum.photos/300/400?random=55')"></div>
<figcaption>みはる&ことね</figcaption>
</figure>
<figure class="sk-card sk-card--mid">
<div class="sk-card__img" style="background-image:url('https://picsum.photos/300/300?random=56')"></div>
<figcaption>5人集合</figcaption>
</figure>
<figure class="sk-card">
<div class="sk-card__img" style="background-image:url('https://picsum.photos/300/210?random=57')"></div>
<figcaption>ステージ袖から</figcaption>
</figure>
<figure class="sk-card sk-card--mid">
<div class="sk-card__img" style="background-image:url('https://picsum.photos/300/280?random=58')"></div>
<figcaption>アンコール</figcaption>
</figure>
</div>
</section>
CSS
/* Sakura:column-count と break-inside:avoid だけで Masonry風フォトギャラリー */
:root {
--pink: #ffd1e0;
--pink-deep: #ff8fb3;
--gray: #fbf7f9;
}
* { box-sizing: border-box; }
body {
margin: 0;
height: 400px;
font-family: "Hiragino Kaku Gothic ProN", "Segoe UI", system-ui, sans-serif;
background: linear-gradient(165deg, #fff5f9, var(--gray));
color: #6a2740;
overflow: hidden;
}
.sk-gal {
height: 400px;
display: flex;
flex-direction: column;
padding: 14px 16px 0;
}
.sk-gal__head { margin-bottom: 10px; }
.sk-gal__title { margin: 0; font-size: 16px; font-weight: 800; }
.sk-gal__sub { font-size: 11px; color: #c06088; }
/* Masonry風:列数を指定し、各タイルの段割れを禁止 */
.sk-gal__masonry {
flex: 1;
min-height: 0;
overflow: auto;
column-count: 4;
column-gap: 10px;
padding-bottom: 14px;
}
@media (max-width: 520px) { .sk-gal__masonry { column-count: 2; } }
.sk-card {
break-inside: avoid;
margin: 0 0 10px;
border-radius: 12px;
overflow: hidden;
background: #fff;
border: 1px solid #ffe0ea;
box-shadow: 0 6px 16px rgba(214, 94, 140, 0.14);
transition: transform 0.2s ease, box-shadow 0.2s ease;
cursor: pointer;
}
.sk-card:hover {
transform: translateY(-3px);
box-shadow: 0 12px 24px rgba(214, 94, 140, 0.24);
}
/* 高さの異なるタイル(石積みのリズムを作る) */
.sk-card__img { height: 110px; background-size: cover; background-position: center; }
.sk-card--mid .sk-card__img { height: 150px; }
.sk-card--tall .sk-card__img { height: 210px; }
.sk-card figcaption {
padding: 7px 10px;
font-size: 10.5px;
color: #8a4a64;
font-weight: 600;
}
@media (prefers-reduced-motion: reduce) {
.sk-card { transition: none; }
}
JavaScript
// 写真カードをクリックで「いいね♡」をキャプションにトグル(ファン操作の演出)
const cards = document.querySelectorAll(".sk-gal__masonry .sk-card");
cards.forEach((card) => {
const cap = card.querySelector("figcaption");
if (!cap) return;
const base = cap.textContent;
card.addEventListener("click", () => {
const liked = card.dataset.liked === "1";
card.dataset.liked = liked ? "0" : "1";
cap.textContent = liked ? base : base + " ♡";
});
});
コード
HTML
<!-- CSS-only Masonry風グリッド:column-count で高さの違うカードを石積み配置 -->
<div class="mason">
<h1 class="mason__head">Masonry <span>Wall</span></h1>
<div class="mason__grid" id="masonGrid">
<!-- カードはJSで生成(高さの異なるタイル) -->
</div>
</div>
CSS
/* 全体:ダークグレー地にネオン系タイル */
* { box-sizing: border-box; margin: 0; padding: 0; }
body {
font-family: "Hiragino Sans", system-ui, sans-serif;
background: radial-gradient(120% 120% at 50% -10%, #2a2540, #141221 70%);
color: #f4f3ff; min-height: 100vh; padding: 18px 16px;
}
.mason__head {
text-align: center; font-size: clamp(18px, 3.4vw, 26px);
font-weight: 800; letter-spacing: .04em; margin-bottom: 14px;
}
.mason__head span {
background: linear-gradient(90deg, #f0abfc, #818cf8);
-webkit-background-clip: text; background-clip: text; color: transparent;
}
/* CSS Multicolumn で Masonry を実現:column 内で要素が積み上がる */
.mason__grid {
column-count: 4;
column-gap: 12px;
width: min(900px, 100%);
margin: 0 auto;
}
@media (max-width: 720px) { .mason__grid { column-count: 3; } }
@media (max-width: 480px) { .mason__grid { column-count: 2; } }
/* タイル:break-inside で途中分割を防ぐ */
.tile {
break-inside: avoid;
margin: 0 0 12px;
border-radius: 12px;
padding: 14px;
color: #15121f;
font-weight: 700;
position: relative; overflow: hidden;
box-shadow: 0 8px 22px -12px rgba(0,0,0,.6);
animation: pop .5s ease backwards;
}
.tile small { display: block; font-size: 10px; opacity: .6; letter-spacing: .14em; }
.tile b { font-size: 15px; }
.tile::after { /* 光沢 */
content: ""; position: absolute; inset: 0;
background: linear-gradient(135deg, rgba(255,255,255,.35), transparent 50%);
pointer-events: none;
}
@keyframes pop {
from { opacity: 0; transform: translateY(10px) scale(.96); }
to { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
.tile { animation: none; }
}
JavaScript
// 高さ・色が異なるタイルを生成して Masonry 風の見た目を作る
(() => {
const grid = document.getElementById('masonGrid');
if (!grid) return;
// パステル系グラデのペア
const palettes = [
['#a7f3d0', '#6ee7b7'], ['#fbcfe8', '#f9a8d4'],
['#bfdbfe', '#93c5fd'], ['#fde68a', '#fcd34d'],
['#ddd6fe', '#c4b5fd'], ['#fecaca', '#fca5a5'],
['#99f6e4', '#5eead4'], ['#fed7aa', '#fdba74'],
];
const labels = ['UI', 'TYPE', 'COLOR', 'MOTION', 'GRID', 'ICON', '3D', 'PHOTO',
'BRAND', 'WEB', 'CODE', 'ART'];
const frag = document.createDocumentFragment();
for (let i = 0; i < 14; i++) {
const tile = document.createElement('div');
tile.className = 'tile';
const [c1, c2] = palettes[i % palettes.length];
// ランダムな高さで石積み感を出す
const h = 70 + Math.floor(Math.random() * 90);
tile.style.minHeight = h + 'px';
tile.style.background = `linear-gradient(160deg, ${c1}, ${c2})`;
tile.style.animationDelay = (i * 0.04) + 's';
tile.innerHTML =
`<small>#${String(i + 1).padStart(2, '0')}</small>` +
`<b>${labels[i % labels.length]}</b>`;
frag.appendChild(tile);
}
grid.appendChild(frag);
})();
🤖 AIエージェント用プロンプト
このままコピーしてAIに貼り付け「追加する場所」だけ書き換えればOK
あなたは熟練のフロントエンドエンジニアです。私のWebサイトに「CSS-only Masonry風グリッド」の効果を追加してください。
# 追加してほしい効果
CSS-only Masonry風グリッド(レイアウト & グリッド)
column-count と break-inside: avoid だけで、高さの異なるタイルを石積み状に並べる Masonry 風ギャラリー。JSのライブラリ不要。
# 追加する場所
👉【ここに対象箇所を記入:例「トップのヒーローセクション」「お問い合わせボタン」「記事カードの一覧」など】
# 参考実装(この見た目・挙動を再現してください)
【HTML】
<!-- CSS-only Masonry風グリッド:column-count で高さの違うカードを石積み配置 -->
<div class="mason">
<h1 class="mason__head">Masonry <span>Wall</span></h1>
<div class="mason__grid" id="masonGrid">
<!-- カードはJSで生成(高さの異なるタイル) -->
</div>
</div>
【CSS】
/* 全体:ダークグレー地にネオン系タイル */
* { box-sizing: border-box; margin: 0; padding: 0; }
body {
font-family: "Hiragino Sans", system-ui, sans-serif;
background: radial-gradient(120% 120% at 50% -10%, #2a2540, #141221 70%);
color: #f4f3ff; min-height: 100vh; padding: 18px 16px;
}
.mason__head {
text-align: center; font-size: clamp(18px, 3.4vw, 26px);
font-weight: 800; letter-spacing: .04em; margin-bottom: 14px;
}
.mason__head span {
background: linear-gradient(90deg, #f0abfc, #818cf8);
-webkit-background-clip: text; background-clip: text; color: transparent;
}
/* CSS Multicolumn で Masonry を実現:column 内で要素が積み上がる */
.mason__grid {
column-count: 4;
column-gap: 12px;
width: min(900px, 100%);
margin: 0 auto;
}
@media (max-width: 720px) { .mason__grid { column-count: 3; } }
@media (max-width: 480px) { .mason__grid { column-count: 2; } }
/* タイル:break-inside で途中分割を防ぐ */
.tile {
break-inside: avoid;
margin: 0 0 12px;
border-radius: 12px;
padding: 14px;
color: #15121f;
font-weight: 700;
position: relative; overflow: hidden;
box-shadow: 0 8px 22px -12px rgba(0,0,0,.6);
animation: pop .5s ease backwards;
}
.tile small { display: block; font-size: 10px; opacity: .6; letter-spacing: .14em; }
.tile b { font-size: 15px; }
.tile::after { /* 光沢 */
content: ""; position: absolute; inset: 0;
background: linear-gradient(135deg, rgba(255,255,255,.35), transparent 50%);
pointer-events: none;
}
@keyframes pop {
from { opacity: 0; transform: translateY(10px) scale(.96); }
to { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
.tile { animation: none; }
}
【JavaScript】
// 高さ・色が異なるタイルを生成して Masonry 風の見た目を作る
(() => {
const grid = document.getElementById('masonGrid');
if (!grid) return;
// パステル系グラデのペア
const palettes = [
['#a7f3d0', '#6ee7b7'], ['#fbcfe8', '#f9a8d4'],
['#bfdbfe', '#93c5fd'], ['#fde68a', '#fcd34d'],
['#ddd6fe', '#c4b5fd'], ['#fecaca', '#fca5a5'],
['#99f6e4', '#5eead4'], ['#fed7aa', '#fdba74'],
];
const labels = ['UI', 'TYPE', 'COLOR', 'MOTION', 'GRID', 'ICON', '3D', 'PHOTO',
'BRAND', 'WEB', 'CODE', 'ART'];
const frag = document.createDocumentFragment();
for (let i = 0; i < 14; i++) {
const tile = document.createElement('div');
tile.className = 'tile';
const [c1, c2] = palettes[i % palettes.length];
// ランダムな高さで石積み感を出す
const h = 70 + Math.floor(Math.random() * 90);
tile.style.minHeight = h + 'px';
tile.style.background = `linear-gradient(160deg, ${c1}, ${c2})`;
tile.style.animationDelay = (i * 0.04) + 's';
tile.innerHTML =
`<small>#${String(i + 1).padStart(2, '0')}</small>` +
`<b>${labels[i % labels.length]}</b>`;
frag.appendChild(tile);
}
grid.appendChild(frag);
})();
# 外部ライブラリ
なし(追加ライブラリ不要)
# 守ってほしいこと
- 既存のHTML構造・レイアウト・デザインを壊さないこと。必要に応じてクラス名・色・サイズを私のサイトに合わせて調整してよい。
- クラス名やidが既存と衝突しないよう、必要なら接頭辞で名前空間を分けること。
- レスポンシブ対応と prefers-reduced-motion への配慮を入れること。
- 私のサイトのフレームワーク(React / Vue / 素のHTML など)に合わせて実装すること。不明な場合は素のHTML/CSS/JSで提示し、組み込み手順も説明すること。
- 変更後の確認手順も簡潔に教えてください。