pagetop

BLOG

左右無限ループをcssで版とjquery版を検証してみた

  • HOME

  • BLOG

  • 左右無限ループをcssで版とjquery版を検証してみた

Article

左右無限ループをcssで版とjquery版を検証してみた

左右無限ループをcssで版とjquery版を検証してみた

クライアントからのリクエストがあり、イメージを左右に無限ループするギミックを検証してみました。

過去にも実績はあるのですが、今回もう少し入り込んで、jquery版とcss版でどちらが最適か考察してみました。

 

今回の要件

  • 複数のイメージが右から左にループスライド
  • イメージにhoverアクション実装
  • イメージにゆっくり揺れるアニメーションを実装

チェックポイント

以下のチェックポイントを基準に検証してみました。

  • 実装しやすいか
  • 拡張しやすいか
  • レスポンシブルへの対応

 

cssでループを実装してみる

まずはCSSのみで実装してみました。以下のようなイメージになります。

cssでループを実装してみる

では、cssをみてみます。

css

.loop_bnr {
position: relative;
display: -webkit-flex;
display: flex;
-webkit-flex-flow: row nowrap;
flex-flow: row nowrap;
width: 100vw;
overflow: hidden;
}

.loop_bnr ul {
display: -webkit-flex;
display: flex;
-webkit-flex-flow: row nowrap;
flex-flow: row nowrap;
width: 100%;
margin: 0;
padding: 0;
position: relative;
}

.loop_bnr li {
display: inline-block;
width: calc(100vw / 2);
margin: 0px 20px;
list-style: none;
text-align: center;
position: relative;
cursor: pointer;
top:20px;
height:400px;
}

.loop_bnr li:nth-child(2n){
top:80px;
}
.loop_bnr li:nth-of-type(5),
.loop_bnr li:nth-of-type(6),
.loop_bnr li:nth-of-type(7),
.loop_bnr li:nth-of-type(8){
display:none;
}
.loop_bnr .inner_box{
position:absolute;
top:0;
left:0;
width:300px;
height:300px;
}
.loop_bnr img {
max-width: 100%;
height: auto;
border-radius:20px;
filter: grayscale(0);
transition-duration: 0.5s;
}
.loopslide_text {
width:100%;
height:100%;
position: absolute;
top: 0%;
left: 0%;
transition-duration: 0.5s;
opacity:0;
}
.loopslide_text_body {
padding:0px;
}
.loopslide_text_body>h4 {
font-size: 20px;
color: #ffffff;
}
.loopslide_text_body>p {
font-size: 16px;
color: #ffffff;
padding:10px;
}
.loop_bnr li:hover .loopslide_text{
opacity:1;
border-radius:20px;
background: rgba(0, 0, 0, 0.5);
}
.loop_bnr li:hover img{
filter: grayscale(100%);
transition-duration: 0.5s;
}
.loop_bnr ul {
-webkit-animation: loop 50s -25s linear infinite;
animation: loop 50s -25s linear infinite;
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
will-change: transform;
}

.loop_bnr ul + ul {
-webkit-animation: loop2 50s linear infinite;
animation: loop2 50s linear infinite;
}

.loop_bnr:hover ul {
animation-play-state: paused;
}

.loop_bnr li.yureru{
transform-origin: center bottom;
animation: yurayura1 10s linear infinite;
}
@keyframes yurayura1 {
0% , 100%{
transform: rotate(2deg);
}
50%{
transform: rotate(-2deg);
}
}

.loop_bnr li:nth-child(2n).yureru{
transform-origin: center bottom;
animation: yurayura2 10s linear infinite;
}

@keyframes yurayura2 {
0% , 100%{
transform: rotate(-2deg);
}
50%{
transform: rotate(2deg);
}
}

display: flex;とflex-flow: row nowrapで横並びにします。イメージのマージンはwidth: calc(100vw / 2)でコントロールします。.loop_bnr liをhoverすることで隠れていたテキストが表示され、イメージがモノクロになります。

ループアニメーションは以下で設定しています。

.loop_bnr ul {
-webkit-animation: loop 50s -25s linear infinite;
animation: loop 50s -25s linear infinite;
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
will-change: transform;
}

.loop_bnr ul + ul {
-webkit-animation: loop2 50s linear infinite;
animation: loop2 50s linear infinite;
}

.loop_bnr ul + ulてとこなんか変ですよね….
これはHTMLでわかるのですが、.loop_bnr内にulが2ブロックあり、イメージ名1〜4までを記述し、その後に5〜8までを記述します。
つまり最初のulに遅れて次のulがスライドしてくるというタイムラグアニメーションです。

.loop_bnr:hover ul {
animation-play-state: paused;
}

上記では、ulエリアをhoverした際アニメーションが止まります。

揺れるアニメーションはjquery版と同じで.yureruに設定しています。

html

<div class="loop_bnr">
<ul>
<li class="yureru">
<div class="inner_box">
<img src="img/slide1.jpg" alt="">
<div class="loopslide_text">
<div class="loopslide_text_body">
<h4>No.1</h4><p data-truncation="3">Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. </p>
</div>
</div>
</div>
</li>

