動きを実現する仕組み
JavascriptでMVなどで使用する複数表示版カルーセルスライダーを作成
STEP1 HTMLコード
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>test2</title>
<meta name="description" content="これはJsのTestページです" />
<meta name="keywords" content="test, サンプル, ウェブサイト" />
<!-- Google Fontsの読み込み -->
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=Noto+Serif+JP:wght@ 200..900&display=swap"
rel="stylesheet"
/>
<!-- CSSファイルの読み込み -->
<link rel="stylesheet" href="css/normalize.css" />
<link rel="stylesheet" type="text/css" href="css/style.css" />
<link rel="stylesheet" type="text/css" href="css/header.css" />
<link rel="stylesheet" type="text/css" href="css/mv.css" />
<link rel="stylesheet" type="text/css" href="css/carousel.css" />
</head>
<body>
<header id="header">
<div class="header_inner">
<div class="header_logo">
<a href="index.html"><img src="images/logo2.svg" alt="ロゴ画像" /></a>
</div>
<nav class="header_nav">
<ul>
<li><a href="index.html">Home</a></li>
<li><a href="test1.html">Test1</a></li>
<li><a href="test2.html">Test2</a></li>
<li><a href="access.html">Access</a></li>
</ul>
<div class="header_btn">
<a href="#" class="btn_basic">お問い合わせ</a>
</div>
</nav>
</div>
</header>
<div class="mv_top_wrapper">
<div class="mv_top_inner">
<div class="mv_top_content">
<ul>
<li><img class="mv_image" src="images/mv1.jpg" alt="画像1" /></li>
<li><img class="mv_image" src="images/mv2.jpg" alt="画像2" /></li>
<li><img class="mv_image" src="images/mv3.jpg" alt="画像3" /></li>
</ul>
</div>
</div>
</div>
<main id="main">
<section class="carousel_section_secondary">
<div class="section_inner_secondary">
<h2 class="section_title_secondary">カルーセルの複数表示セクション</h2>
<div class="custom-carousel_secondary">
<div class="carousel-slides_secondary">
<div class="carousel-slide_secondary active">
<img src="/images/mv1.jpg" alt="画像1">
</div>
<div class="carousel-slide_secondary">
<img src="/images/mv2.jpg" alt="画像2"/>
</div>
<div class="carousel-slide_secondary">
<img src="/images/mv3.jpg" alt="画像3"/>
</div>
<div class="carousel-pagination_secondary"></div>
<button class="carousel-prev_secondary">❮</button>
<button class="carousel-next_secondary">❯</button>
</div>
</div>
</div>
</section>
</main>
<footer>
<div class="footer_inner"></div>
</footer>
<!-- JavaScriptファイルの読み込み -->
<script src="js/anime_mv.js"></script>
<script src="js/carousel.js"></script>
<script src="js/carousel_secondary.js"></script>
</body>
</html>CSSでコーディング
STEP2 cssコード
normalize.css
@charset "utf-8";
/*---------------サイトの基本設定---------------*/
/*cssのリセット*/
こちらはノーマライズするときは要らない html,
body,
div,
span,
object,
iframe,
h1,
h2,
h3,
h4,
h5,
h6,
p,
blockquote,
pre,
abbr,
address,
cite,
code,
del,
dfn,
em,
img,
ins,
kbd,
q,
samp,
small,
strong,
sub,
sup,
var,
b,
i,
dl,
dt,
dd,
ol,
ul,
li,
fieldset,
form,
label,
legend,
table,
caption,
tbody,
tfoot,
thead,
tr,
th,
td,
article,
aside,
canvas,
details,
figcaption,
figure,
footer,
header,
hgroup,
menu,
nav,
section,
summary,
time,
mark,
audio,
video {
font-size: 100%;
margin: 0;
padding: 0;
vertical-align: baseline;
border: 0;
outline: 0;
background: transparent;
}
/*html&bodyの設定*/
html {
font-size: 62.5%; /* 1rem = 10px */
overflow-y: scroll;
overflow-x: hidden;
}
body {
font-family: "YakuHanJPs_Noto", "Roboto", "Noto Sans JP", "游ゴシック Medium",
"游ゴシック体", "Yu Gothic Medium", "YuGothic", "ヒラギノ角ゴ ProN",
"Hiragino Kaku Gothic ProN", "メイリオ", "Meiryo", "MS Pゴシック",
"MS PGothic", sans-serif;
margin: 0;
padding: 0;
line-height: 1.8;
width: 100%;
height: 100%;
}
/* Box Sizing の設定 */
*,
*::before,
*::after {
box-sizing: border-box;
}
/* - - h1.h2.h3.... - - */
h1,
h2,
h3,
h4,
h5,
h6 {
font-weight: bold;
color: #000;
overflow-wrap: break-word;
}
/* -- a -- */
a {
text-decoration: none;
outline: none;
color: #000;
}
a,
a > img {
-webkit-transition: 0.2s;
-moz-transition: 0.2s;
-ms-transition: 0.2s;
-o-transition: 0.2s;
transition: 0.2s;
}
/* -- img -- */
img {
display: block;
max-width: 100%;
height: auto;
}
/* -- ul -- */
ul {
list-style: none;
}
li {
list-style: none;
}
/* -- :hover -- */
a:hover,
button:hover,
input[type="button"]:hover,
input[type="submit"]:hover,
input[type="reset"]:hover {
cursor: pointer;
}
/* -- inputの設定 --*/
input[type="text"] {
font-size: 1rem;
}
input[type="submit"] {
padding: 8px;
border: #efefef;
color: #000;
background-color: aliceblue;
}
/*-- フォーム要素の設定 --*/
button,
input,
select,
textarea {
font-family: inherit;
font-size: 100%;
margin: 0;
}
button {
border: none;
background: none;
padding: 0;
cursor: pointer;
}
/*--テーブルのborder-collapse*/
table {
border-collapse: collapse;
border-spacing: 0;
}
style.css
@charset "utf-8";
/*---------------rootの基本設定---------------*/
:root {
/* カラーパレット */
--primary-color: #3498db;
--secondary-color: #2ecc71;
--bg-beige: #f3f0e8;
--text-color: #333;
--white--: #ffffff;
--gold--: #b49f68;
--black--: #000000;
--footer-bg: #222222;
/* フォントサイズ */
--font-small: 12px; /* 12px */
--font-medium: 16px; /* 16px */
--font-large: 20px; /* 20px */
/* スペーシング */
--spacing-small: 8px;
--spacing-medium: 16px;
--spacing-large: 24px;
}
/*---------------設定終了---------------*/
/*---------------デバイス別表示・非表示---------------*/
/* PC専用(769px以上で表示) */
.pc-only {
display: block;
}
@media screen and (max-width: 768px) {
.pc-only {
display: none !important;
}
}
/* タブレット専用(768px〜1024px) */
.tablet-only {
display: none;
}
@media screen and (min-width: 768px) and (max-width: 1024px) {
.tablet-only {
display: block;
}
}
/* スマホ専用(500px以下で表示) */
.sp-only {
display: none;
}
@media screen and (max-width: 500px) {
.sp-only {
display: block !important;
}
}
/* モバイル専用(768px以下で表示:タブレット+スマホ) */
.mobile-only {
display: none;
}
@media screen and (max-width: 768px) {
.mobile-only {
display: block !important;
}
}
/*---------------デバイス別表示・非表示の設定終了---------------*/
/*---------------全体のフォント設定---------------*/
body {
font-family: "Noto Serif JP", "Helvetica Neue", Arial, sans-serif;
}
/*---------------全体のフォント設定終了---------------*/
header.css
@charset "utf-8";
/*---------------headerの設定-------------------------------*/
#header {
background-color: var(--white--);
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
position: fixed;
top: 0;
width: 100%;
z-index: 999;
}
.header_inner {
width: 100%;
height: 70px;
margin-inline: auto;
padding-block: min(0.69vw, 10px);
padding-inline: min(1.39vw, 20px);
display: flex;
justify-content: space-between;
align-items: center;
}
.header_logo img {
width: 100%;
}
.header_nav {
display: flex;
align-items: center;
}
.header_nav ul {
list-style: none;
display: flex;
gap: min(1.39vw, 20px);
margin-right: min(1.39vw, 20px);
padding: 0;
}
.header_nav ul li a {
text-decoration: none;
color: var(--text-color);
font-size: min(1.11vw, 16px);
font-weight: 500;
}
.header_nav ul li a:hover {
color: var(--primary-color);
}
.header_btn .btn_basic {
background-color: var(--gold--);
color: var(--white--);
font-size: min(1.11vw, 16px);
padding-block: min(0.69vw, 10px);
padding-inline: min(1.39vw, 20px);
text-decoration: none;
border-radius: 5px;
font-weight: 600;
}
.header_btn .btn_basic:hover {
background-color: var(--black--);
}
/*---------------headerの設定終了-------------------------------*/
ここからがこの記事のメインのcssコード
@charset "utf-8";
/*---------------カルーセル2の設定-----------------------*/
/* PC時のみ3枚表示(中央だけ目立つ) */
.carousel_section_secondary {
width: 100%;
margin-block: 100px;
/* 必要に応じてmin-heightを調整 */
}
.section_inner_secondary {
width: 100%;
max-width: 1200px;
margin: 0 auto;
}
.section_title_secondary {
position: relative;
font-size: min(2.78vw, 40px);
font-weight: bold;
color: var(--text-color);
text-align: left;
margin-bottom: min(1.39vw, 20px);
padding-left: 15px;
}
.section_title_secondary::before {
content: "";
position: absolute;
top: 0;
left: 0;
width: 5px;
height: 100%;
background-color: var(--black--);
}
/* 基本レイアウト */
.custom-carousel_secondary {
position: relative;
left: 50%;
transform: translateX(-50%);
width: 100%;
max-width: 1200px; /* 親の幅を広げる */
margin: 0 auto;
padding: 0 0.5em;
overflow: hidden;
}
/* スライド領域 */
.carousel-slides_secondary {
position: relative;
width: 100%;
aspect-ratio: 16 / 8;
display: flex;
justify-content: center;
align-items: center;
}
/* スライド基本 */
.carousel-slide_secondary {
position: absolute;
top: 50%;
left: 50%;
width: 400px;
aspect-ratio: 16 / 8;
transform: translate(-50%, -50%) scale(0.7);
opacity: 0;
z-index: 1;
transition: transform 0.5s cubic-bezier(0.77, 0, 0.175, 1),
opacity 0.5s cubic-bezier(0.77, 0, 0.175, 1);
pointer-events: none;
}
.carousel-slide_secondary.active {
transform: translate(-50%, -50%) scale(1);
opacity: 1;
z-index: 3;
width: 800px;
aspect-ratio: 5 / 3;
pointer-events: auto;
}
.carousel-slide_secondary img {
width: 100%;
height: 100%;
object-fit: cover;
position: relative;
border-radius: 8px;
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
z-index: 0;
}
/* active, prev, next以外は非表示 */
.carousel-slide_secondary:not(.active):not(.prev):not(.next) {
opacity: 0;
pointer-events: none;
z-index: 1;
}
.carousel-slide_secondary.prev {
transform: translate(-180%, -50%) scale(0.85); /*通常は-150%*/
opacity: 0.7;
z-index: 2;
pointer-events: auto;
width: 300px;
aspect-ratio: 5 / 3;
}
.carousel-slide_secondary.next {
transform: translate(80%, -50%) scale(0.85); /*通常は50%*/
opacity: 0.7;
z-index: 2;
pointer-events: auto;
width: 300px;
aspect-ratio: 5 / 3;
}
/* ボタン */
.carousel-prev_secondary,
.carousel-next_secondary {
position: absolute;
top: 50%;
transform: translateY(-50%);
background: rgba(0, 0, 0, 0.3);
color: #fff;
border: none;
font-size: 2em;
padding: 0.2em 0.6em;
cursor: pointer;
z-index: 3;
}
.carousel-prev_secondary {
left: 10px;
}
.carousel-next_secondary {
right: 10px;
}
/* ページネーション */
.carousel-pagination_secondary {
position: absolute;
left: 50%;
bottom: 15px;
transform: translateX(-50%);
display: flex;
gap: 8px;
z-index: 3;
}
.carousel-dot_secondary {
width: 12px;
height: 12px;
border-radius: 50%;
background: #fff;
opacity: 0.5;
cursor: pointer;
border: 1px solid #888;
transition: opacity 0.3s;
}
.carousel-dot_secondary.active {
opacity: 1;
background: #333;
}
/* レスポンシブ max-width */
@media screen and (max-width: 1300px) {
.section_inner_secondary {
width: 100%;
max-width: 900px;
margin: 0 auto;
}
.carousel-slide_secondary.active {
width: 600px;
}
.carousel-slide_secondary.prev {
transform: translate(-190%, -50%) scale(0.85); /*通常は-150%*/
width: 200px;
aspect-ratio: 5 / 3;
}
.carousel-slide_secondary.next {
transform: translate(90%, -50%) scale(0.85); /*通常は50%*/
width: 200px;
aspect-ratio: 5 / 3;
}
}
/* iPadサイズ(600px~899px)で2枚表示 */
@media (min-width: 600px) and (max-width: 1022px) {
.carousel-slides_secondary {
position: relative;
aspect-ratio: 16 / 8;
}
.carousel-slide_secondary {
position: absolute;
top: 50%;
left: 50%;
width: 320px;
aspect-ratio: 16 / 11;
opacity: 0;
z-index: 1;
pointer-events: none;
transition: transform 0.7s cubic-bezier(0.77, 0, 0.175, 1),
opacity 0.7s cubic-bezier(0.77, 0, 0.175, 1);
}
.carousel-slide_secondary.active {
width: 320px;
transform: translate(-100%, -50%) scale(1);
opacity: 1;
z-index: 3;
pointer-events: auto;
}
.carousel-slide_secondary.next {
width: 320px;
transform: translate(0%, -50%) scale(1);
opacity: 1;
z-index: 2;
pointer-events: auto;
}
.carousel-slide_secondary.prev,
.carousel-slide_secondary:not(.active):not(.next) {
opacity: 0;
pointer-events: none;
z-index: 1;
display: none;
}
.carousel-slide_secondary img {
width: 100%;
height: 100%;
border-radius: 8px;
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
}
}
@media screen and (max-width: 768px) {
.carousel_section_secondary {
margin-block: 50px;
/* 必要に応じてmin-heightを調整 */
}
.section_inner_secondary {
width: 100%;
margin: 0 auto;
padding-inline: 10px;
}
.custom-carousel_secondary {
margin-top: 20px;
}
.carousel-dot_secondary {
width: 15px;
height: 15px;
}
}
/* スマホは1枚だけ表示 */
@media (max-width: 600px) {
.carousel-slide_secondary {
position: absolute;
top: 0;
left: 0;
width: 100%;
aspect-ratio: 16 / 8;
opacity: 0;
z-index: 1;
pointer-events: none;
transition: opacity 1s ease-in-out;
}
.carousel-slide_secondary.active {
transform: none;
opacity: 1;
z-index: 2;
width: 100%;
aspect-ratio: 16 / 8;
pointer-events: auto;
}
.carousel-slide_secondary.prev,
.carousel-slide_secondary.next,
.carousel-slide_secondary:not(.active) {
opacity: 0;
pointer-events: none;
z-index: 1;
}
.carousel-prev_secondary,
.carousel-next_secondary {
top: 50%;
transform: translateY(-50%);
}
}
@media (max-width: 500px) {
.carousel-prev_secondary,
.carousel-next_secondary {
font-size: 1.2em;
padding: 0.3em 0.4em;
}
}
JSを使ってJSコード作成
STEP3 JSコード
document.addEventListener("DOMContentLoaded", function () {
const slides = document.querySelectorAll(".carousel-slide_secondary");
const prevBtn = document.querySelector(".carousel-prev_secondary");
const nextBtn = document.querySelector(".carousel-next_secondary");
const pagination = document.querySelector(".carousel-pagination_secondary");
let current = 0;
let timer;
// ページネーション生成
if (pagination) {
slides.forEach((_, i) => {
const dot = document.createElement("span");
dot.className = "carousel-dot_secondary" + (i === 0 ? " active" : "");
dot.addEventListener("click", function () {
current = i;
showSlide(current);
stopAuto();
startAuto();
});
pagination.appendChild(dot);
});
}
function updatePagination(idx) {
const dots = document.querySelectorAll(".carousel-dot_secondary");
dots.forEach((dot, i) => {
dot.classList.toggle("active", i === idx);
});
}
function showSlide(idx) {
slides.forEach((slide, i) => {
slide.classList.remove("active", "prev", "next");
if (i === idx) {
slide.classList.add("active");
} else if (i === (idx - 1 + slides.length) % slides.length) {
slide.classList.add("prev");
} else if (i === (idx + 1) % slides.length) {
slide.classList.add("next");
}
});
updatePagination(idx);
}
function nextSlide() {
current = (current + 1) % slides.length;
showSlide(current);
}
function prevSlide() {
current = (current - 1 + slides.length) % slides.length;
showSlide(current);
}
function startAuto() {
timer = setInterval(nextSlide, 4000);
}
function stopAuto() {
clearInterval(timer);
}
if (prevBtn && nextBtn) {
prevBtn.addEventListener("click", function () {
prevSlide();
stopAuto();
startAuto();
});
nextBtn.addEventListener("click", function () {
nextSlide();
stopAuto();
startAuto();
});
}
// 画像にマウス・タッチで自動再生停止
slides.forEach((slide) => {
slide.addEventListener("mouseenter", stopAuto);
slide.addEventListener("mouseleave", startAuto);
slide.addEventListener("touchstart", stopAuto, { passive: true });
slide.addEventListener("touchend", startAuto, { passive: true });
});
// スワイプで次/前
let startX = null;
slides.forEach((slide) => {
slide.addEventListener(
"touchstart",
function (e) {
startX = e.touches[0].clientX;
},
{ passive: true }
);
slide.addEventListener(
"touchend",
function (e) {
if (startX === null) return;
let endX = e.changedTouches[0].clientX;
if (endX - startX > 50) {
prevSlide();
stopAuto();
startAuto();
} else if (startX - endX > 50) {
nextSlide();
stopAuto();
startAuto();
}
startX = null;
},
{ passive: true }
);
});
showSlide(current);
startAuto();
});
コチラのサイトはコチラから
