CSSでスクロールバー非表示とJSでスクロールバーのデザインをカスタマイズする
スクロールバーはブラウザによってUIが違い、どのブラウザでも同じように表示させたいときがあると思います。色々方法はありますが、その1つとして紹介したいと思います。
スクロールバーの非表示
コンテナが固定幅
こちらの記事ではCSSのみでスクロールバーを非表示にする方法が紹介されています。
<div class="container">
<div class="scrollable">
<div class="adjustment">
...
</div>
</div>
</div>
.container {
width: 250px;
overflow: hidden;
}
.scrollable {
width: 270px; /* 250 + 20 */
height: 300px;
overflow: hidden;
overflow-y: scroll;
-webkit-overflow-scrolling: touch;
}
.adjustment {
width: 250px; /* 元に戻す */
}
ブラウザによってはスクロールバーの幅が17pxではないこともあるので、.scrollable
の横幅を20pxと多めにとってあります。固定幅ならばこの手法で実現できますがレスポンシブデザインが主流の今、固定幅というのはあまりないと思います。やはり、可変幅での対応が必要となってきます。
コンテナが可変幅
<div class="container">
<div class="scrollable">
...
</div>
</div>
* {
box-sizing: border-box;
}
body {
/* JavaScriptでスクロールバーの幅を取得するために必要 */
overflow-y: scroll;
}
.container {
max-width: 400px;
overflow: hidden;
}
.scrollable {
margin-right: -17px; /* オーバーレイスクロールバーを消す */
padding-right: 17px; /* オーバーレイスクロールバーを消す */
height: 300px;
overflow: hidden;
overflow-y: scroll;
-webkit-overflow-scrolling: touch;
}
.scrollable.is-scrollbar {
padding-right: 0;
}
var scrollbar_width = window.innerWidth - document.body.scrollWidth;
// 固定スクロールバーのとき(オーバーレイでない)
if (scrollbar_width > 0) {
$('.scrollable').addClass('is-scrollbar');
// スクロールバーの幅が17pxでないとき
if (scrollbar_width !== 17) {
$('.scrollable').css('margin-right', '-' + scrollbar_width + 'px');
}
}
Macなどの一部OSではスクロールバーがオーバーレイ表示されるため、margin-right
を使ってはみ出させてその分を padding-right
で調整し、非表示になるようにしています。スクロールバーの幅をJavaScriptで取得して、オーバーレイスクロールバーかそうでないかで場合分けします。また、スクロールバーの幅が17pxではないブラウザもあるので、そのときは style
属性で上書きするようにしています。
overflow-y: scroll
のバグ
IEやFirefoxでは overflow-y: scroll
を指定した要素の padding-bottom
が無視されるというバグがあります。これを回避する手段として2つ紹介します。
子要素に padding
を定義
<div class="container">
<div class="scrollable">
<div class="adjustment">
...
</div>
</div>
</div>
.scrollable {
overflow-y: scroll;
}
.adjustment {
padding: 1em;
}
擬似要素で表現
<div class="container">
<div class="scrollable">
...
</div>
</div>
.scrollable {
overflow-y: scroll;
}
.scrollable {
padding: 1em 1em 0;
}
.scrollable::after {
display: block;
height: 1em;
content: '';
}
擬似要素で padding-bottom
だけ作る手法です。
固定スクロールバーを自作
固定スクロールバーをどの環境でも同じように表示されるように自作してみます。これを応用すれば、オーバーレイスクロールバーも作ることができます。
基本構造
ベースとして1.2-コンテナが可変幅のCSS/JSを使います。
<div class="container">
<div class="scrollable">
<div class="adjustment">
...
</div>
</div>
<div class="scrollbar">
<div class="scrollbar-thumb"></div>
</div>
</div>
.container {
position: relative;
}
.adjustment {
margin-right: 17px; /* スクロールバーの幅 */
padding: 1.3em 1.5em;
}
.scrollbar {
position: absolute;
top: 0;
right: 0;
bottom: 0;
width: 17px; /* スクロールバーの幅 */
background-color: #ece1e3;
}
.scrollbar-thumb {
min-height: 50px;
background-color: #baa4a9;
}
スクロールバーに必要なHTML/CSSを追加していきます。
スクロールバーの高さを設定
$(window).on('load', function() {
var scrollable_height = $('.scrollable').height(),
adjustment_height = $('.adjustment').outerHeight(),
scrollbar_height = parseInt(scrollable_height * scrollable_height / adjustment_height);
$('.scrollbar-thumb').css('height', scrollbar_height);
});
IEで outerHeight()
が $(function() { ... });
のタイミングで正確に読み取れなかったため、$(window).on('load')
にしています。
スクロールに応じて位置変更
$(window).on('load', function() {
...
var scrollbar_track = scrollable_height - scrollbar_height;
$('.scrollable').on('scroll', function() {
var offset = $(this).scrollTop() * scrollbar_track / (adjustment_height - scrollable_height);
$('.scrollbar-thumb').css('transform', 'translateY(' + offset + 'px)');
});
});
つまみでスクロールさせる
$(window).on('load', function() {
...
var active = false, // つまみを操作しているかどうか
scrollbar_thumb_cursor_y; // つまみ内のクリック位置
$('.scrollbar-thumb').on('mousedown', function(event) {
active = true;
scrollbar_thumb_cursor_y = event.pageY - $(this).offset().top;
});
$(document).on('mouseup', function() {
active = false;
});
$(document).on('mousemove', function(event) {
if (!active) return;
var scrollbar_thumb_y = ((event.pageY - $('.scrollbar').offset().top) / scrollbar_track * scrollbar_track) - scrollbar_thumb_cursor_y;
// つまみが上下の領域外を超えないようにする
if (scrollbar_thumb_y < 0) {
scrollbar_thumb_y = 0;
} else if (scrollbar_thumb_y > scrollbar_track) {
scrollbar_thumb_y = scrollbar_track;
}
// つまみの位置設定
$('.scrollbar-thumb').css('transform', 'translateY(' + scrollbar_thumb_y + 'px)');
// つまみの位置に応じてスクロールさせる
$('.scrollable').scrollTop(($('.scrollbar-thumb').offset().top - $('.scrollbar').offset().top) / scrollbar_track * (adjustment_height - scrollable_height));
});
// つまみを操作中はテキスト選択できないようにする
$(document).on('selectstart', function() {
if (active) return false;
});
});
変数 active
にスクロールバーのつまみを操作中かどうか保存しておきます。あとはつまみの位置を求め、何pxスクロールさせるかを設定するだけです。
jQueryプラグインの紹介
自作でもサクッと作れますが、とても素晴らしいjQueryプラグインがあったので紹介します。
こちらのプラグインはとても素晴らしいのですが、1つだけ残念な点があります。標準機能の overflow-y: scroll
を使用せずJavaScriptで操作しているため、-webkit-overflow-scrolling: touch
の気持ちいいスクロールができません。一応慣性スクロールはできますが、純正のものほど気持ちよくはないのです。それ以外はカスタマイズもしやすく便利だと思います。
CSS本執筆しました!!!
CSS本出します!1/29発売予定
— たかもそ@CSS本1/29発売!! (@takamosoo) 2018年12月31日
自分がCSS学びたての頃にもっとはやく知りたかったテクニックを載せています。CSSの基礎知識について解説していないので、中級者〜向けとなります。CSS入門書を読んではみたものの、思い通りに作れない人にオススメです。
よろしくお願いします。https://t.co/fkz1dM03Pj pic.twitter.com/suYyaPqwIs