最初は画面上に固定されてないけどスクロールしてる途中で、特定の要素が画面に固定される。
そんなサイト見たことないですか?
See the Pen Untitled by ma-chan (@ma-chan) on CodePen.
こんな感じです。
こちら数行のJavascirptコードで簡単に実装出来ます。
上記の実装をするためのコードを記載します。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<div class="oya oya1"></div>
<div class="oya oya2"><div class="ko">要素</div></div>
<div class="oya oya3"></div>
<div class="oya oya4"></div>
<script src="main.js"></script>
</body>
</html>
HTML* {
margin: 0;
padding: 0;
}
.oya {
height: 100vh;
position: relative;
}
.oya1 {
background-color: red;
}
.oya2 {
background-color: green;
}
.oya3 {
background-color: blue;
}
.oya4 {
background-color: pink;
}
.ko {
background-color: black;
color: white;
font-size: 20px;
position: absolute;
height: 150px;
width: 150px;
right: 0;
bottom: 0;
display: flex;
justify-content: center;
align-items: center;
}
.watchingFixed {
position: fixed;
z-index: 1;
}
CSSconst oyaPosition = document.querySelector(".oya2");
const koPosition = document.querySelector(".ko");
console.log(koPosition.getBoundingClientRect());
window.addEventListener("scroll", () => {
if (oyaPosition.getBoundingClientRect().bottom <= window.innerHeight) {
koPosition.classList.add("watchingFixed");
} else {
koPosition.classList.remove("watchingFixed");
}
});
JavaScript以上です。
ここからはこの実装方法を知りたい方向けに、より詳しく解説していきます。
是非とも最後までご覧ください。
HTML/CSSの初期設定
ここからはHTML/CSSの初期設定について解説していきます。
HTMLで設定すべきポイントは特にないです。
自分が要素を固定したい位置を自由に記述しましょう。
CSSで設定すべきことは、位置を固定するためのクラスを作成することです。
それがこちらになります。
.watchingFixed {
position: fixed;
z-index: 1;
}
CSSここでのポイントはposition: fixed;を設定することです。
また、できればz-indexも記述した方がいいです。
z-indexを記述しなくてもうまくいきますが、状況によっては他の要素に埋もれてしまう可能性もあります。
これでHTML/CSSの準備は完了です。
JavaScript
ここからJavaScriptの解説に入っていきます。
JavaScriptで設定すべきポイントは以下になります。
- 固定したい親要素と固定したい要素自体を取得
- scrollイベントとif文
- 要素を固定する位置を設定
- 意図するスクロール位置で要素の固定と分離
一つずつ解説していきます。
固定したい要素の親要素と固定したい要素を取得
//固定したい要素の親要素と固定したい要体を取得
const oyaPosition = document.querySelector(".oya2");
const koPosition = document.querySelector(".ko");
JavaScriptまず固定したい固定したい要素の親要素と固定したい要素を取得します。
親要素も取得するのがポイントです。
詳しくは割愛しますが、親要素を取得しないと、一度画面を固定するとそこから二度と動かないという不具合が発生します。
必ず親要素も取得するようにしましょう。
scrollイベントとif文
次に設定するのがscrollイベントとif文の設定です。
const oyaPosition = document.querySelector(".oya2");
const koPosition = document.querySelector(".ko");
//scrollイベントとif文を設定
window.addEventListener("scroll", () => {
if () {
} else {
}
});
JavaScriptscrollしてる途中でイベントを発火させたいので、scrollイベントを設定。
後にif文で条件分岐するのでif文を設定。
ここは簡単ですね!
要素を固定する位置を設定
const oyaPosition = document.querySelector(".oya2");
const koPosition = document.querySelector(".ko");
window.addEventListener("scroll", () => {
if (
//画面下の絶対値と親要素の要素の絶対値を取得して条件分岐
oyaPosition.getBoundingClientRect().bottom <= window.innerHeight
) {
} else {
}
});
JavaScriptここが重要なポイントです。
重要な箇所はこちらです。
- 固定したい要素の親要素の絶対位置を取得
- 画面全体の高さを取得
- 要素の下端が画面内に入ったか判定する条件
一つずつ解説していきます。
固定したい要素の親要素の絶対位置を取得
まず固定したい要素の親要素の絶対位置を取得します。
そのためにgetBoundingClientRect()を使います。
getBoundingClientRect()は、指定した要素の現在位置とサイズを取得出来るメソッドです。
上の例で言うと、固定したい要素の親要素の現在位置とサイズになります。
上記のコードの例でいくと、親要素が画面の下に到達した時に指定した要素を固定したいです。
getBoundingClientRect()の下端の絶対位置を取得したいので、getBoundingClientRect().bottomと記述します。
画面全体の高さを取得
次に画面全体の高さを取得します。
画面全体の高さを取得する理由は、画面全体の高さが画面下の絶対位置になるからです。
最初の実装画面を見ていただければわかると思いますが、画面の下に要素が来たと同時に要素が固定されていると思います。
画面全体の高さを取得するために、window.innerHeightを使用します。
window.innerHeightを使えば画面全体の高さを取得できます。
要素の下端が画面内に入ったか判定する条件
ここまでで【固定したい要素の親要素の絶対位置を取得】と【画面全体の高さを取得】に成功しています。
あとは、画面下に固定したい要素の下端部が通過した時の条件を書きます。
それが、<=の比較演算子です。
画面の高さ(window.innerHeight)が、固定したい要素の親要素(getBoundingClientRect().bottom)の下を超えたらtrueになる。
これで画面が、固定したい要素の下を通過した時にtrueになるif文が出来ました。
意図するスクロール位置で要素の固定と分離
最後にすることは条件分岐で要素を付けたり離したりするだけです。
const oyaPosition = document.querySelector(".oya2");
const koPosition = document.querySelector(".ko");
window.addEventListener("scroll", () => {
if (oyaPosition.getBoundingClientRect().bottom <= window.innerHeight) {
//画面が固定したい要素の下を通過したら固定
koPosition.classList.add("watchingFixed");
} else {
//画面が固定したい要素より上を通過したら離れる
koPosition.classList.remove("watchingFixed");
}
});
JavaScriptここは簡単です。
さきほど記述したif文がtrueになったら事前に用意したCSSであるwatchingFixedを固定したい要素に付与します。
そうでない場合(画面が固定したい要素より上にきたら)watchingFixedを取り除きます。
これで完成です。
まとめ
ここまでスクロールの途中で特定の要素を固定する方法について解説してきました。
結構簡単に出来て、実務でも実装する機会が多いのでぜひ覚えていただけたらと思います。