レスポンシブページを作る時に必要なブレイクポイント。
PCとSPでCSSだけでなくJSの処理を分けたいことは多々あります。
そんな時はこう書きますよね。
@media screen and (max-width: 600px) {
body{
background-color: pink;
}
}
window.onresize = function(){
if(window.innerWidth > 600){
~~~~~~~ PC ~~~~~~~
}else{
~~~~~~~ SP ~~~~~~~
}
}
そんな時、cssのブレイクポイントと、JSのブレイクポイントがズレたらお話しにならない。
メディアクエリは、スクロールバーを含めた幅で判定する
なのでウィンドウ幅の判定には、スクロール幅も含めた値を返す window.innerWidth を使う。$(window).width() はバーを含めない値を返すため、その分CSS側とズレてしまう。
上記を考慮して、
601px以上は白
600px以下はピンク
になるページが以下です。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>1</title>
<style>
* {
margin: 0;
padding: 0;
}
h1 {
height: 2000px;
}
@media screen and (max-width: 600px) {
body {
background-color: pink;
}
}
</style>
</head>
<body>
<h1 id="h1"></h1>
<script>
// 変数
var breakpoint = 600;
var dom = document.getElementById("h1");
// 関数
var getW = function() {
return window.innerWidth;
}
var setText = function(dom, text) {
if (getW() > breakpoint) {
dom.innerHTML = "白: " + text;
} else {
dom.innerHTML = "ピンク: " + text;
}
}
// 実行
setText(dom, getW());
// バインド
window.onresize = function() {
setText(dom, getW());
}
</script>
</body>
</html>
ただ上記で、うまくいかないブラウザが一つありました。
Mac Safariです。
スクロールバーがない時は、他のブラウザと同じ挙動なのですが、
スクロールバーが出た瞬間に牙をむきました。
そう、こいつは、何故か
メディアクエリで、スクロールバーを含めない幅で判定する
という狂った挙動をとりました。
先ほどのデモだと
text → 白: 610 (JS側)
背景 → ピンク (CSS側)
というふうになり JS側とCSS側でズレてしまっています。
本当は1ブラウザの為にここまでやりたくなかったのですが、仕方ありません。
それが以下になります。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>2</title>
<style>
* {
margin: 0;
padding: 0;
}
h1 {
height: 2000px;
}
@media screen and (max-width: 600px) {
body {
background-color: pink;
}
}
</style>
</head>
<body>
<h1 id="h1"></h1>
<script>
// 変数
var breakpoint = 600;
var dom = document.getElementById("h1");
var isMacSafari = (function() { //mac safariの判定
ua = window.navigator.userAgent.toLowerCase()
if ((ua.indexOf('safari') !== -1) && (ua.indexOf('chrome') === -1) && (ua.indexOf('mac') !== -1)) {
return true
} else {
return false
}
})();
var scrollBar = isMacSafari ? window.innerWidth - document.body.clientWidth : 0; //バーの幅を出す
// 関数
var getW = function() {
return window.innerWidth - scrollBar;
}
var setText = function(dom, text) {
if (getW() > breakpoint) {
dom.innerHTML = "白: " + text;
} else {
dom.innerHTML = "ピンク: " + text;
}
}
// 実行
setText(dom, getW());
// バインド
window.onresize = function() {
setText(dom, getW());
}
</script>
</body>
</html>
ポイントとしては、
・MacSafariかどうかの判定
・その場合はスクロールバーの幅を出す
・MacSafariの時だけ、JSの処理の際、スクロールバー分だけ長さを引いて、CSSの方に合わせる
ユーザーエージェントって将来どうなるかわからないので、あまり使いたくないんです。。これ私のMacだけとかじゃないですよねw?(MacbookPro 2015モデル)
レスポンシブサイト作る上で必ずぶち当たると思うんですが、皆さんどうしているのか。
なにかもっとスマートなやり方があったら教えてくださいませ。