【Next.js】ベントグリッドの作り方を Tailwind CSS のコード付きで解説
公開日: 2026年9月12日 · 読了目安 10 分
Next.js でベントグリッド(Bento UI)を作る手順をコード付きで解説。Tailwind CSS の col-span・row-span でマスの比率を決め、スマホでは1列に戻し、大きいマスだけをゆっくり動かす方法まで扱います。
ベントグリッドは CSS Grid と大きいマス1つで作れる
Apple の発表スライドのような、大小のマスを組み合わせたレイアウトを Next.js の LP に入れたい。試しにカードを並べてみたら、ただのタイル一覧に見えた。
そんなときに読んでほしい記事です。
ベントグリッド(Bento UI)は、弁当箱のように大きさの違うマスを1つの枠に収めるレイアウトです。
CSS Grid の基本の指定だけで作れるので、専用のライブラリは要りません。
コツは、大きいマスを1つだけ決め、残りをその補足にすることです。
この記事で分かること:
Tailwind CSS の grid でベントグリッドを組むコード
4列・2列・1列と、画面幅に合わせてマスを組み替える方法
大きいマスだけをループで動かし、他は入場だけにする方法
見出しの順番・キーボード操作・表示速度で気をつけること
ベントグリッドが崩れて見える3つの理由
ベントグリッドは、うまくいくと情報量が多くても整って見えます。一方で、少し外すと「カードを詰め込んだだけ」に見えます。
崩れて見える原因は、たいてい次のどれかです。
全部のマスが同じ大きさか、大きいマスが2つ以上あって、どこを見ればよいか分からない
大きいマスに長い文章を詰めている(大きいマスは写真か数字の場所)
スマホでもデスクトップと同じスパンを使い、細いマスが縦に伸びる
加えて、全部のマスに枠線と影を付けると、画面が重くなります。マスの区切りは、余白と背景の色の差だけで十分です。
Tailwind CSS の grid でベントグリッドを組む
まず、デスクトップでのマスの配置を決めます。ここでは4列2行の枠に、次の4つのマスを置きます。
目玉のマス: 2列×2行(左半分)。写真と短い見出しを置く
数字のマス2つ: 1列×1行(右上に2つ並ぶ)
横長のマス: 2列×1行(右下)。補足の説明や小さなデモを置く
この配置を Tailwind CSS のクラスにすると、次のコードになります。
状態を持たないので、サーバーコンポーネントのまま使えます。
import Image from "next/image";
export function Bento() {
return (
<section className="mx-auto max-w-6xl px-6 py-24">
<h2 className="text-3xl font-semibold tracking-tight md:text-4xl">
チームの仕事が、ひと目で分かる
</h2>
<div className="mt-12 grid auto-rows-[minmax(180px,auto)] grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4">
<article className="relative overflow-hidden rounded-3xl bg-zinc-900 p-8 text-white sm:col-span-2 lg:row-span-2">
<Image
src="/bento/team.jpg"
alt="打ち合わせをするチーム"
fill
sizes="(min-width: 1024px) 50vw, 100vw"
className="object-cover opacity-60"
/>
<div className="relative flex h-full flex-col justify-end">
<h3 className="text-2xl font-semibold">進み具合を1画面で共有</h3>
<p className="mt-2 max-w-sm text-sm text-zinc-200">
誰が何をしているか、会議を開かずに分かります。
</p>
</div>
</article>
<article className="rounded-3xl bg-zinc-100 p-6">
<p className="text-4xl font-semibold">98%</p>
<h3 className="mt-2 text-sm text-zinc-600">翌月も使い続けるチームの割合</h3>
</article>
<article className="rounded-3xl bg-zinc-100 p-6">
<p className="text-4xl font-semibold">3分</p>
<h3 className="mt-2 text-sm text-zinc-600">導入にかかる平均時間</h3>
</article>
<article className="rounded-3xl bg-indigo-50 p-6 sm:col-span-2">
<h3 className="font-semibold">Slack と GitHub につながる</h3>
<p className="mt-2 text-sm text-zinc-600">
通知はいつものチャンネルに届き、新しいツールを開く必要がありません。
</p>
</article>
</div>
</section>
);
}ベントグリッドの行の高さを揃える
列の数(grid-cols)を決めたら、次は行の高さ(auto-rows)を決めます。
コードでは、行の高さを「最低 180 ピクセル、中身が多ければ伸びる」と指定しています。
高さを固定しないので、文章が増えてもマスからはみ出しません。
row-span-2 のマスは、2行分の高さと gap を足した大きさになります。目玉のマスを写真で埋めるなら、この高さがあると見栄えがよくなります。
マスの間の溝は 16〜24px にする
ベントグリッドは、マスの間の溝が均一であることで整って見えます。gap-4(16px)から gap-6(24px)が扱いやすい幅です。
角丸は rounded-2xl から rounded-3xl くらいにし、全部のマスで揃えます。
ベントグリッドの空いたマスを自動で詰める
マスの数や大きさを変えて穴が空いたときは、grid-flow-row-dense を付けると、後ろのマスが空きに詰められます。
ただし、見た目の順番と HTML の順番がずれるため、Tab キーでの移動順が飛びます。
まずはマスの順番を書き換えて解決し、それでも難しいときだけ使います。
スマホではベントグリッドを1列か2列に戻す
デスクトップと同じ col-span をスマホにも当てると、細いマスが縦に長く伸びて読みにくくなります。上のコードでは、ブレークポイントごとに列の数を変えています。
スマホ(sm 未満): 1列。全部のマスが縦に並ぶ
タブレット(sm 以上): 2列。目玉と横長のマスは2列をまたぐ
デスクトップ(lg 以上): 4列。目玉のマスが2行をまたぐ
スパンのクラスに sm: や lg: を付けているのは、この切り替えのためです。row-span-2 も lg: のときだけ効かせると、スマホで目玉のマスが不自然に高くなりません。
1列のときは、目玉のマスを最初に置くと、写真から読み始められます。
ベントグリッドの大きいマスだけを動かすアニメーション
ベントグリッドに動きを付けるときは、役割を分けます。大きいマスの中だけゆっくりループする背景を置き、小さいマスは入場のときに少しずつ遅れて出るだけにします。
全部のマスが同時に浮いたり揺れたりすると、グリッドの形が見えなくなります。
目玉のマスにループするグラデーションを敷く
CSS の keyframes を globals.css に1つ足し、Tailwind CSS の任意値クラスで呼び出します。12 秒かけて往復する程度の遅さにすると、背景として目にうるさくなりません。
@keyframes bento-drift {
0%,
100% {
transform: translate(0, 0) scale(1);
}
50% {
transform: translate(-6%, 4%) scale(1.1);
}
}目玉のマスに置くグラデーションの要素
目玉のマスの中、写真の代わりか写真の上に置きます。マスに overflow-hidden が付いているので、はみ出した部分は見えません。
<div
aria-hidden
className="absolute -inset-1/4 bg-[radial-gradient(circle_at_30%_30%,#6366f1,transparent_60%)] opacity-70 animate-[bento-drift_12s_ease-in-out_infinite] motion-reduce:animate-none"
/>小さいマスは入場のタイミングだけ遅らせる
Motion(旧 Framer Motion)の whileInView(画面に入ったら動かす指定)で、マスごとに 0.06 秒ずつ遅らせて出します。
マスの article をこの BentoTile に置き換え、何番目のマスか(index)を渡します。
"use client";
import { motion } from "motion/react";
import type { ReactNode } from "react";
export function BentoTile({
index,
className,
children,
}: {
index: number;
className?: string;
children: ReactNode;
}) {
return (
<motion.article
className={className}
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true, amount: 0.4 }}
transition={{ duration: 0.5, delay: index * 0.06, ease: "easeOut" }}
>
{children}
</motion.article>
);
}ベントグリッドを公開する前の確認リスト
ベントグリッドは見た目が先に立つため、次の点を見落としがちです。公開前に1つずつ確かめてください。
見出しの順番: マスの見出しは同じ階層(h3)に揃え、階層を飛ばさない
キーボード: マスにリンクがあるとき、Tab キーでの移動順が見た目の順番と大きくずれない
表示速度: 最初の画面にあるなら、目玉の写真に優先読み込み(priority)を付け、そのマスを透明から始めない
スマホ: 1列で縦に並べたとき、目玉のマスが最初に来る
動きを減らす設定: その設定の人には、ループを止めている
完成したベントグリッドをコピーして使う方法

