Amazon10/19まで!プライム感謝祭開催中! セール会場へ

SWELL│ギャラリー・投稿リスト・リッチカラムブロックをスライダー化する方法

SWELLのギャラリー・投稿リスト・リッチカラムを、Flickityで横に送れる表示へ変更する方法です。

ブロックのまま編集し、公開画面で専用クラスを付けた部分だけをスライダーにします。

表示幅に合わせた高さをFlickityに計算させ、画像の読み込み後にも再計算します。

自動再生とループは使わず、前後ボタンで操作します。

目次

著者

WEB制作をしているデジタルノマド
WordPressのカスタマイズが好きで、色々と自作しています。

WordPressのカスタマイズに困ったらご相談ください!

動く見本:ギャラリー

画像を1枚ずつ表示します。

最後の画像では「次へ」が無効になります。

画像の縦横比が違う場合は、最も高さのあるセルに合わせた余白が残る仕様です。

動く見本:投稿リスト

通常の投稿リストブロックを使う見本です。

画面幅600px未満では1枚と次のカードの一部、600px以上では2枚、960px以上では3枚を表示します。

動く見本:リッチカラム

画像と文章をまとめたカラムを1枚として送ります。

3つの見本は独立して操作できます。

カラムのサンプル画像

画像と文章を同じカラムに入れた見本です。

画像と文章を同じカラムに入れた見本です。

画像と文章を同じカラムに入れた見本です。

画像と文章を同じカラムに入れた見本です。

リッチカラムブロックを一列に配置する設定時の編集画面の表示例。

画像と文章を同じカラムに入れた見本です。

追加CSSクラスを付けるブロック

ブロックを選択し、「高度な設定」の「追加CSSクラス」へ入力します。

先頭のドットは不要です。

個別の画像やカラム内の段落ではなく、親ブロックを選びます。

対象クラス
ギャラリーブロック全体flickity-parent-gallery
投稿リストブロック全体flickity-parent-postlist
リッチカラムブロック全体flickity-parent-column

1.Flickityを読み込むPHPを登録

PHPをCode Snippetsか子テーマのfunctions.phpのどちらか1か所へ登録します。

25516は設置先の記事IDへ変更してください。

すでにFlickityを読み込んでいる場合は、重複登録せず既存の対象ページ指定を確認します。

ライブラリは外部CDNから読み込みます。

add_action('wp_enqueue_scripts', function () {
    // 25516 は設置先の投稿IDへ置き換えます。固定ページなら is_page を使います。
    if (!is_single(array(25516))) return;
    wp_enqueue_style('flickity-css', 'https://unpkg.com/flickity@2/dist/flickity.min.css', array(), null);
    wp_enqueue_script('flickity', 'https://unpkg.com/flickity@2/dist/flickity.pkgd.min.js', array(), null, true);
});

2.専用CSSと共通JavaScriptを登録

CSSは追加CSSまたは設置先の記事CSS欄へ、JavaScriptは記事JS欄へ貼り付けます。

JSにscriptタグは付けません。

3種類のブロックに共通のコードなので、ブロックの数だけ登録する必要はありません。

