ギャラリー · ギャラリー

ベントーグリッドの写真ギャラリー

保存した一覧を見る 0 →

このブラウザー内に保存します。別の端末との同期はなく、サイトデータを消すと保存も消えます。

印刷時は見本を静止画にし、プロンプトと解説を出力します。PDF保存はブラウザーの印刷画面から選べます。

Vibehaus · デザイン資料
https://vibe.itlibra.com/design/bento-photo-gallery/
完全無料・著作権フリー(CC0)· 料金¥0 · 商用利用・改変自由

プレビュー

画面に合わせる

指定幅で実際に組み替えて表示します。表示領域より広い場合は、この枠の中で横へスクロールできます。

vibe.itlibra.com/preview/bento-photo-gallery/

AIへの指示文

写真作品のギャラリーページを、ベントーグリッド(弁当箱のように大小のタイルを組み合わせるレイアウト)で作ってください。

要件:
- 配色: 暗背景 #0f1012、タイル #17191d、境界線 #262a30、テキスト #f2f3f5、アクセント #7cd4c0。
- グリッドは `grid-template-columns: repeat(6, 1fr)` + `grid-auto-rows: 116px` を土台にする。
- タイルの大きさを4種類に分ける: 主役(span 4 × 3行)、縦長(span 2 × 3行)、横長(span 3 × 2行)、正方形(span 2 × 2行)。
- 最下段に全幅(span 6)の細いストリップを置き、アーカイブへの導線にする。
- 各タイルは角丸14px、写真の上に下方向グラデーション(透明 → rgba(0,0,0,0.72))を重ね、その上にタイトルと撮影地・日付を置く。
- hover で translateY(-3px) + 枠線をアクセント色に。
- 上部にカテゴリ絞り込みチップ(ピル型、選択中はアクセント色で塗る)。
- 900px 以下は4カラム、560px 以下は2カラムに再構成する。
- 写真は用意せず CSS グラデーションで代用してよい。

バリエーション

明るい紙面版

背景を #faf8f4、タイルを白、境界線を薄いグレーに。
写真の上のグラデーションは不要にして、タイトルはタイルの下に置く。

動画サムネイル版

各タイルに再生時間バッジと再生アイコンを追加。
主役タイルだけ hover で自動再生プレビューが走る想定にする。

このプレビューのコード

HTML・CSS・JavaScriptの1ファイルです。外部依存・広告・解析コードはありません。CSSで描く7作品を4分類で絞り込む見本です。実件数を表示し、すべてへ戻せます。作品は説明へ移動します。写真の取得・撮影実績・投稿・送信・保存は含みません。

CC0 · 改変・商用利用自由 · revision 91c6835537a7

