<div class="carousel-02">
<div class="carousel-02__items" id="js-carousel-02-items">
<ul>
<li><a class="carousel-02__item" href="#">
<div class="carousel-02__item-img"><img src="https://picsum.photos/id/1001/400/400" width="400" height="400" alt="" /></div>
<p class="carousel-02__item-date">2021/01/01</p>
<p class="carousel-02__item-text">テキストが入ります。テキストが入ります。テキストが入ります。テキストが入ります。</p>
</a></li>
<li><a class="carousel-02__item" href="#">
<div class="carousel-02__item-img"><img src="https://picsum.photos/id/1002/400/400" width="400" height="400" alt="" /></div>
<p class="carousel-02__item-date">2021/01/02</p>
<p class="carousel-02__item-text">テキストが入ります。テキストが入ります。テキストが入ります。テキストが入ります。</p>
</a></li>
<li><a class="carousel-02__item" href="#">
<div class="carousel-02__item-img"><img src="https://picsum.photos/id/1003/400/400" width="400" height="400" alt="" /></div>
<p class="carousel-02__item-date">2021/01/03</p>
<p class="carousel-02__item-text">テキストが入ります。テキストが入ります。テキストが入ります。テキストが入ります。</p>
</a></li>
<li><a class="carousel-02__item" href="#">
<div class="carousel-02__item-img"><img src="https://picsum.photos/id/1004/400/400" width="400" height="400" alt="" /></div>
<p class="carousel-02__item-date">2021/01/04</p>
<p class="carousel-02__item-text">テキストが入ります。テキストが入ります。テキストが入ります。テキストが入ります。</p>
</a></li>
<li><a class="carousel-02__item" href="#">
<div class="carousel-02__item-img"><img src="https://picsum.photos/id/1005/400/400" width="400" height="400" alt="" /></div>
<p class="carousel-02__item-date">2021/01/05</p>
<p class="carousel-02__item-text">テキストが入ります。テキストが入ります。テキストが入ります。テキストが入ります。</p>
</a></li>
</ul>
</div>
<div class="carousel-02__foot">
<div class="carousel-02__buttons"><a class="carousel-02__button carousel-02__button--prev" id="js-carousel-02-button-prev" href="#"><</a><a class="carousel-02__button carousel-02__button--next" id="js-carousel-02-button-next" href="#">></a></div>
<div class="carousel-02__indicator-base">
<div class="carousel-02__indicator" id="js-carousel-02-indicator"></div>
</div>
</div>
</div>
.carousel-02
.carousel-02__items#js-carousel-02-items
ul
each item in items
li
a.carousel-02__item(href=item.link)
.carousel-02__item-img
img(src=item.img, width=item.width, height=item.height alt='')
p.carousel-02__item-date #{ item.date }
p.carousel-02__item-text #{ item.text }
.carousel-02__foot
.carousel-02__buttons
a.carousel-02__button.carousel-02__button--prev#js-carousel-02-button-prev(href='#') <
a.carousel-02__button.carousel-02__button--next#js-carousel-02-button-next(href='#') >
.carousel-02__indicator-base
.carousel-02__indicator#js-carousel-02-indicator
{
"items": [
{
"link": "#",
"img": "https://picsum.photos/id/1001/400/400",
"width": 400,
"height": 400,
"date": "2021/01/01",
"text": "テキストが入ります。テキストが入ります。テキストが入ります。テキストが入ります。"
},
{
"link": "#",
"img": "https://picsum.photos/id/1002/400/400",
"width": 400,
"height": 400,
"date": "2021/01/02",
"text": "テキストが入ります。テキストが入ります。テキストが入ります。テキストが入ります。"
},
{
"link": "#",
"img": "https://picsum.photos/id/1003/400/400",
"width": 400,
"height": 400,
"date": "2021/01/03",
"text": "テキストが入ります。テキストが入ります。テキストが入ります。テキストが入ります。"
},
{
"link": "#",
"img": "https://picsum.photos/id/1004/400/400",
"width": 400,
"height": 400,
"date": "2021/01/04",
"text": "テキストが入ります。テキストが入ります。テキストが入ります。テキストが入ります。"
},
{
"link": "#",
"img": "https://picsum.photos/id/1005/400/400",
"width": 400,
"height": 400,
"date": "2021/01/05",
"text": "テキストが入ります。テキストが入ります。テキストが入ります。テキストが入ります。"
}
]
}
$BLOCK_NAME: '.carousel-02';
// 変数
$color_primary: #800000;
$color_text: #333;
$color_bg: #fafafa;
$color_line: rgba(0, 0, 0, 0.12);
#{ $BLOCK_NAME } {
position: relative;
width: 600px;
padding: 24px;
overflow: hidden;
background: $color_bg;
// スライダーの左側を隠す目的で疑似要素配置
&::after {
position: absolute;
top: 0;
right: 100%;
bottom: 0;
left: -100%;
content: '';
background: $color_bg;
}
&__items {
margin: 0 -8px;
.slick-list {
overflow: visible;
}
}
&__item {
display: block;
padding: 0 8px;
}
&__item-img {
& > img {
width: 100%;
}
}
&__item-date {
padding-top: 15px;
font-size: 11px;
font-weight: bold;
color: $color_primary;
}
&__item-text {
padding-top: 7px;
font-size: 13px;
line-height: 1.5;
color: $color_text;
}
&__foot {
display: flex;
align-items: center;
margin-top: 12px;
}
&__buttons {
display: flex;
flex-shrink: 0;
margin-right: 24px;
}
&__button {
display: flex;
align-items: center;
justify-content: center;
width: 48px;
height: 48px;
color: $color_primary;
background: #fff;
&.is-disable {
color: #ddd;
}
}
&__indicator-base {
position: relative;
width: 100%;
height: 2px;
background: $color_line;
}
&__indicator {
position: absolute;
top: 0;
bottom: 0;
left: 0;
background: $color_primary;
transition: width 0.5s;
}
}
import $ from 'jquery';
import 'slick-carousel';
export const carousel02 = () => {
$(function() {
const carousel = new Carousel02();
carousel.init();
});
}
class Carousel02 {
$carousel: JQuery;
$btnPrev: JQuery;
$btnNext: JQuery;
$indicator: JQuery;
slickOpt: Object;
slidesNum: number;
constructor() {
this.$carousel = $('#js-carousel-02-items ul');
this.$btnPrev = $('#js-carousel-02-button-prev');
this.$btnNext = $('#js-carousel-02-button-next');
this.$indicator = $('#js-carousel-02-indicator');
this.slidesNum = 2;
this.slickOpt = {
autoplaySpeed: 3000,
arrows: false,
dots: false,
infinite: false,
slidesToShow: this.slidesNum,
};
}
/**
* 初期化
*/
init(): void {
this.initHandler();
this.btnHandler();
this.changeHandler();
// カルーセルの実行
// @ts-ignore
this.$carousel.slick(this.slickOpt);
}
/**
* ボタンのスタイル設定
* @param total カルーセル要素の総数
* @param next 次のカルーセルの番号
*/
setBtnStyle(total: number, next: number): void {
// 前へボタンのスタイル
if (next === 1) {
this.$btnPrev.addClass('is-disable');
} else {
this.$btnPrev.removeClass('is-disable');
}
// 次へボタンのスタイル
if (next === (total - this.slidesNum + 1)) {
this.$btnNext.addClass('is-disable');
} else {
this.$btnNext.removeClass('is-disable');
}
}
/**
* インジケーターのスタイル設定
* @param total カルーセル要素の総数
* @param next 次のカルーセルの番号
*/
setIndicatorStyle(total: number, next: number): void {
const percent = next / (total - this.slidesNum + 1) * 100;
this.$indicator.width(`${percent}%`);
}
/**
* ボタンクリック時の挙動
*/
btnHandler(): void {
// 前へボタンクリック時
this.$btnPrev.on('click', e => {
e.preventDefault();
// @ts-ignore
this.$carousel.slick('slickPrev');
});
// 次へボタンクリック時
this.$btnNext.on('click', e => {
e.preventDefault();
// @ts-ignore
this.$carousel.slick('slickNext');
});
}
/**
* カルーセル構築時の挙動
*/
initHandler(): void {
this.$carousel.on('init reInit', (e, slick) => {
const total = slick.slideCount;
this.setBtnStyle(total, 1);
this.setIndicatorStyle(total, 1);
});
}
/**
* カルーセル変更時の挙動
*/
changeHandler(): void {
this.$carousel.on('beforeChange', (e, slick, current, next) => {
const total = slick.slideCount;
this.setBtnStyle(total, next + 1);
this.setIndicatorStyle(total, next + 1);
});
}
}