次の要素まで揃ったベントグリッドは、grid のクラスだけでは決まりません。調整に半日かかることもあります。
マスの比率
角丸
中の文字の大きさ
目玉のマスのループ
DesignLayer は、人が組んだ React + Tailwind のモーション付きセクションを、ブラウザでライブプレビューしてからコピーできるカタログです。
閲覧はアカウントもカードも不要です。https://design-layer.com/ja/components
無料サンプル10個を無料アカウントで回数制限なくコピーでき、動画プロンプトは月1回です。Free では MCP に接続できません。カタログ全体は30日ビルドパス($19の1回払い、自動更新なし)、Lifetime Access(先着100名の$79の1回払い)、Plus(月額 $9、いつでも解約可)です。コピーした後は、目玉のマスの写真と数字の文言だけを差し替えます。
マスの比率は触らない方が崩れません。
ベントグリッドについてよくある質問
必要ありません。CSS Grid の列の指定(grid-template-columns)と、マスをまたがせる指定(span)で作れます。
Tailwind CSS なら、4種類のクラスで足ります。列の数と行の高さは、grid-cols と auto-rows で決めます。
マスの大きさは、何列・何行をまたぐか(col-span と row-span)で決めます。
まとめ:Next.js でベントグリッドを作る手順
ベントグリッドは CSS Grid の基本の指定だけで作れる
大きいマスは1つだけにし、写真か数字を置く
スマホでは1列、タブレットでは2列に戻し、目玉のマスを2行分にするのはデスクトップだけにする
動きは大きいマスのループと、小さいマスの入場の遅延に分ける
見出しの順番・キーボードでの移動順・目玉の写真の読み込みを公開前に確認する
まずはこの記事の Bento をそのまま貼り、写真と数字を自分の内容に差し替えてみてください。
カードで見せる場合は https://design-layer.com/ja/articles/nextjs-features-section-guide 、Tailwind CSS での動きの付け方は https://design-layer.com/ja/articles/nextjs-tailwind-animation-guide が参考になります。