<li class="yureru">
<div class="inner_box">
<img src="img/slide2.jpg" alt=""><div class="loopslide_text">
<div class="loopslide_text_body">
<h4>No.2</h4><p data-truncation="3">Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. </p>
</div>
</div>
</div>
</li>
<li class="yureru">
<div class="inner_box">
<img src="img/slide3.jpg" alt=""><div class="loopslide_text">
<div class="loopslide_text_body">
<h4>No.3</h4><p data-truncation="3">Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. </p>
</div>
</div>
</div>
</li>
<li class="yureru">
<div class="inner_box">
<img src="img/slide4.jpg" alt=""><div class="loopslide_text">
<div class="loopslide_text_body">
<h4>No.4</h4><p data-truncation="3">Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. </p>
</div>
</div>
</div>
</li>

中略

<li class="yureru">
<div class="inner_box">
<img src="img/slide8.jpg" alt=""><div class="loopslide_text">
<div class="loopslide_text_body">
<h4>No.8</h4><p data-truncation="3">Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. </p>
</div>
</div>
</div>
</li>

</ul>
<ul>
<li class="yureru">
<div class="inner_box">
<img src="img/slide5.jpg" alt=""><div class="loopslide_text">
<div class="loopslide_text_body">
<h4>No.5</h4><p data-truncation="3">Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. </p>
</div>
</div>
</div>
</li>
<li class="yureru">
<div class="inner_box">
<img src="img/slide6.jpg" alt=""><div class="loopslide_text">
<div class="loopslide_text_body">
<h4>No.6</h4><p data-truncation="3">Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. </p>
</div>
</div>
</div>
</li>
<li class="yureru">
<div class="inner_box">
<img src="img/slide7.jpg" alt=""><div class="loopslide_text">
<div class="loopslide_text_body">
<h4>No.7</h4><p data-truncation="3">Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. </p>
</div>
</div>
</div>
</li>
<li class="yureru">
<div class="inner_box">
<img src="img/slide8.jpg" alt=""><div class="loopslide_text">
<div class="loopslide_text_body">
<h4>No.8</h4><p data-truncation="3">Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. </p>
</div>
</div>
</div>
</li>

</ul>
</div>

先に書いた通り、2つのulで動いています。
とここで以下のCSSの説明になります。

.loop_bnr li:nth-of-type(5),
.loop_bnr li:nth-of-type(6),
.loop_bnr li:nth-of-type(7),
.loop_bnr li:nth-of-type(8){
display:none;
}

わざわざこう書いたのはレスポンシブ対応のためです。正直、そのままでは崩れます。
検証してみたのですが、モバイルでループ処理自体が難しく、最適化させる早道はPCとモバイルではソースを分けることでした。(まあ未熟なのですが…)

そのため@media screenではdisplay:blockにし、.loop_bnr ul + ulはnoneにしました。加えて、display: flexではなくblockにし.loop_bnr liをfloatにしてループそのものをやめました。

まあモバイルでループというのもどうかな?て感じですが、最適化に多少手こずる結果になりました。

もう一つ。

ulが2つある状況がプログラムで生成する場合は、ちょっと不細工かなと..

ただ、数量とサイズのレギュレーションが明確で、固定ブロックとして利用するのであればjsがない分軽量であるとは思います。
また、アニメーションが止まる仕様のため、リンク要素があればいいと思いました。

 

jqueryでループを実装してみる

続いてjquery版をみてみます。

jqueryでループを実装してみる

jqueryを設定する

<script src='https://code.jquery.com/jquery-3.3.1.min.js'></script>

css

.wrapper {
overflow: hidden;
width: 100%;
}
.slider {
display: flex;
}
.slider__inner {
width: 100%;
margin:100px 0;
display: flex;
}
.reverse {
display: flex;
/*overflow: hidden;*/
width: 100%;
margin:100px 0;
}
.reverse__inner {
display: flex;
}

.slider__inner:first-child {
animation: loop 90s linear infinite;
}

.slider__inner:nth-child(2) {
animation: loop2 90s -60s linear infinite;
}

.slider__inner:last-child {
animation: loop3 90s -30s linear infinite;
}

@keyframes loop {
0% {
transform: translateX(200%);
}
to {
transform: translateX(-100%);
}
}

@keyframes loop2 {
0% {
transform: translateX(100%);
}
to {
transform: translateX(-200%);
}
}

@keyframes loop3 {
0% {
transform: translateX(0%);
}
to {
transform: translateX(-300%);
}
}

.reverse__inner:first-child {
animation: loop4 90s linear infinite;
}

.reverse__inner:nth-child(2) {
animation: loop5 90s -60s linear infinite;
}

.reverse__inner:last-child {
animation: loop6 90s -30s linear infinite;
}

@keyframes loop4 {
0% {
transform: translateX(-100%);
}
to {
transform: translateX(200%);
}
}

@keyframes loop5 {
0% {
transform: translateX(-200%);
}
to {
transform: translateX(100%);
}
}

