タイトル: スライダーの作成とカスタマイズ
SEOタイトル: JavaScript スライダー実装ガイド(Swiper / Slick / 自前実装 / React / Vue)
この本文には実行可能なタグ等が含まれるため、安全のためHTMLソースとして表示しています。本文データは変更していません。
<table border="1" cellpadding="6" cellspacing="0" style="border-collapse:collapse;background:#fffbea;border:1px solid #f4c430;margin:1em 0;width:100%"><tr><td style="background:#f4c430;color:#000;font-weight:bold;padding:8px">この記事の要点</td></tr><tr><td style="padding:10px"><ul><li>現在の定番は <strong>Swiper.js</strong>(タッチ・モバイル対応・依存なし)</li><li>昔ながらの選択肢: <strong>Slick.js</strong>(jQuery 必須) / <strong>jQuery UI Slider</strong>(つまみ型)</li><li>自前実装は <strong>touchstart / touchmove / touchend</strong> + <strong>transform: translateX()</strong> の組み合わせ</li><li>オプション: <strong>autoplay / loop / pagination / navigation / effect:"fade"</strong></li><li>フレームワーク版: <strong>Vue Awesome Swiper</strong> / <strong>swiper/react</strong> / <strong>react-slick</strong></li></ul></td></tr></table>
<h2>JavaScript スライダーの選択肢</h2>
<table border="1" cellpadding="6" cellspacing="0" style="border-collapse:collapse;width:100%">
<thead><tr style="background:#e3f2fd"><th>ライブラリ</th><th>特徴</th><th>サイズ</th></tr></thead>
<tbody>
<tr><td><strong>Swiper.js</strong></td><td>依存なし、タッチ最適化、超多機能</td><td>140KB(gzip 40KB)</td></tr>
<tr><td>Slick.js</td><td>jQuery 必須、レガシ案件に多い</td><td>40KB + jQuery</td></tr>
<tr><td>Glide.js</td><td>軽量、依存なし</td><td>30KB</td></tr>
<tr><td>Splide.js</td><td>アクセシビリティ重視</td><td>50KB</td></tr>
<tr><td>jQuery UI Slider</td><td>つまみ型(カルーセルでなく値選択)</td><td>jQuery UI</td></tr>
</tbody>
</table>
<h2>Swiper.js(推奨)</h2>
<p>2026 年現在、新規実装は Swiper.js 一択と言って良いほど。CDN ですぐ使えます:</p>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-html"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/swiper@11/swiper-bundle.min.css" />
<script src="https://cdn.jsdelivr.net/npm/swiper@11/swiper-bundle.min.js"></script>
<div class="swiper" style="width:600px;height:400px">
<div class="swiper-wrapper">
<div class="swiper-slide"><img src="/img/1.jpg"></div>
<div class="swiper-slide"><img src="/img/2.jpg"></div>
<div class="swiper-slide"><img src="/img/3.jpg"></div>
</div>
<div class="swiper-pagination"></div>
<div class="swiper-button-prev"></div>
<div class="swiper-button-next"></div>
</div>
<script>
const swiper = new Swiper('.swiper', {
loop: true,
autoplay: { delay: 3000, disableOnInteraction: false },
pagination: { el: '.swiper-pagination', clickable: true },
navigation: { nextEl: '.swiper-button-next', prevEl: '.swiper-button-prev' },
effect: 'slide', // slide | fade | cube | coverflow | flip
speed: 600,
});
</script></code></pre>
<h2>Swiper の主要オプション</h2>
<table border="1" cellpadding="6" cellspacing="0" style="border-collapse:collapse;width:100%">
<thead><tr style="background:#e3f2fd"><th>オプション</th><th>説明</th></tr></thead>
<tbody>
<tr><td><code>slidesPerView</code></td><td>同時に表示するスライド数(複数表示)</td></tr>
<tr><td><code>spaceBetween</code></td><td>スライド間の余白 (px)</td></tr>
<tr><td><code>loop</code></td><td>無限ループ</td></tr>
<tr><td><code>autoplay</code></td><td>自動再生 <code>{ delay: 3000 }</code></td></tr>
<tr><td><code>effect</code></td><td>slide / fade / cube / coverflow / flip / creative</td></tr>
<tr><td><code>breakpoints</code></td><td>レスポンシブ別オプション</td></tr>
<tr><td><code>centeredSlides</code></td><td>中央寄せ</td></tr>
<tr><td><code>lazy</code></td><td>画像遅延読み込み</td></tr>
</tbody>
</table>
<h2>レスポンシブ対応</h2>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-javascript">new Swiper('.swiper', {
slidesPerView: 1,
spaceBetween: 10,
breakpoints: {
640: { slidesPerView: 2, spaceBetween: 20 },
768: { slidesPerView: 3, spaceBetween: 30 },
1024: { slidesPerView: 4, spaceBetween: 40 },
},
});</code></pre>
<h2>CSS カスタマイズ</h2>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-css">/* ページネーションの bullet を四角に */
.swiper-pagination-bullet {
width: 20px;
height: 4px;
border-radius: 0;
background: #ccc;
opacity: 1;
}
.swiper-pagination-bullet-active {
background: #ff6b6b;
}
/* prev/next ボタンの色 */
.swiper-button-prev,
.swiper-button-next {
color: #ff6b6b;
--swiper-navigation-size: 28px;
}
/* スライド画像をはみ出さない */
.swiper-slide img {
width: 100%;
height: 100%;
object-fit: cover;
}</code></pre>
<h2>React で使う(swiper/react)</h2>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-jsx">import { Swiper, SwiperSlide } from 'swiper/react';
import { Navigation, Pagination, Autoplay } from 'swiper/modules';
import 'swiper/css';
import 'swiper/css/navigation';
import 'swiper/css/pagination';
export default function Carousel({ items }) {
return (
<Swiper
modules={[Navigation, Pagination, Autoplay]}
navigation
pagination={{ clickable: true }}
autoplay={{ delay: 3000 }}
loop
spaceBetween={20}
slidesPerView={1}
breakpoints={{
640: { slidesPerView: 2 },
1024: { slidesPerView: 3 },
}}
>
{items.map(item => (
<SwiperSlide key={item.id}>
<img src={item.image} alt={item.title} />
</SwiperSlide>
))}
</Swiper>
);
}</code></pre>
<h2>Vue で使う(vue-awesome-swiper / swiper/vue)</h2>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-vue"><template>
<swiper
:modules="modules"
:slides-per-view="1"
:space-between="20"
navigation
:pagination="{ clickable: true }"
:autoplay="{ delay: 3000 }"
loop
>
<swiper-slide v-for="item in items" :key="item.id">
<img :src="item.image" />
</swiper-slide>
</swiper>
</template>
<script setup>
import { Swiper, SwiperSlide } from 'swiper/vue';
import { Navigation, Pagination, Autoplay } from 'swiper/modules';
import 'swiper/css';
import 'swiper/css/navigation';
import 'swiper/css/pagination';
const modules = [Navigation, Pagination, Autoplay];
defineProps(['items']);
</script></code></pre>
<h2>Slick.js(レガシ案件向け)</h2>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-html"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/slick-carousel@1.8/slick/slick.css" />
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/slick-carousel@1.8/slick/slick-theme.css" />
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/slick-carousel@1.8/slick/slick.min.js"></script>
<div class="my-slider">
<div><img src="/img/1.jpg"></div>
<div><img src="/img/2.jpg"></div>
<div><img src="/img/3.jpg"></div>
</div>
<script>
$(document).ready(function() {
$('.my-slider').slick({
autoplay: true,
autoplaySpeed: 3000,
dots: true,
arrows: true,
infinite: true,
slidesToShow: 1,
});
});
</script></code></pre>
<h2>自前実装(依存なし)</h2>
<p>ライブラリを使いたくない場合の最小実装:</p>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-html"><style>
.slider { position: relative; overflow: hidden; width: 600px; height: 300px; }
.slides { display: flex; transition: transform 0.5s ease; }
.slide { min-width: 100%; }
.slide img { width: 100%; height: 300px; object-fit: cover; }
</style>
<div class="slider">
<div class="slides">
<div class="slide"><img src="/img/1.jpg"></div>
<div class="slide"><img src="/img/2.jpg"></div>
<div class="slide"><img src="/img/3.jpg"></div>
</div>
</div>
<script>
const slides = document.querySelector('.slides');
let index = 0;
let startX = 0;
let dragX = 0;
setInterval(() => {
index = (index + 1) % 3;
slides.style.transform = `translateX(-${index * 100}%)`;
}, 3000);
slides.addEventListener('touchstart', e => {
startX = e.touches[0].clientX;
});
slides.addEventListener('touchmove', e => {
dragX = e.touches[0].clientX - startX;
});
slides.addEventListener('touchend', () => {
if (Math.abs(dragX) > 50) {
index = (index + (dragX < 0 ? 1 : -1) + 3) % 3;
slides.style.transform = `translateX(-${index * 100}%)`;
}
});
</script></code></pre>
<h2>jQuery UI Slider(値選択用つまみ)</h2>
<p>「スライダー」でも<strong>値を選ぶつまみ型 UI</strong>を作りたい場合はこちら:</p>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-javascript">// HTML: <div id="amount-slider"></div> <input id="amount" value="500">
$('#amount-slider').slider({
min: 0,
max: 1000,
step: 10,
value: 500,
slide: function(event, ui) {
$('#amount').val(ui.value);
},
});</code></pre>
<h2>FAQ</h2>
<p><strong>Q: Swiper の loop で重複コンテンツが SEO に悪影響しない?</strong><br />
A: 内部的にクローンを <code>aria-hidden="true"</code> で複製しているだけで、Googlebot は実体を 1 つと認識します。</p>
<p><strong>Q: アクセシビリティ的にスライダーは推奨される?</strong><br />
A: 自動再生はユーザーの注意を奪うため、停止ボタン必須・<code>prefers-reduced-motion</code> 尊重・キーボード操作対応が WCAG 推奨です。</p>
<p><strong>Q: 画像が大量で遅い</strong><br />
A: Swiper の <code>lazy</code> オプションで遅延読み込み。または <code>loading="lazy"</code> 属性を画像に付与。</p>
<!-- @RESTORED_IMG_v1 -->
<h2>📸 参考画像</h2>
<p style="color:#666;font-size:0.85em;margin-bottom:1em">※ 旧バージョンから引き継いだ参考画像です。手順・図解の補助としてご覧ください。</p>
<p style="text-align:center;margin:1em 0"><img alt="参考画像" src="https://jpn.itlibra.com/uploadImage/20190706173607_8102003.png" style="max-width:640px;width:100%;height:auto;border:1px solid #ccc;border-radius:4px" /></p>