4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

デバイスの画面幅からはみ出している要素を検出する方法(2)

Posted at

レスポンシブ対応のデバッグする際、デバイスの画面幅からはみ出して横スクロールの原因となっている要素がないか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

要素のはみ出しをチェックするコードです。

javascript(前編からの再掲)
function getDeviceWidth() {
  if (typeof window.visualViewport === 'undefined') {
    return window.innerWidth;
  }
  const width = visualViewport.width * visualViewport.scale;
  return Math.round(width);
}
javascript
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にwidthheight属性が指定されている場合は、それらを削除してチェックします。CSSでの設定漏れを検出するためです。

このサンプルでは、slickスライダーの画像はチェックの対象外としました。変数ignoreにセットしているquerySelectorAllの箇所です。スライダーの画像は元々画面外に配置されており、チェックで毎回検出されてconsoleの出力が鬱陶しくなるためです。
この機能をオフにするには、コメント行に示したようにignoreに空のNodeListがセットされるようにします。

はみ出しが検出された要素を画面上で見分けやすくするために、このサンプルでは__overflowセレクターに対してoutlineを指定して輪郭線を表示させています。

css
.__overflow {
  outline: 2px solid red;
  outline-offset: -2px;
}

check_overflow()の用途はデバッグに限られるため、コーディング中にちょっと表示をチェックしたい時だけDevToolsのconsoleに上記のスニペットをコピペして実行するという使い方でも十分です。

4
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?