コードを表示
<!doctype html>
<!-- Vibehaus · CC0 · 架空の表示・操作見本。外部素材・送信・永続保存なし。 -->
<html lang="ja">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta name="robots" content="noindex" />
    <title>ベントーグリッドの写真ギャラリー — Vibehaus プレビュー</title>
    <style>
      :root {
        --bg: #0f1012;
        --tile: #17191d;
        --tile-hi: #1e2126;
        --line: #262a30;
        --fg: #f2f3f5;
        --fg-dim: #9aa1ab;
        --accent: #7cd4c0;
        --accent-warm: #f0a868;
      }
      * { box-sizing: border-box; }
      html, body { margin: 0; padding: 0; }
      body {
        font-family: "Inter", "Helvetica Neue", "Hiragino Kaku Gothic ProN",
          "Noto Sans JP", "Yu Gothic", "Meiryo", sans-serif;
        background: var(--bg);
        color: var(--fg);
        line-height: 1.8;
        -webkit-font-smoothing: antialiased;
      }

      .wrap {
        max-width: 1240px;
        margin: 0 auto;
        padding: clamp(1.5rem, 4vw, 3rem) clamp(1rem, 3vw, 2rem) 4rem;
      }

      header.top {
        display: flex;
        align-items: flex-end;
        justify-content: space-between;
        gap: 1.5rem;
        flex-wrap: wrap;
        padding-bottom: 1.5rem;
        border-bottom: 1px solid var(--line);
      }
      .eyebrow {
        font-family: "JetBrains Mono", ui-monospace, monospace;
        font-size: 0.72rem;
        letter-spacing: 0.18em;
        text-transform: uppercase;
        color: var(--accent);
        margin: 0 0 0.5rem;
      }
      h1 {
        margin: 0;
        font-size: clamp(1.7rem, 4vw, 2.6rem);
        line-height: 1.4;
        font-weight: 700;
      }
      .count {
        font-family: "JetBrains Mono", ui-monospace, monospace;
        font-size: 0.78rem;
        color: var(--fg-dim);
      }

      .filters {
        display: flex;
        gap: 0.5rem;
        flex-wrap: wrap;
        margin: 1.5rem 0 1.75rem;
      }
      .chip {
        font-size: 0.82rem;
        line-height: 1.5;
        padding: 0.4rem 0.95rem;
        border: 1px solid var(--line);
        border-radius: 999px;
        background: var(--tile);
        color: var(--fg-dim);
        cursor: pointer;
        transition: color 0.15s, border-color 0.15s, background 0.15s;
      }
      .chip:hover { color: var(--fg); border-color: var(--accent); }
      .chip[aria-pressed="true"] {
        color: var(--bg);
        background: var(--accent);
        border-color: var(--accent);
        font-weight: 600;
      }

      /* Bento grid — a 6-column bed where tiles claim different spans. */
      .bento {
        display: grid;
        grid-template-columns: repeat(6, 1fr);
        grid-auto-rows: 92px;
        gap: 12px;
      }
      .tile {
        position: relative;
        overflow: hidden;
        border: 1px solid var(--line);
        border-radius: 14px;
        background: var(--tile);
        padding: 1rem;
        display: flex;
        flex-direction: column;
        justify-content: flex-end;
        text-decoration: none;
        color: inherit;
        transition: transform 0.18s ease, border-color 0.18s, background 0.18s;
      }
      .tile:hover {
        transform: translateY(-3px);
        border-color: var(--accent);
        background: var(--tile-hi);
      }
      .tile:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

      /* Stand-in artwork: pure CSS gradients so the file stays self-contained. */
      .art { position: absolute; inset: 0; z-index: 0; }
      .a1 { background: radial-gradient(120% 90% at 20% 15%, #2f6f63 0%, #14322f 55%, #0f1012 100%); }
      .a2 { background: linear-gradient(150deg, #3a2f52 0%, #6b4a7a 55%, #1a1523 100%); }
      .a3 { background: radial-gradient(100% 120% at 80% 20%, #8a5a2b 0%, #3b2716 60%, #120e0a 100%); }
      .a4 { background: linear-gradient(200deg, #1f3b52 0%, #2c6079 60%, #0e1a22 100%); }
      .a5 { background: conic-gradient(from 210deg at 60% 40%, #4a4436, #7d6a3f, #2b271c, #4a4436); }
      .a6 { background: linear-gradient(115deg, #45213a 0%, #8a3f63 50%, #1d0f18 100%); }
      .a7 { background: radial-gradient(90% 110% at 30% 80%, #2a4d3a 0%, #16281f 60%, #0d1410 100%); }
      .art::after {
        content: "";
        position: absolute;
        inset: 0;
        background: linear-gradient(180deg, rgba(0,0,0,0) 35%, rgba(0,0,0,0.72) 100%);
      }

      .tile-body { position: relative; z-index: 1; }
      .tile-title {
        margin: 0;
        font-size: 0.98rem;
        line-height: 1.5;
        font-weight: 600;
      }
      .tile-meta {
        margin: 0.15rem 0 0;
        font-family: "JetBrains Mono", ui-monospace, monospace;
        font-size: 0.7rem;
        letter-spacing: 0.08em;
        color: var(--fg-dim);
      }
      .badge {
        position: absolute;
        top: 0.85rem;
        left: 0.85rem;
        z-index: 1;
        font-family: "JetBrains Mono", ui-monospace, monospace;
        font-size: 0.64rem;
        letter-spacing: 0.14em;
        text-transform: uppercase;
        padding: 0.22rem 0.55rem;
        border-radius: 999px;
        background: rgba(15, 16, 18, 0.78);
        border: 1px solid var(--line);
        color: var(--accent-warm);
      }

      /* Span assignments — the whole point of a bento layout. */
      .s-hero  { grid-column: span 4; grid-row: span 3; }
      .s-tall  { grid-column: span 2; grid-row: span 3; }
      .s-wide  { grid-column: span 3; grid-row: span 2; }
      .s-box   { grid-column: span 2; grid-row: span 2; }
      .s-small { grid-column: span 2; grid-row: span 2; }
      .s-strip { grid-column: span 6; grid-row: span 1; }

      .strip {
        flex-direction: row;
        align-items: center;
        justify-content: space-between;
        gap: 1rem;
        background: var(--tile);
      }
      .strip p { margin: 0; font-size: 0.9rem; line-height: 1.7; color: var(--fg-dim); }
      .strip b { color: var(--fg); font-weight: 600; }
      .strip .go {
        font-family: "JetBrains Mono", ui-monospace, monospace;
        font-size: 0.75rem;
        letter-spacing: 0.12em;
        color: var(--accent);
        white-space: nowrap;
      }

      @media (max-width: 900px) {
        .bento { grid-template-columns: repeat(4, 1fr); }
        .s-hero { grid-column: span 4; grid-row: span 3; }
        .s-tall, .s-wide, .s-box, .s-small { grid-column: span 2; grid-row: span 2; }
        .s-strip { grid-column: span 4; }
      }
      @media (max-width: 560px) {
        .bento { grid-template-columns: repeat(2, 1fr); grid-auto-rows: 86px; }
        .s-hero { grid-column: span 2; grid-row: span 3; }
        .s-tall, .s-wide, .s-box, .s-small, .s-strip { grid-column: span 2; grid-row: span 2; }
      }
    [hidden]{display:none!important}
a,button,input,summary{min-width:44px;min-height:44px}
a{touch-action:manipulation}
button{cursor:pointer}
button:disabled{cursor:default}
a:focus-visible,button:focus-visible,input:focus-visible{outline:3px solid currentColor;outline-offset:4px}
nav a{display:inline-flex;align-items:center;justify-content:center}
nav{flex-wrap:wrap}
header.bar{flex-wrap:wrap;gap:1rem}
input{max-width:100%}
.demo-notes{position:relative;z-index:10;box-sizing:border-box;max-width:1080px;width:calc(100% - 2rem);margin:2rem auto;padding:clamp(1rem,3vw,2rem);background:#0f1012;color:#f2f3f5;border:1px solid currentColor;text-align:left;font-family:"Hiragino Sans","Yu Gothic",Meiryo,sans-serif;font-size:13px;line-height:1.8;letter-spacing:0;overflow-wrap:anywhere}
.demo-notes h2{font-size:18px;line-height:1.5;margin:0 0 .75rem}
.demo-notes h3{font-size:15px;line-height:1.5;margin:0 0 .4rem}
.demo-notes p{font:inherit;color:inherit;opacity:1;margin:0 0 1rem;max-width:none;letter-spacing:0}
.demo-notes section{margin-top:1.25rem;scroll-margin-top:1rem}
.demo-notes button{font:inherit;color:inherit;background:transparent;border:1px solid currentColor;padding:.4rem .75rem}
.demo-notes a{color:inherit}
.demo-notes .demo-motion{margin-bottom:1rem}
.demo-notes section:focus{outline:3px solid currentColor;outline-offset:4px}
@media(prefers-reduced-motion:reduce){*,*::before,*::after{animation:none!important;transition:none!important}
}
.tile[hidden]{display:none!important}
.tile-title{overflow-wrap:anywhere}
.strip{flex-wrap:wrap}
.strip .go{white-space:normal}
.filters{flex-wrap:wrap}
</style>
  </head>
  <body>
    <div class="wrap">
      <header class="top">
        <div>
          <p class="eyebrow">Gallery · 2026 Selection</p>
          <h1>光と静けさの記録</h1>
        </div>
        <span class="count"><span data-gallery-count>7</span> WORKS · 表示見本</span>
      </header>

      <div class="filters" role="group" aria-label="絞り込み">
        <button data-js-control disabled class="chip" type="button" aria-pressed="true">すべて</button>
        <button data-js-control disabled class="chip" type="button" aria-pressed="false">風景</button>
        <button data-js-control disabled class="chip" type="button" aria-pressed="false">建築</button>
        <button data-js-control disabled class="chip" type="button" aria-pressed="false">静物</button>
        <button data-js-control disabled class="chip" type="button" aria-pressed="false">夜</button>
      </div>

      <p data-gallery-empty hidden role="status">この分類の作品はありません。「すべて」で7件へ戻れます。</p>
<div class="bento">
        <a data-gallery-group="風景" class="tile s-hero" href="#demo-link-0">
          <span class="art a1" aria-hidden="true"></span>
          <span class="badge">Featured</span>
          <div class="tile-body">
            <h2 class="tile-title">霧の谷、夜明け前の30分</h2>
            <p class="tile-meta">Nagano · 2026.05 · CSS ART</p>
          </div>
        </a>

        <a data-gallery-group="風景" class="tile s-tall" href="#demo-link-1">
          <span class="art a2" aria-hidden="true"></span>
          <div class="tile-body">
            <h2 class="tile-title">紫の残照</h2>
            <p class="tile-meta">Kyoto · 2026.04</p>
          </div>
        </a>

        <a data-gallery-group="静物" class="tile s-wide" href="#demo-link-2">
          <span class="art a3" aria-hidden="true"></span>
          <div class="tile-body">
            <h2 class="tile-title">砂丘のテクスチャー</h2>
            <p class="tile-meta">Tottori · 2026.03</p>
          </div>
        </a>

        <a data-gallery-group="夜" class="tile s-box" href="#demo-link-3">
          <span class="art a4" aria-hidden="true"></span>
          <div class="tile-body">
            <h2 class="tile-title">港、青の時間</h2>
            <p class="tile-meta">Hakodate</p>
          </div>
        </a>

        <a data-gallery-group="風景" class="tile s-small" href="#demo-link-4">
          <span class="art a5" aria-hidden="true"></span>
          <div class="tile-body">
            <h2 class="tile-title">枯野</h2>
            <p class="tile-meta">Aso</p>
          </div>
        </a>

        <a data-gallery-group="夜" class="tile s-box" href="#demo-link-5">
          <span class="art a6" aria-hidden="true"></span>
          <span class="badge">New</span>
          <div class="tile-body">
            <h2 class="tile-title">ネオンの雨</h2>
            <p class="tile-meta">Osaka · 2026.07</p>
          </div>
        </a>

        <a data-gallery-group="風景" class="tile s-small" href="#demo-link-6">
          <span class="art a7" aria-hidden="true"></span>
          <div class="tile-body">
            <h2 class="tile-title">杉の列</h2>
            <p class="tile-meta">Yakushima</p>
          </div>
        </a>

        <a class="tile s-strip strip" href="#demo-link-7">
          <p><b>アーカイブ 2018–2025</b> — 過去の全シリーズを年代順に見る</p>
          <span class="go">VIEW ARCHIVE →</span>
        </a>
      </div>
    </div>


  <aside class="demo-notes" aria-label="この見本について">
<h2>この見本について</h2>
<p>CSSで描く架空の作品集です。写真の撮影実績や画像ファイルは含みません。作品リンクは構成の説明へ移動し、投稿・アップロード・保存は行いません。配布HTMLはCC0・利用料¥0。外部素材やライブラリの取得は不要です。</p>
<section id="demo-link-0" tabindex="-1">
<h3>霧の谷、夜明け前の30分の見本</h3>
<p>色面と余白で作品を見せる構成例です。タイトル・地名・撮影時刻は架空の設定で、写真・別ページ・投稿機能は含みません。</p>
</section>
<section id="demo-link-1" tabindex="-1">
<h3>紫の残照の見本</h3>
<p>色面と余白で作品を見せる構成例です。タイトル・地名・撮影時刻は架空の設定で、写真・別ページ・投稿機能は含みません。</p>
</section>
<section id="demo-link-2" tabindex="-1">
<h3>砂丘のテクスチャーの見本</h3>
<p>色面と余白で作品を見せる構成例です。タイトル・地名・撮影時刻は架空の設定で、写真・別ページ・投稿機能は含みません。</p>
</section>
<section id="demo-link-3" tabindex="-1">
<h3>港、青の時間の見本</h3>
<p>色面と余白で作品を見せる構成例です。タイトル・地名・撮影時刻は架空の設定で、写真・別ページ・投稿機能は含みません。</p>
</section>
<section id="demo-link-4" tabindex="-1">
<h3>枯野の見本</h3>
<p>色面と余白で作品を見せる構成例です。タイトル・地名・撮影時刻は架空の設定で、写真・別ページ・投稿機能は含みません。</p>
</section>
<section id="demo-link-5" tabindex="-1">
<h3>ネオンの雨の見本</h3>
<p>色面と余白で作品を見せる構成例です。タイトル・地名・撮影時刻は架空の設定で、写真・別ページ・投稿機能は含みません。</p>
</section>
<section id="demo-link-6" tabindex="-1">
<h3>杉の列の見本</h3>
<p>色面と余白で作品を見せる構成例です。タイトル・地名・撮影時刻は架空の設定で、写真・別ページ・投稿機能は含みません。</p>
</section>
<section id="demo-link-7" tabindex="-1">
<h3>アーカイブ 2018–2025 — 過去の全シリーズを年代順に見る VIEW ARCHIVE →の見本</h3>
<p>色面と余白で作品を見せる構成例です。タイトル・地名・撮影時刻は架空の設定で、写真・別ページ・投稿機能は含みません。</p>
</section>
<noscript>
<p>JavaScriptなしでも初期表示と説明リンクを利用できます。絞り込み・入力確認・演出の切替は無効です。</p>
</noscript>
</aside><script>
const filters=[...document.querySelectorAll('.chip')],tiles=[...document.querySelectorAll('[data-gallery-group]')];filters.forEach((button,i)=>button.addEventListener('click',()=>{filters.forEach(b=>b.setAttribute('aria-pressed',String(b===button)));let count=0;tiles.forEach(tile=>{tile.hidden=i!==0&&tile.dataset.galleryGroup!==button.textContent;if(!tile.hidden)count++});document.querySelector('[data-gallery-count]').textContent=count;document.querySelector('[data-gallery-empty]').hidden=count!==0}));
document.querySelectorAll('[data-js-control]').forEach(el=>el.disabled=false);
</script>
</body>
</html>

2026年10月14日、Chromiumで320・390・768・1280pxの描画とキーボードのフォーカス表示を確認しました。他のブラウザは未確認です。利用先のブラウザと実データでも確認してください。

概要

ベントーグリッドは、日本の弁当箱の仕切りから名前を取ったレイアウトです。2020年代前半にApple製品ページやSaaSの機能紹介で一気に広まりましたが、もともとの発想は雑誌のフォトエッセイに近く、写真の一覧こそ本来の適地です。大小のタイルが噛み合う構造は、作品に自然な格差をつけます。

均一グリッドが失うもの

同じサイズの正方形を並べるギャラリーは、整然としている代わりに、どれを先に見ればいいのか教えてくれません。訪問者の視線は左上から機械的に走査し、途中で飽きて離脱します。ベントーグリッドは、大きさそのものを編集の言葉として使います。主役に4列3行を与え、脇役を2列2行に収める——それだけで、作者がどれを推しているかが一目で伝わります。写真の良し悪しではなく、並べ方が価値を決めるという事実に向き合うレイアウトです。

暗い背景が写真を立たせる理由

写真ギャラリーを暗背景にするのは、単なる雰囲気作りではありません。周囲が明るいと、目は画面全体の平均輝度に順応し、写真の中の明部が沈んで見えます。背景を落とすと写真そのものが光源になり、色の再現域が広く感じられます。美術館の展示室が暗いのと同じ理屈です。タイルの上に下方向のグラデーションを重ねてキャプションを置くのも、写真の情報量を削らずに文字を読ませるための古典的な手法です。

仕上げの判断軸

崩れやすいのはレスポンシブです。カラム数だけ減らして span を固定したままにすると、タイルが画面外へはみ出します。6列→4列→2列と落とすタイミングで span も同時に縮めてください。

4×3 / 2×2主役と脇役のタイル。作者の推しが一目で伝わる
6→4→2カラム数の段。span を固定するとタイルが画面外へ出る
10点この様式が成立する下限。少ないと強弱がノイズに見える

写真の縦横比が揃っていない場合は切り抜きで対応できますが、人物や建築は切れ方の確認が要ります。作品数が10点に満たないうちは、ベントーの強弱がノイズに見えることもあります。

見本で試せる範囲

CSSで描く7作品を4分類で絞り込む見本です。実件数を表示し、すべてへ戻せます。作品は説明へ移動します。写真の取得・撮影実績・投稿・送信・保存は含みません。 作品・記事・サービス名や数値は表示のための設定です。リンク先には、このHTMLに含まれる範囲と利用先で接続する処理を説明しています。配布HTMLはCC0・利用料¥0で、保存した1ファイルだけで表示できます。

ギャラリーの構成要素

ギャラリーの構成要素 絞り込み・件数 width と height を書いて、読み込み前に場所を確保する 書かないと、画像が届くたびに下の内容が突き落とされる
ギャラリーは画像の枚数だけレイアウトのずれが起きます。寸法の申告と遅延読み込みは、見た目より先に手当てしてください。

使いどころ

  • 写真家・映像作家のポートフォリオ
  • 作品数に強弱があるギャラリー
  • 建築・インテリアの事例集
  • 雑誌のフォトエッセイ企画
  • 商品写真の一覧ページ

このデザインの分類

カテゴリ
ギャラリー
スタイル
ベントー / ダーク / ミニマル / クール / エディトリアル

背景と狙いどころ

よくある質問

タイルの大きさはどう決めますか?
見せたい順に大・中・小を割り当てます。全部を大きくすると差が消え、ただの均一グリッドに戻ります。
写真の縦横比がバラバラでも成立しますか?
タイル側で object-fit: cover を指定して切り抜けば成立します。ただし人物や建築は切れ方を個別に確認してください。
レスポンシブで崩れませんか?
カラム数を6→4→2と落とし、span 値も同時に縮めます。span を固定したままだとはみ出します。
画像が多いと重くなりませんか?
主役タイル以外は loading=lazy、サムネイルは実表示サイズの2倍までに抑えるのが目安です。

この画面を実装する

動くサンプルとコピペできるコードを、技術別にまとめています。