左から・右から・真ん中から
画像が際立つ CSS アニメーションの紹介です。アイキャッチ画像や本文中の画像、ランディングページの画像など、いろいろな画像に使えます。
サンプルは、便宜上アニメーションの再生回数を無限にしています(提示している CSS のアニメーション回数は 1 回です)。
共通の HTML 。
<div class="img-wrap">
<img>
</div>
左から徐々に表示するアニメーション。
CSS 。
.img-wrap {
overflow: hidden;
position: relative;
}
.img-wrap:before {
animation: img-wrap 2s cubic-bezier(.4, 0, .2, 1) forwards;
background: #fff;
bottom: 0;
content: '';
left: 0;
pointer-events: none;
position: absolute;
right: 0;
top: 0;
z-index: 1;
}
@keyframes img-wrap {
100% {
transform: translateX(100%);
}
}
上記 CSS の translateX(100%)
を translateX(-100%)
と値をマイナスにすると、右から表示するアニメーションに。
CSS 。
.img-wrap {
overflow: hidden;
position: relative;
}
.img-wrap:before {
animation: img-wrap 2s cubic-bezier(.4, 0, .2, 1) forwards;
background: #fff;
bottom: 0;
content: '';
left: 0;
pointer-events: none;
position: absolute;
right: 0;
top: 0;
z-index: 1;
}
@keyframes img-wrap {
100% {
transform: translateX(-100%);
}
}
今度は画像の中心から、円形に広がるアニメーション(IE ではアニメーションしません)。
CSS 。
.img-wrap {
animation: img-wrap 2s cubic-bezier(.4, 0, .2, 1);
}
@keyframes img-wrap {
0% {
clip-path: circle(0 at 50% 50%);
-webkit-clip-path: circle(0 at 50% 50%);
}
100% {
clip-path: circle(100% at 50% 50%);
-webkit-clip-path: circle(100% at 50% 50%);
}
}
ただし、IE ではアニメーションは動かず、ただ普通に画像が表示されます。
また、clip-path
は GPU アクセラレーションで処理されないため、ブラウザに負荷をかける他、なめらかなアニメーションにならないデメリットがあります。
2 つの領域で異なるアニメーション
画像を 2 つの領域に分け、それぞれ異なるアニメーションにしてみます。HTML は、これまでのものと変わりません。
<div class="img-wrap">
<img>
</div>
画像の上部は左から、下部は右から表示するアニメーション。
CSS 。
.img-wrap {
overflow: hidden;
position: relative;
}
.img-wrap:before,
.img-wrap:after {
animation: 2s cubic-bezier(.4, 0, .2, 1) forwards;
background: #fff;
content: '';
left: 0;
pointer-events: none;
position: absolute;
right: 0;
z-index: 1;
}
.img-wrap:before {
animation-name: img-wrap-before;
top: 0;
bottom: 50%;
}
.img-wrap:after {
animation-name: img-wrap-after;
top: 50%;
bottom: 0;
}
@keyframes img-wrap-before {
100% {
transform: translateX(100%);
}
}
@keyframes img-wrap-after {
100% {
transform: translateX(-100%);
}
}
今度は画像の左側は上から、右側は下から表示するアニメーション。
CSS 。
.img-wrap {
overflow: hidden;
position: relative;
}
.img-wrap:before,
.img-wrap:after {
animation: 2s cubic-bezier(.4, 0, .2, 1) forwards;
background: #fff;
bottom: 0;
content: '';
pointer-events: none;
position: absolute;
top: 0;
z-index: 1;
}
.img-wrap:before {
animation-name: img-wrap-before;
left: 0;
right: 50%;
}
.img-wrap:after {
animation-name: img-wrap-after;
left: 50%;
right: 0;
}
@keyframes img-wrap-before {
100% {
transform: translateY(100%);
}
}
@keyframes img-wrap-after {
100% {
transform: translateY(-100%);
}
}
3 つ以上の領域で異なるアニメーション
<div> を使えば画像を 3 つ以上の領域に分け、それぞれ異なるアニメーションを指定できます。
HTML 。
<div class="img-wrap">
<div class="cover1"></div>
<div class="cover2"></div>
<div class="cover3"></div>
<img>
</div>
CSS 。
.img-wrap {
overflow: hidden;
position: relative;
}
.cover1,
.cover2,
.cover3 {
animation: cover 2s cubic-bezier(.4, 0, .2, 1) forwards;
background: #fff;
height: calc(100%/3);
left: 0;
pointer-events: none;
position: absolute;
right: 0;
z-index: 1;
}
.cover1 {
top: 0;
}
.cover2 {
animation-delay: .2s;
top: calc(100%/3);
}
.cover3 {
animation-delay: .4s;
top: calc(100%/3*2);
}
@keyframes cover {
100% {
transform: translateX(100%);
}
}
スクロールアニメーション
画像が画面内に入ると、アニメーションが始まります。画像が見えなくなるまでスクロールすれば、再度アニメーションをご確認いただけます。
HTML 。
<div class="img-wrap">
<img>
</div>
JavaScript 。
(function() {
const image = document.querySelectorAll('.img-wrap');
const observer = new IntersectionObserver(function(entries) {
entries.forEach(function(entry) {
if (entry.intersectionRatio > 0) {
entry.target.classList.add('img-animation');
} else {
entry.target.classList.remove('img-animation');
}
});
});
Array.prototype.forEach.call(image, function(img) {
observer.observe(img);
});
})();
CSS 。
.img-wrap {
opacity: 0;
}
.img-animation {
animation: img-opacity 2s cubic-bezier(.4, 0, .2, 1);
overflow: hidden;
position: relative;
}
.img-animation:before {
animation: img-animation 2s cubic-bezier(.4, 0, .2, 1) forwards;
background: #fff;
bottom: 0;
content: '';
left: 0;
pointer-events: none;
position: absolute;
right: 0;
top: 0;
z-index: 1;
}
@keyframes img-opacity {
100% {
opacity: 1;
}
}
@keyframes img-animation {
100% {
transform: translateX(100%);
}
}