今回は画面横幅に応じた要素の表示の切り替えなどの処理「JavaScriptによるレスポンシブ対応」の実現方法を以下3点で紹介したいと思います。
- resizeイベント
- observer
- matchMedia
resizeイベント
言わずと知れたブラウザのウィンドウサイズの変更時に発生するイベントです。簡単な使用例は以下です。
window.addEventListener('resize', function () {
// リサイズ時の処理
console.log('resizeしました! resizeするたびに実行されます!')
})
画面幅に応じた処理の例
window.addEventListener('resize', function () {
let width = window.innerWidth
console.log(width)
if (width < 767) {
// sp
document.body.innerText = 'sp:' + width + 'px'
} else if (width < 1023) {
// tablet
document.body.innerText = 'tablet:' + width + 'px'
} else {
// pc
document.body.innerText = 'pc:' + width + 'px'
}
})
上記は、windowオブジェクトのaddEventListenerメソッドを使用してウィンドウサイズが変更された時に、画面幅を取得しています。画面幅を取得し、その画面幅からSP/TABLET/PCかどうかを判断し、それぞれの画面幅にあった処理を行います。
メリット
- 簡単
- わかりやすい
メリットとしては、addEventListenerはよく使用するメソッドなので、一見簡単でわかりやすいと思います。
デメリット
- 画面幅が変更されるたびに処理が実行される
- 画面がカクツク時がある
デメリットとしては、画面幅が変更されるたび処理が実行されるため、一度画面幅に応じた処理を実行したにもかかわらず再度同じことをする、など無駄が発生してしまいます。
同じ処理を実行しないように、画面幅に応じた処理を行なったかどうかを判断する処理を追加したとしても、その判断の処理は実行されます。 その処理が重ければ画面が固まってしまう可能性もあります。
observer(ResizeObserver)
次はobserverです。私は当初、画面幅に応じたJavaScriptの処理をresizeイベントで実装していました。切り替わった時だけ処理が実行される方法がないのかと思いつつもresizeで対応していました。
そんな中画面幅でなく、特定要素の横幅に応じて処理を実装したくて色々調べていたら、「ResizeObserver」に辿り着きました。
「ResizeObserver」では、指定要素を監視してサイズ変更を検知して処理を実行することができます。
画面幅(要素の横幅)に応じた処理の例
ブラウザの画面幅を変更することで動作を確認することができます。
メリット
- 画面幅でなく要素の横幅でレスポンシブ対応ができる
ResizeObserverの場合は、ブラウザの画面幅でなく要素の横幅に応じてレスポンシブなデザインにすることができます。
デメリット
- 要素の横幅が変更されるたび処理が実行される
ResizeObserverの場合でも、resize同様要素の横幅が変更されるたびに処理が実行されてしまい、処理の無駄が発生してしまいます。
matchMedia
observer(ResizeObserver)を発見し、満足していましたが、zenn.devのjs系の記事を読み漁っていたところ、matchMediaというものを知りました。
matchMediaとはresize同様、windowオブジェクトのメソッドの一つで、 なんとCSSのメディアクエリのように画面幅に応じた処理を記述することができます!
if (window.matchMedia( "(min-width: 400px)" ).matches)
画面幅に応じた処理の例
ブラウザの画面幅を変更することで動作を確認することができます。
メリット
- 画面幅が指定値に変わったタイミングで処理が実行される
- CSSのメディアクエリのように書ける
デメリット
ResizeObserverのように、特定要素の横幅に応じた処理は無理そうです。
以上となります。今後は、画面幅でのJavaScriptを利用してレスポンシブ対応はresizeイベントでなく、matchMediaによって実装したほうが、処理の無駄がなく効率的で良さそうです。
しかし、特定要素自体の横幅に応じた処理は、ResizeObserverで実装するのが良さそうです。