画面をスクロールしたら固定ヘッダーに境界線がつくUIをCSSのみで実現する方法を紹介します。どんな時にそのようなUIを採用したくなるかというと、画面が読み込まれた直後はヘッダーとコンテンツの境界をシームレスに表現したいが、スクロールをしたらヘッダーが重なるので境界をはっきりさせたい。そんなときです。
画面をスクロールしたら固定ヘッダーに境界線がつくUIをCSSのみで実現する
これを実現したいと思った時にパッと思いつく方法は、スクロールされたかどうかをJavaScriptでチェックしてclassを付与するという方法ですが、この記事で紹介する作り方をすればCSSだけで実現できます。
以下のデモ画面をスクロールしてみてください。
JavaScriptを利用せずにCSSだけで実現しているのでいくつか制約がありますが、これらの制約を受け入れられるのであれば、JavaScriptを書かなくてもいいのでおすすめです。
- 境界線を表示するタイミングはスクロール直後である
- 背景色がベタ塗りである必要がある
コードサンプル
では、どのように実現しているのかを見ていきましょう。コードを見た方が理解が早いと思うので、まずはコードをご覧いただきます。必要なところだけに絞っているので、完全なサンプルはCodePenのデモを参照してください。
HTMLはこうです:
<div id="container">
<header>Title</header>
<div id="border"></div>
<div id="article">
<div></div>
<div></div>
<div></div>
...
</div>
</div>
この例だと、div#border
が境界線になります。
そしてSCSSはこちら:
$header-height: 50px;
#container {
padding-top: $header-height;
}
header {
height: $header-height;
background: #fff;
position: fixed;
top: 0;
width: 100%;
z-index: 2;
}
#border {
position: relative;
z-index: 1;
&::before,
&::after {
content: "";
width: 100%;
}
&::before {
position: fixed;
border-bottom: 1px solid gray;
}
&::after {
position: absolute;
border-bottom: 1px solid white;
}
}
ポイントとしては、境界線として見せたいborderと、スクロールされていない時にそれを覆い隠す(背景色と同じ色の)borderを重ねるということです。
borderを重ねる理由
背景色と同じ色のborderを重ねると、そこにborderがあっても視覚的にはborderはないように見えます。これでページ読み込み直後のシームレスな見た目を実現します。
そして、画面をスクロールした時にどうなるのかというと、
- 境界線として見せたいborder(この例では
::before
)はposition: fixed
なのでその位置に留まり続ける - 覆い隠す方のborder(この例では
::after
)はposition: absolute
なので、スクロールとともに動く
というかんじで、覆い隠されていたborderが見えるようになるわけです。これで、スクロール前は隠す、スクロールしたら表示するということができました。
単純なことをしているだけなので、考え方を覚えてしまえば簡単に再現ができると思います。ぜひご利用ください。