レスポンシブ対応のデバッグする際、デバイスの画面幅からはみ出して横スクロールの原因となっている要素がないかJavaScriptを使ってチェックしたい。——記事の後編です。
前編で作った関数getDeviceWidth()
を使って、実際に要素のはみ出しをチェックしてみましょう。
レスポンシブ対応がお粗末なサンプルを用意しました:
https://codepen.io/kaz_hashimoto/pen/rNvjwBb
デモの動画です。これはiPad ProのSplit Viewで表示した例です。Split Viewで割り当てられた領域の幅を「画面幅」として、その幅をはみ出してレイアウトされている要素を赤枠で表示しています。実際にはビューポートの幅がSplit Viewの幅にスケーリングされページがフィットして表示されています。
See the Pen [video] detect overflow elements by Kazuhiro Hashimoto (@kaz_hashimoto) on CodePen.
※画像引用:Photo by Inspirationfeed on Unsplash
要素のはみ出しをチェックするコードです。
function getDeviceWidth() {
if (typeof window.visualViewport === 'undefined') {
return window.innerWidth;
}
const width = visualViewport.width * visualViewport.scale;
return Math.round(width);
}
let enable_check_overflow = true;
(function check_overflow() {
if (!enable_check_overflow) {
return;
}
const device_width = getDeviceWidth();
// const ignore = document.body.querySelectorAll('.slick-slide:not(*)');
const ignore = document.body.querySelectorAll('.slick-slide, .slider');
const list = document.body.querySelectorAll('*');
for (const el of list) {
if (el.classList.contains('__overflow')) {
continue;
}
let exclude = false;
for (const o of ignore) {
if (o.contains(el)) {
exclude = true;
break;
}
}
if (exclude) {
continue;
}
['width', 'height'].forEach(a => {
if (el.hasAttribute(a)) {
el.removeAttribute(a);
}
});
let checked = false;
const r = el.getBoundingClientRect();
if (r.width > device_width) {
console.log('## overflow width', el);
checked = true;
} else if (r.right > device_width) {
console.log('## overflow right', el);
checked = true;
}
if (checked) {
el.classList.add('__overflow');
}
}
setTimeout(check_overflow, 5000);
})();
check_overflow()
は5秒おきにbody
内の要素をスキャンして、要素のバウンディングボックスの寸法をチェックします。ボックスの幅がデバイスの画面幅を超えていた場合やボックスの右端が画面幅を超えていた場合には、consoleにメッセージとElementを出力し、その要素にclass __overflow
をフラグとして立てます。
注)__overflow
は一度ONになると解除されません。
img要素などHTMLにwidth
やheight
属性が指定されている場合は、それらを削除してチェックします。CSSでの設定漏れを検出するためです。
このサンプルでは、slickスライダーの画像はチェックの対象外としました。変数ignore
にセットしているquerySelectorAll
の箇所です。スライダーの画像は元々画面外に配置されており、チェックで毎回検出されてconsoleの出力が鬱陶しくなるためです。
この機能をオフにするには、コメント行に示したようにignore
に空のNodeListがセットされるようにします。
はみ出しが検出された要素を画面上で見分けやすくするために、このサンプルでは__overflow
セレクターに対してoutline
を指定して輪郭線を表示させています。
.__overflow {
outline: 2px solid red;
outline-offset: -2px;
}
check_overflow()
の用途はデバッグに限られるため、コーディング中にちょっと表示をチェックしたい時だけDevToolsのconsoleに上記のスニペットをコピペして実行するという使い方でも十分です。