@keyframes loop6 {
0% {
transform: translateX(-300%);
}
to {
transform: translateX(0%);
}
}

.slider__item{
position: relative;
}
.slider__item:nth-child(2n){
top:20px;
}
.loopslide_inner {
position: relative;
cursor: pointer;
margin:0 10px;
}
.loopslide_inner>img {
max-width: 100%;
height: auto;
filter: grayscale(0);
transition-duration: 0.5s;
border-radius:20px;
}
.loopslide_text {
width:100%;
height:98%;
position: absolute;
top: 0%;
left: 0%;
transition-duration: 0.5s;
opacity:0;
}
.loopslide_text_body {
padding:10px;
}
.loopslide_text_body>h4 {
font-size: 16px;
color: #ffffff;
}
.loopslide_text_body>p {
font-size: 14px;
color: #ffffff;
}
.loopslide_inner:hover .loopslide_text{
opacity:1;
background: rgba(0, 0, 0, 0.5);
border-radius:20px;
}
.loopslide_inner:hover img{
filter: grayscale(100%);
transition-duration: 0.5s;
}

.yureru{
transform-origin: center bottom;
animation: yurayura1 10s linear infinite;
}
@keyframes yurayura1 {
0% , 100%{
transform: rotate(2deg);
}
50%{
transform: rotate(-2deg);
}
}

.yureru:nth-child(2n){
transform-origin: center bottom;
animation: yurayura2 10s linear infinite;
}

@keyframes yurayura2 {
0% , 100%{
transform: rotate(-2deg);
}
50%{
transform: rotate(2deg);
}
}

css版と同様にflexで横並びにします。

.slider__innerで右から左に、.reverse__innerは左から右にイメージがループします。

また、css版と同様にタイムラグアニメーションを以下で設定しています。

.slider__inner:first-child {
animation: loop 90s linear infinite;
}

.slider__inner:nth-child(2) {
animation: loop2 90s -60s linear infinite;
}

.slider__inner:last-child {
animation: loop3 90s -30s linear infinite;
}

@keyframes loop {
0% {
transform: translateX(200%);
}
to {
transform: translateX(-100%);
}
}

@keyframes loop2 {
0% {
transform: translateX(100%);
}
to {
transform: translateX(-200%);
}
}

@keyframes loop3 {
0% {
transform: translateX(0%);
}
to {
transform: translateX(-300%);
}
}

その他の設定は大体CSS版と同様ですが、ulが2ブロックあるような設定はありません。

html

<div class="slider">
<div class="slider__inner">

<div class="slider__item yureru">
<div class="loopslide_inner">
<img src="img/slide1.jpg" alt="" width="300">
<div class="loopslide_text">
<div class="loopslide_text_body">
<h4>No.1</h4><p data-truncation="3">Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. </p>
</div>
</div>
</div>
</div>

中略

<div class="slider__item yureru">
<div class="loopslide_inner">
<img src="img/slide7.jpg" alt="" width="300">
<div class="loopslide_text">
<div class="loopslide_text_body">
<h4>No.7</h4><p data-truncation="3">Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. </p>
</div>
</div>
</div>
</div>

<div class="slider__item yureru">
<div class="loopslide_inner">
<img src="img/slide8.jpg" alt="" width="300">
<div class="loopslide_text">
<div class="loopslide_text_body">
<h4>No.8</h4><p data-truncation="3">Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. </p>
</div>
</div>
</div>
</div>


</div>
</div>

上記は.slider__innerのみのソースです。見てわかる通り、1ブロック内に全てのイメージが挿入されます。プログラムの生成には向いてると言えます。

javascript

jQuery(function($){
$('.slider__inner').each(function(){
var sliderWidth = $(this).width();
$(this).clone(true).insertBefore(this);
$(this).clone(true).insertAfter(this);

$('.slider').css('width', sliderWidth*5);
});
$('.reverse__inner').each(function(){
var sliderWidth = $(this).width();
$(this).clone(true).insertBefore(this);
$(this).clone(true).insertAfter(this);

$('.reverse').css('width', sliderWidth*2);
});
});

対象セレクタを以下で設定します。

$('.slider__inner').each(function(){

イメージの数に応じて表示サイズのコントロールは以下で設定します。

$('.slider').css('width', sliderWidth*5);

ここちょっと面倒ですが、数が増えた場合そのままの数値(*5部分)だとイメージサイズが相対的に小さくなります。このあたりが、プログラムとの親和性に少し面倒ですね。

また、このままではhoverでアニメーションが止まりません。

レスポンシブについては良いです!そのままのサイズで問題なければmadiaクエリを使用する必要はありません。

 

css版とjquery版のまとめ

実装しやすいか 拡張性があるか レスポンシブルへの対応
css版 ✖️ ✖️
jquery版

ということで、個人的にはjquery版がいいです。

ただし、自分のスキルとその他のテクニックを全て検証したわではなく、飽くまで個人的な感想です。

今後とも検証したいと思います。

 

css版のデモ

jquery版のデモ

Spread the love