position:fixedで固定した要素を横スクロールさせるJavaScript

こんにちは、ナカムラです。
今回は横スクロールが発生する状態で、pisition:fixed(もしくはabsolute)で位置を固定した要素を追従させるJavaScriptのご紹介をします。

レスポンシブ対応のサイトとはいえ、スマホのサイズから一般的なPCのサイズまで全ての幅に対応するのはなかなか大変です。
あまり求められていない場合も多いので、PCではある程度で幅を固定することが多いです。
(全てに対応するかどうかは案件により異なりますし、どうすべきか、というご意見も色々とあると思いますが、今回は触れません。時間と予算が許されるなら対応はしたいところですが…)

幅を固定にすると何が起きるかというと、
設定した幅よりも、ウィンドウサイズが狭かった時に、横スクロールするようになります。

ヘッダーなどは、position:fixedで固定にすることも多いですよね。
そうした場合、ページの横スクロールを操作しても、
位置は固定されたままになり、ウィンドウ幅を超えた部分は表示されない状態になります。

固定要素内だけリキッドにする方法もありますが、
コンテンツが固定幅なのにヘッダーが可変するのもなんだか気持ち悪い気もします。
(スクロール操作せずにメニューをクリックできるのは楽なので、悩ましいところではあります)

そこで、横スクロールした時に、固定させた要素も一緒に動くようにしたいと思います。

DEMO

See the Pen position:fixedで固定した要素を横スクロールさせるJavaScript by Nakamura (@takayo-nakamura) on CodePen.

解説

Javascriptはこれだけです。

const element = document.querySelector('.js-scroll-x') // 要素の取得
window.addEventListener('scroll', () => {
  element.style.left = -window.pageXOffset + 'px' //横にスクロールした分、位置をずらす
})

位置を調整したい要素を取得し、
addEventListenerで、スクロールが発生したときに
取得した要素のstyle.leftに、横スクロールの数値をマイナスにして付与します。
(単位も付け加えないとstyleに反映されないのでご注意ください)

右にスクロールした分、固定した要素を左にずらすことで、
コンテンツとともに横スクロールをしているかのように見せています。

※複数箇所に当てたい場合は、要素の取得をquerySelectorAllにして、forEachでイベントを付与していきます。 (DEMO内にコメントで書いてあります。)

JavaScriptを使わない方法

ヘッダーなどでしたらposition:stickyで固定(追従)させる方法もあります。
stickyなら横スクロールしてくれるので、わざわざJavaScriptを書く必要がないです。

対応方法はいろいろあるので、適切なものを選んで実装してください。