今回は、「PhotoshopVIP」のレイアウト紹介記事を基にした内容です。
目から鱗の記事だったので、早速使ってみたかったのもあります。
スワイプエフェクトをCSSメインで、コード量も少なく実装できてしまうので、是非最後までご覧ください。
スワイプエフェクトで使用するCSS
スワイプエフェクトは、ページをスクロールすると、コンテンツが重なり合うレイアウトで、「PhotoshopVIP」さんで紹介されたCSSのみでできるスタイリングです。
.scroll-container {
height: 100vh;
overflow-y: scroll;
scroll-snap-type: y mandatory;
}
.section {
height: 100vh;
scroll-snap-align: start;
scroll-snap-stop: always;
}
詳細の内容は以下の参考記事から見れるので、こちらの記事も参考にしてみてください。
CSSのみで簡単に実装できるので、めちゃめちゃ便利です。
この記事ではこのCSSをベースに、表示されたブロックにclass名をあてるスニペットを解説していきます。
スワイプエフェクトで切り替わるサンプル
早速サンプルです。
5つのブロックからなるページで、スクロールすると各ブロックがウィンドウにピッタリ収まって表示されます。
1枚目のブロックだけ、スクロールすると2枚目が上にかぶさるようにしています。
フルサイズの縦スライダーをCSSだけでできるレイアウトです。
実装の手順と方法
コードの解説の前に、実装の手順と方法について簡単にご説明します。
HTMLで記述します。
<div class="scroll-container">
<section class="section">
<h1 id="mainLogo">
<img src="https://dubdesign.net/wp-content/uploads/2022/07/mainlogo.svg" alt="ロゴ">
</h1>
<img src="https://dubdesign.net/wp-content/uploads/2022/07/001_building.jpg" class="bgImg">
</section>
<section class="section">
<img src="https://dubdesign.net/wp-content/uploads/2022/07/002_building.jpg" class="bgImg">
</section>
<section class="section">
<img src="https://dubdesign.net/wp-content/uploads/2022/07/003_building.jpg" class="bgImg">
</section>
<section class="section">
<img src="https://dubdesign.net/wp-content/uploads/2022/07/004_business.jpg" class="bgImg">
</section>
<section class="section">
<img src="https://dubdesign.net/wp-content/uploads/2022/07/005_business.jpg" class="bgImg">
</section>
</div>
次に、JavaScriptのコードをページに記述します。
コードは <body>〜</body>
で、</body>
の閉じタグ(クロージングタグ)の前に記述しましょう。
const doObserve = (element) => {
const targets = document.querySelectorAll('.section'); /* ターゲットの指定 */
const options = {
root: null,
rootMargin: '0px',
threshold: 0
};
const observer = new IntersectionObserver((items) => {
items.forEach((item) => {
if (item.isIntersecting) {
item.target.classList.add('scrollon'); /* スクロールでターゲットに付与するclassの指定 */
} else {
item.target.classList.remove('scrollon'); /* 表示域から外れた時にターゲットから削除するclassの指定 */
}
});
}, options);
Array.from(targets).forEach((target) => {
observer.observe(target);
});
};
doObserve('.observe_target');
最後にCSSの記述です。
.scroll-container {
height: 100vh;
overflow-y: scroll;
scroll-snap-type: y mandatory;
}
.section {
width: 100%;
height: 100vh;
scroll-snap-align: start;
scroll-snap-stop: always;
position: relative;
}
.section:first-child {
position: sticky;
top: 0;
}
.section .bgImg {
object-fit: cover;
object-position: center;
width: 100%;
position: relative;
}
body {
margin: 0;
}
h1#mainLogo {
position: absolute;
top: 50%;
z-index: 1;
left: 50%;
transform: translate(-50%, -50%);
}
h1#mainLogo img {
width: 320px;
height: 320px;
}
これで完成です!
ざっくりとしたコードの解説
コードについてざっくりですが解説します。コードはHTML・JavaScript・CSSの3種類です。
HTML
HTMLは、「scroll-container」のclass名を持つ親の div
タグに、「section」のclass名の section
タグがそれぞれスクロールした時にピタッとウィンドウに収まるブロックです。
<div class="scroll-container">
<section class="section">
<h1 id="mainLogo">
<img src="https://dubdesign.net/wp-content/uploads/2022/07/mainlogo.svg" alt="ロゴ">
</h1>
<img src="https://dubdesign.net/wp-content/uploads/2022/07/001_building.jpg" class="bgImg">
</section>
<section class="section">
<img src="https://dubdesign.net/wp-content/uploads/2022/07/002_building.jpg" class="bgImg">
</section>
<section class="section">
<img src="https://dubdesign.net/wp-content/uploads/2022/07/003_building.jpg" class="bgImg">
</section>
<section class="section">
<img src="https://dubdesign.net/wp-content/uploads/2022/07/004_business.jpg" class="bgImg">
</section>
<section class="section">
<img src="https://dubdesign.net/wp-content/uploads/2022/07/005_business.jpg" class="bgImg">
</section>
</div>
1個目のブロックには、h1
タグで重ねるロゴを置いています。
JavaScript
JavaScriptは、「ターゲットの指定」を行い、条件分岐で処理方法をそれぞれ記述します。
const doObserve = (element) => {
const targets = document.querySelectorAll('.section'); /* ターゲットの指定 */
const options = {
root: null,
rootMargin: '0px',
threshold: 0
};
const observer = new IntersectionObserver((items) => {
items.forEach((item) => {
if (item.isIntersecting) {
item.target.classList.add('scrollon'); /* スクロールでターゲットに付与するclassの指定 */
} else {
item.target.classList.remove('scrollon'); /* 表示域から外れた時にターゲットから削除するclassの指定 */
}
});
}, options);
Array.from(targets).forEach((target) => {
observer.observe(target);
});
};
doObserve('.observe_target');
具体的には、冒頭にある option
で「root」のキーを「null」に設定することで、要素がウィンドウに入ったかどうかの検知ができるようになります。
そして、検知された時に実行される処理は、まず IntersectionObserver
を作成し、要素に対しての検知を行なっていくと、検知したオブジェクトを取得できるようになります。
CSS
CSSは
「scroll-container」のclass名には、scroll-snap-type: y mandatory;
で y 方向にスナップ点を強制的に移動させるプロパティを記述。そして、「section」のclass名を持つ要素には、 scroll-snap-align: start;
でスクロールスナップ領域の先頭位置をスナップ位置にして、scroll-snap-stop: always;
ですべてのポイントにスクロールを可能な限りスナップさせてスナップスクロールを作ります。
.scroll-container {
height: 100vh;
overflow-y: scroll;
scroll-snap-type: y mandatory;
}
.section {
width: 100%;
height: 100vh;
scroll-snap-align: start;
scroll-snap-stop: always;
position: relative;
}
.section:first-child {
position: sticky;
top: 0;
}
.section .bgImg {
object-fit: cover;
object-position: center;
width: 100%;
position: relative;
}
body {
margin: 0;
}
h1#mainLogo {
position: absolute;
top: 50%;
z-index: 1;
left: 50%;
transform: translate(-50%, -50%);
}
h1#mainLogo img {
width: 320px;
height: 320px;
}
そして、1個目のブロックがスクロールした時に2個目のブロックが上から重なるようになるよう擬似要素の「:first-child」で position: sticky;
プロパティを記述します。
また、親要素と各ブロックの高さを 100vh
にして、画面にちょうどフィットさせるようにします。
スマホに最適なコードは書いていないので、使う場合は別途書くようにしましょう。
さいごに
今回は以下の記事を参考に、JavaScriptでclass名の追加・削除の方法を解説しましたが、参考元の記事には、この他にも使えるテクニックが多数紹介されているので、参考にしてみてください。