
Sassでクロスフェードのスライドアニメーションを実装する
最近、Sassを使っていろんな機能を実装するケースが増えてきたので備忘録的にメモを残しておきたいと思います。今回はクロスフェードで複数の画像が切り替わるスライドショーをSassで作成していきます。
ギャラリーサイトやヒーローヘッダーなどを採用したサイトでよく見かけますね、特にフルスクリーンで表示されるパターンが多いようで、今回はその形でサンプルを作成して見ました。このような機能は、以前まではjavascript、特にjQueryを使って実装するケースが一般的でしたが、最近ではCSSのみで表現できるようになってきました。
ただ、コード自体が複雑で分かりにくかったり、長くなりすぎて書きにくかったりという問題がありましたが、Sassの登場によりスッキリと記述できるようになったことで、かなり実装しやすくなったのではないでしょうか。
今回はこちら「Ken Burns Effect fullscreen without js」(A Pen By Nicola Pressi)のサンプルを参考に、設定項目を変数化していろんな案件で使いまわしやすいようにアレンジしてみました。
まずはHTMLを組んでいきます。構造自体はシンプルで、ラッパー要素となる親要素で画像が表示される子要素を囲んでいます。
【HTML】※一部抜粋
<div class="bg-crossfade-wrap"> <div class="bg-crossfade-img"> </div> <div class="bg-crossfade-img"> </div> <div class="bg-crossfade-img"> </div> <div class="bg-crossfade-img"> </div> </div>そしてSass(SCSS)で動きの部分を実装していきます。今回は複数の画像を表示させる順番に重ねて、時間差で表示非表示を繰り返すことでクロスフェードの表現を実装しています。ソースコードはこちらになります。 【CSS(SCSS)】
// config
$image-count: 4;
$time-delay: 3s;
$time-duration: 1s;
$time-total: ($time-delay * $image-count);
// image src
$images: (
'1': bg-image01,
'2': bg-image02,
'3': bg-image03,
'4': bg-image04
);
// mixin
@mixin background-config {
background-repeat: no-repeat;
background-position: center center;
background-size: cover;
}
@mixin animation-config {
animation-name: bg-crossfade;
animation-duration: $time-total;
animation-timing-function: linear;
animation-delay: 0s;
animation-iteration-count: infinite;
animation-direction: normal;
}
// animation
@for $i from 1 through $image-count {
@keyframes bg-crossfade-#{$i} {
$delay-rate: percentage($time-delay / $time-total);
$duration-rate: percentage($time-duration / $time-total);
$case-1: ($delay-rate * ($i - 1) - $duration-rate / 2);
$case-2: ($delay-rate * ($i - 1) + $duration-rate / 2);
$case-3: ($delay-rate * ($i) - $duration-rate / 2);
$case-4: ($delay-rate * ($i) + $duration-rate / 2);
$case-5: (100% - $duration-rate / 2);
$case-6: (($case-4 - $case-1) * 100% / $case-5);
@if ($case-1 < 0%) {
$case-1: 0%;
}
@if ($case-2 < 0%) {
$case-2: 0%;
}
@if ($case-3 > 100%) {
$case-3: 100%;
}
@if ($case-4 > 100%) {
$case-4: 100%;
}
#{$case-1} {
opacity: 1;
}
#{$case-2} {
opacity: 1;
}
#{$case-3} {
opacity: 1;
}
#{$case-4} {
opacity: 0;
}
@if ($i != $image-count) {
100% {
opacity: 0;
}
}
@if ($i == 1) {
#{$case-5} {
opacity: 0;
}
100% {
opacity: 1;
}
}
}
}
// style
.bg-crossfade-wrap {
width: 100%;
height: 100vh;
position: relative;
overflow: hidden;
z-index: -1;
.bg-crossfade-img {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
@include background-config;
@include animation-config;
@for $i from 1 through $image-count {
&:nth-child(#{$i}) {
animation-name: bg-crossfade-#{$i};
z-index: ($image-count - $i);
}
}
@each $order, $image in $images {
&:nth-child(#{$order}) {
background-image: url(#{$image}.jpg);
}
}
}
}
少し長いのですが、まずは使用する画像の枚数や表示時間、アニメーションの切り替わり時間などを変数で管理できるようになっています。そして、使用する画像のファイル名も合わせて表示させる順番に登録する形になります。この時にインデックスとなる番号も合わせて入れることになります。
そして、背景画像とアニメーションのプロパティをmixinで登録しておきます。あまり変えることはないかもしれませんが、アレンジするときに便利ですね。
そして今回のポイントになるキーフレームを登録していきます。ここでSassの機能である「@for」で繰り返しの処理を行うことで、各画像用に個別のキーフレームを作成することができます。その中で、キーフレームの位置を並び順の画像ごとに動的に出力させることで、時間差でのアニメーションになるようになっているようです。
最後に各画像を重ねるように配置していきます。ここで、各画像の重なり順ですが、先ほどと同じく「@for」を使って画像の並び順で動的に変化させています。そして、「@each in」を使うことで背景画像も変数で登録した個別のものが充て振られるようになっています。
これでjavascriptを使わないでSassのみでクロスフェードのスライドアニメーションができました。今回のサンプルはこちらになります。
See the Pen crossfade animation on CSS by designsupply (@designsupply) on CodePen.
参考サイトではクロスフェードに加えて、拡大縮小のアニメーションがついたいわゆる「ケンバーンエフェクト」と呼ばれる効果が紹介されています。これもCSSのtransformプロパティを使うことでいろんなアレンジができそうですね。javascriptを使わないことで、処理の負担も減るかと思いますので軽量化を目指すケースでも相性がいいのではないでしょうか。 (参考にさせて頂いたサイト) Ken Burns Effect fullscreen without js Sass:eachやforを使って繰り返し記述する手間を省くcategories
- WordPress(61)
- JavaScript(49)
- Vue.js(48)
- CSS(46)
- jQuery(34)
- Nuxt.js(22)
- Sass(21)
- Gulp(17)
- webpack(16)
- PHP(14)
- HTML(14)
- GSAP(11)
- React(10)
- Vite(9)
- Pug(9)
- Laravel(8)
- Cordova(8)
- Linux(7)
- Next.js(6)
- Apache(5)
- Shopify(4)
- REST API(4)
- Node.js(4)
- Smarty(3)
- Git(3)
- JSON(3)
- その他プログラミング(3)
- Google Apps API(3)
- Bootstrap(3)
- 環境構築・システム(3)
- TypeScript(2)
- EJS(2)
- RMS(2)
- Docker(2)
- Instagram API(2)
- Excel VBA(2)
- SVG(1)
- Dart(1)
- ECカートASP(1)
- Markdown(1)
- AMP(1)
- Nginx(1)
- XML(1)
- shellscript(1)
- Ruby(1)
- MySQL(1)