.waza-flickity-track { display:block; width:100%; min-width:0; }
.waza-flickity-track .waza-flickity-cell { box-sizing:border-box; width:82%; margin-right:16px; }
.flickity-parent-gallery .waza-flickity-cell { width:100%; margin-right:0; }
.waza-flickity-cell > .wp-block-image,
.waza-flickity-cell > .swell-block-column { width:100%!important; margin:0!important; }
.waza-flickity-cell img { max-width:100%; }
.flickity-parent-gallery .waza-flickity-cell .wp-block-image img { display:block; width:100%; height:auto!important; aspect-ratio:auto!important; }
.waza-flickity-track .flickity-prev-next-button { width:44px; height:44px; }
.waza-flickity-track :is(a,button):focus-visible { outline:3px solid #0969da; outline-offset:-3px; }
@media(min-width:600px) {
  .flickity-parent-postlist .waza-flickity-cell,
  .flickity-parent-column .waza-flickity-cell { width:calc((100% - 16px) / 2); }
}
@media(min-width:960px) {
  .flickity-parent-postlist .waza-flickity-cell,
  .flickity-parent-column .waza-flickity-cell { width:calc((100% - 32px) / 3); }
}

/* 縦長画像の見本では、高さを制限して比率を保ちます。 */
.waza-flickity-mixed .waza-flickity-cell .wp-block-image img { width:auto!important; max-width:100%; max-height:480px; margin-inline:auto; }
function wazaInitFlickity() {
  if (typeof Flickity === 'undefined') return;
  const definitions = [
    ['.flickity-parent-gallery', null, '.wp-block-image'],
    ['.flickity-parent-postlist', '.p-postList', '.p-postList__item'],
    ['.flickity-parent-column', '.swell-block-columns__inner', '.swell-block-column']
  ];
  definitions.forEach(([selector, innerSelector, cellSelector]) => {
    document.querySelectorAll(selector).forEach(root => {
      if (root.dataset.wazaFlickityReady) return;
      const inner = innerSelector ? root.querySelector(innerSelector) : root;
      if (!inner) return;
      const children = Array.from(inner.children).filter(child => child.matches(cellSelector));
      if (children.length < 2) return;
      const track = document.createElement('div');
      track.className = 'waza-flickity-track';
      track.setAttribute('aria-label', '横に送れるコンテンツ');
      const cells = children.map(child => {
        const cell = document.createElement('div');
        cell.className = 'waza-flickity-cell';
        // li を ul の外へ移さず、中身を専用の div に移します。
        if (child.tagName === 'LI') {
          cell.append(...Array.from(child.childNodes));
          child.remove();
        } else cell.append(child);
        track.append(cell);
        return cell;
      });
      if (inner === root) root.prepend(track);
      else inner.replaceWith(track);
      root.dataset.wazaFlickityReady = '1';
      const carousel = new Flickity(track, {
        cellSelector: '.waza-flickity-cell', cellAlign: 'left', contain: true,
        setGallerySize: true, adaptiveHeight: false, imagesLoaded: true,
        autoPlay: false, wrapAround: false, pageDots: false,
        prevNextButtons: true, accessibility: true
      });
      track.querySelector('.previous')?.setAttribute('aria-label', '前へ');
      track.querySelector('.next')?.setAttribute('aria-label', '次へ');
      const refresh = () => requestAnimationFrame(() => carousel.resize());
      track.querySelectorAll('img').forEach(img => {
        if (!img.complete) { img.addEventListener('load', refresh, {once:true}); img.addEventListener('error', refresh, {once:true}); }
      });
      cells.forEach((cell, index) => {
        cell.querySelectorAll('a,button,input,select,textarea').forEach(control => {
          control.addEventListener('focus', () => carousel.select(index, false, true));
        });
      });
      if (document.fonts) document.fonts.ready.then(refresh);
      window.addEventListener('load', refresh, {once:true});
    });
  });
}
if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", wazaInitFlickity, { once: true });
else wazaInitFlickity();

導入前の確認と適用範囲

まず検証用サイトで、変更前のコードと設定をバックアップします。

同じブロックを加工するスライダー処理がすでにある場合は、掲載コードを重ねて適用しないでください。

掲載コードは投稿リストのliをulの外へそのまま移動せず、中身を専用セルへ移します。

編集画面のブロックデータは変更しません。

2件未満のブロックはスライダー化せず、そのまま表示します。

後からAjaxで追加するブロックや入れ子のスライダーには対応していません。

高さが合わない・動かない場合

画像が欠ける場合は、対象画像やスライダーに固定高さのCSSが適用されていないか確認します。

高さは全セルの表示高に合わせるため、画像の比率や文章量が違うと短いセルに余白が残ります。

画像が未読込の状態と読み込み後、PC・スマートフォンの両方で確認してください。

ボタンが出ない場合は、PHPの対象ページID、クラス名、Flickityの読み込みを確認します。

ライブラリが読み込めないときはブロックを変換せず表示します。

JS欄にPHPを貼らないこと、同じ対象にSwiperも適用していないことを確認してください。

キャッシュ削除後に再確認します。

元のブロック表示へ戻す場合は、この記事の手順で追加したJS・CSSと追加クラスを外し、このページだけに追加したライブラリ読み込みを停止します。

別ページでも使う共通の読み込みは停止しないでください。

ほかの方式との選び方

投稿一覧だけが目的なら、SWELL内のSwiperを使う投稿リストやCSSだけの横スクロールも比較できます。

Flickityの詳細設定は公式オプション、利用条件は公式ライセンス案内で確認してください。

画像1枚と縦横比が違う画像の見本

次は画像1枚だけのギャラリーです。

追加クラスがあってもスライダー化せず、前後ボタンを出しません。

次は横長の画像と縦長の操作画面を並べた見本です。

高い方のセルに枠の高さを合わせるため、短いセルには余白が残ります。

画像を欠けさせる固定高さの指定は使いません。

JavaScriptの実行が遅れる場合

JavaScriptを遅延実行する設定では、DOMContentLoadedが終わってからコードが動く場合があります。

掲載コードはdocument.readyStateを確認し、読み込み済みならその場で初期化します。

この初期化は、実行時にFlickity本体が読み込み済みであることが前提です。本体が未定義なら通常のブロック表示を保ち、その後に本体が読み込まれても自動では再試行しません。記事JSを含めて読み込み順を確認し、遅延実行設定を使う場合は本体と初期化コードの実行順が保たれるようにしてください。

外部CDNに接続できない場合や、遅延実行の設定を変えた場合の実ブラウザー動作は未検証です。

設定変更後は対象記事のキャッシュと公開画面を確認してください。

縦長の画像が画面を占有しすぎる場合は、親ギャラリーにwaza-flickity-mixedも付けます。

掲載CSSでは画像を最大480px高にし、縦横比を保って中央に置きます。

枠の高さは表示されたセルから計算します。

スマホでの操作画面

縦長の画像を表示した状態です。

前へボタンにはキーボード操作のフォーカス枠が付き、最後の画像では次へボタンが無効になります。

縦長画像を表示したFlickityの見本と前へボタンのフォーカス
2026年10月2日撮影。WAZAの公開ページ、スマホ幅390pxで確認。
  • URLをコピーしました!

実装を任せたい方へ

SWELLのカスタマイズ代行

記事のコードをそのまま使うのが不安な場合や、サイトに合わせた調整が必要な場合は当社が実装します。1時間 ¥8,000〜(税込)。テーマ更新に強い書き方で納品します。

WAZAの有料記事のサブスクリプションも開始しました。

サービス

Service

WordPressサイトのカスタマイズのサービスに関心がありましたら、ぜひ詳細をご覧ください。

目次