Jqueryでパララックス画像を自作する方法
お疲れ様です。
パララックス画像、WEB制作学習中の自分からするとスタイリッシュで憧れます。
スクロールすると、スクロール量に応じて特定の画像だけが上向きに動く、というものになります。
色々とプラグインが出ているパララックスですが、今回はその仕組みを知るためにも1から自作してみました。
実務で1から自作することは、工数の関係上などであまりなさそうですが、学習の為にやってみました。
なかなか大変でしたが、仕組み自体はシンプルです。
仕組み
今回はbackground-imageではなく、imgタグを使います。
<div class="img">という画像エリアを表すdivタグの中にimgタグがあります。
親の画像エリアにposition: relative、はみ出た要素を隠すoverflow: hiddenを指定し。
子要素のimgは、高さが欲しいのでheight: 150%、width:autoを指定します。
さらに、position: absoluteとtop: 0、left: 50%、translate: -50% 0を指定します。
jQueryでスクロールして画面内に入ったら、「スクロール量 - 要素の位置」に指定した数値割ったものをマイナスしてやります。
.css('top', -「スクロール量 - 要素の位置 - 調整用の数値」)
といった感じです。
コードは以下です↓
<!-- index.html -->
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="./css/style.min.css">
<title>Document</title>
</head>
<body>
<div class="container">
<div class="txt-img">
<div class="text">
<p>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Cum eveniet eos animi laboriosam libero! Odit iure consequatur saepe quod. Quae at, quis quidem minus fuga ipsam inventore non. Alias, magnam.
</p>
</div>
<div class="img">
<img src="./img/cabbage-gfbe0c78be_640.jpg" alt="" srcset="">
</div>
</div>
<div class="txt-img reverse">
<div class="text">
<p>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Cum eveniet eos animi laboriosam libero! Odit iure consequatur saepe quod. Quae at, quis quidem minus fuga ipsam inventore non. Alias, magnam.
</p>
</div>
<div class="img">
<img src="./img/kristopher-roller-zepnJQycr4U-unsplash.jpg" alt="" srcset="">
</div>
</div>
<div class="txt-img">
<div class="text">
<p>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Cum eveniet eos animi laboriosam libero! Odit iure consequatur saepe quod. Quae at, quis quidem minus fuga ipsam inventore non. Alias, magnam.
</p>
</div>
<div class="img">
<img src="./img/matteo-di-iorio-VD-Vjc8VmRA-unsplash.jpg" alt="" srcset="">
</div>
</div>
<div class="txt-img reverse">
<div class="text">
<p>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Cum eveniet eos animi laboriosam libero! Odit iure consequatur saepe quod. Quae at, quis quidem minus fuga ipsam inventore non. Alias, magnam.
</p>
</div>
<div class="img">
<img src="./img/merch-husey-H-AmuI7mu-c-unsplash.jpg" alt="" srcset="">
</div>
</div>
<div class="txt-img">
<div class="text">
<p>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Cum eveniet eos animi laboriosam libero! Odit iure consequatur saepe quod. Quae at, quis quidem minus fuga ipsam inventore non. Alias, magnam.
</p>
</div>
<div class="img">
<img src="./img/taylor-kiser-N7buN8Lv7uQ-unsplash.jpg" alt="" srcset="">
</div>
</div>
</div>
<script src="https://code.jquery.com/jquery-3.7.0.min.js" integrity="sha256-2Pmvv0kuTBOenSvLm6bvfBSSHrUJ+3A7x6P5Ebd07/g=" crossorigin="anonymous"></script>
<script src="./js/script.js"></script>
</body>
</html>
cssがコチラです(sassで書いてます。)↓
//style.scss
@charset "utf-8";
*,
*::before,
*::after {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
min-height: 400vh;
}
.container {
width: min(1120px, 100% - 4rem);
margin-inline: auto;
}
.txt-img {
padding-top: 80px;
padding-bottom: 80px;
display: flex;
gap: 35px;
&:first-child {
margin-top: 650px;
}
.text {
flex: 2;
p {
font-size: 1.5rem;
}
}
.img {
flex: 1.5;
aspect-ratio: 3/2;
position: relative;
overflow: hidden;
img {
height: 150%;
width: auto;
position: absolute;
top: 0;
left: 50%;
translate: -50% 0;
}
}
}
.reverse {
flex-direction: row-reverse;
}
txt-imgというクラスがついたdivタグの中に、text、imgというdivタグが入っています。
display: flex でそれぞれ横並びにし、reverseというクラスがついたものだけ左右逆に並べています。
text、imgそれぞれのdivタグに flexプロパティを指定し、幅を調整します。
txt-imgの最初の要素だけにmargin-top: 650px、bodyにはheight: 400vhを指定し、十分なスクロール量を確保しました。
ここはスペース確保のためのスタイルで、実務では必要ありません。
Jqueryがコチラです↓
スクロール量・要素の位置・cssの上書きの為に書きます
//script.js
$(function() {
function parallaxImg() {
let img = $('.img img');
img.each(function() {
let elemPos = $(this).offset().top;
let scroll = $(window).scrollTop();
let windowHeight = $(window).height();
let adjust = 120;
//要素が画面内に入ってすぐではなく、そこから120上に来たら発動するため
let parallaxSpeed = 0.2;
//画像を動かす量が多すぎると、はみ出してします可能性がある為。この値を大きくすれば、画像が動く量が大きくなる
if (scroll > elemPos - windowHeight + adjust) {
$(this).css('top', (scroll - elemPos) * parallaxSpeed + 'px');
//スクロール量から要素の位置を引き、調整用の数値をかけ、文字列'px'を足したものをtopに代入
}
});
}
$(window).on('scroll', function() {
parallaxImg();
//画面をスクロールした時に、関数parallaxImgが発動する
});
});
以上になります。
マウスホイールでスクロールすると、どうしてもカクカクするので、慣性スクロールなどと組み合わせると効果を発揮しそうです。
あと、画像の高さを十分確保することが必要なのでheight: 150%をしてしていますが。
それに合わせて、width: auto で横幅も多少広くなるはずです。
逆に縦長すぎる画像だと、横幅が狭くなり、画像の両端がスカスカになってしまうので、photoshopの「コンテンツに応じた塗りつぶし」でスペースを確保しておくといいかもしれないです。
最後まで閲覧頂きありがとうございます。