139

When I size my Chrome window to 328 x 455 pixels I still see a horizontal scrollbar. How can I find out which element is causing this? I've been looking at elements via the developer console, but can't find the element.

I then tried the script I found here, but nothing is logged. I tried it on element body, section1 and a bunch of others but don't know what else to do.

    $(function () {
        var f = $('body'); //document.getElementById("body");
        var contentHeight = f.scrollHeight;
        var declaredHeight = $(f).height();

        var contentWidth = f.scrollWidth;
        var declaredWidth = $(f).width();
        if (contentHeight > declaredHeight) {
            console.log("invalid height");
        }
        if (contentWidth > declaredWidth) {
            console.log("invalid width");
        }
    });
Adam
  • 6,041
  • 36
  • 120
  • 208
  • 5
    Not the best way, but a fast fix: `body{ overflow-x: hidden; }` – lmgonzalves Jul 16 '15 at 15:30
  • Ok, tnx, I guess that visually solves the issue, but I'm not sure Google's "mobilegeddon" will like this way of solving the problem. So I'm still looking to find the element and address the issue head-on. – Adam Jul 16 '15 at 15:34
  • 6
    I have same problem once, and resolve it like this: I delete lets say – Akul Von Itram Jul 16 '15 at 15:40

14 Answers14

309
.slide-content .scroller {
  width: 1024px;
}

"fastestest" way: added this in inspector:

* {
  outline: 1px solid #f00 !important;
}

and the culprit appeared

Luca
  • 9,259
  • 5
  • 46
  • 59
  • 16
    The red border was super helpful. I quickly found that a `input[type="file"]` had a large font size and was causing the screen to be wider than I wanted. Thanks. – Ryan Jan 27 '18 at 18:04
  • 4
    This just helped me out again, and I discovered that some `input` fields for a Stripe form were the culprits, but I had to use `border: 1px solid red!important;`. I recommend adding `!important` to your answer. – Ryan Jul 29 '18 at 16:54
  • 5
    pay attention with this approach, the border can actually change the places where scrollbars appear, since it has a width itself. – bersling Jun 10 '20 at 10:56
  • 1
    in the op case, 1px didn't make a difference, but if that is a concern, one can always add a `border-top` only – Luca Jun 13 '20 at 09:21
  • 11
    Nice trick. I replaced `border` with `outline` though. It was much clearer to find the culprit that way (outline doesn't make boxes larger, it just drew lines "over" it) – Mariusz Pawelski May 19 '21 at 11:52
  • I spent hours trying to find the problem and I couldn't use overflow-x: hidden; because I have sticky elements. This helped me fix it in seconds! – Kaleba KB Keitshokile Oct 19 '21 at 17:05
  • Mine turned out to be a hidden (by default) element too that was not revealed by the accepted answer. Baptiste's answer (https://stackoverflow.com/a/67834009/145725) worked so I've suggested an edit to include his helpful addition – Matthew Dec 31 '22 at 04:11
93

An excellent article by Chris Coyier explains everything you need to know about this problem.

after reading this article, I used this code in my console to find the element responsible for vertical scrolling:

press F12 in your Browser then choose console and paste the below code there and press enter:

var all = document.getElementsByTagName("*"), i = 0, rect, docWidth = document.documentElement.offsetWidth;
for (; i < all.length; i++) {
    rect = all[i].getBoundingClientRect();
    if (rect.right > docWidth || rect.left < 0){
        console.log(all[i]);
        all[i].style.borderTop = '1px solid red';
    }
}

Update:
if the above code didn't work, it might be an element inside an iframe that makes the page scroll vertically.

in this scenario you can search through the iframes using this code:

var frames = document.getElementsByTagName("iframe");
for(var i=0; i < frames.length; i++){
   var frame = frames[i];
   frame = (frame.contentWindow || frame.contentDocument);
   var all = frame.document.getElementsByTagName("*"),rect,
       docWidth = document.documentElement.offsetWidth;
   for (var j =0; j < all.length; j++) {
       rect = all[j].getBoundingClientRect();
       if (rect.right > docWidth || rect.left < 0){
           console.log(all[j]);
           all[j].style.borderTop = '1px solid red';
       }
   }
}
Mosijava
  • 3,941
  • 3
  • 27
  • 39
  • Also, if you want to test this issue, I''ve created a post about this with cypress: https://www.ismaelramos.dev/how-to-test-if-there-is-any-element-outside-the-viewport-with-cypress/ – ismaestro Feb 22 '22 at 07:44
  • The first snippet worked for me! – manudicri Aug 28 '22 at 15:01
  • If you want to do this for vertical scrollbar: `var all = document.getElementsByTagName("*"), i = 0, rect, docHeight = document.documentElement.offsetHeight; for (; i < all.length; i++) { rect = all[i].getBoundingClientRect(); if (rect.right > docHeight || rect.left < 0){ console.log(all[i]); all[i].style.borderLeft = '1px solid red'; } }` – Junaid Jun 26 '23 at 14:24
28

Find the culprit by copy paste the below js code in your URL address bar.

javascript:(function(d){var w=d.documentElement.offsetWidth,t=d.createTreeWalker(d.body,NodeFilter.SHOW_ELEMENT),b;while(t.nextNode()){b=t.currentNode.getBoundingClientRect();if(b.right>w||b.left<0){t.currentNode.style.setProperty('outline','1px dotted red','important');console.log(t.currentNode);}};}(document));
brandito
  • 698
  • 8
  • 19
Tamilselvan K
  • 1,133
  • 11
  • 10
  • 2
    Wow this is amazing. The accepted answer with adding a border to everything didn't help me, the scrollbar disappeared when I did that. – William Randokun Jun 16 '20 at 12:11
  • 2
    I like that solution however, you should explain it and it marks elements which are cut off on the left which typically (except RTL) doesn't cause a scroll bar. – rekire Jun 22 '20 at 11:07
  • 3
    One can just copy paste the following in the browser console, if pasting it on URL address bar is not working for some reason ``` (function(d){var w=d.documentElement.offsetWidth,t=d.createTreeWalker(d.body,NodeFilter.SHOW_ELEMENT),b;while(t.nextNode()){b=t.currentNode.getBoundingClientRect();if(b.right>w||b.left<0){t.currentNode.style.setProperty('outline','1px dotted red','important');console.log(t.currentNode);}};}(document)); ``` – Samyak Bhuta Aug 13 '20 at 06:01
  • Thank You, This is the best answer.✅, the accepted answer is not good enough like this. – Hamidreza Khorammfar Sep 05 '22 at 13:08
9

Add this to your css file:

* {
  outline: 1px solid #f00 !important;
  opacity: 1 !important;
  visibility: visible !important;
}

It's making sure everything is visible while debugging with the red border.

Baptiste Arnaud
  • 2,522
  • 3
  • 25
  • 55
6

Overflowing elements

My quick solution with jQuery, stijn de ryck's createXPathFromElement and the console:

/**
 * Show information about overflowing elements in the browser console.
 *
 * @author Nabil Kadimi
 */
var overflowing = [];
jQuery(':not(script)').filter(function() {
    return jQuery(this).width() > jQuery(window).width();
}).each(function(){
    overflowing.push({
        'xpath'    : createXPathFromElement(jQuery(this).get(0)),
        'width'    : jQuery(this).width(),
        'overflow' : jQuery(this).width() - jQuery(window).width()
    });
});
console.table(overflowing);


/**
  * Gets the Xpath of an HTML node
  *
  * @link https://stackoverflow.com/a/5178132/358906
  */
function createXPathFromElement(e){for(var t=document.getElementsByTagName("*"),a=[];e&&1==e.nodeType;e=e.parentNode)if(e.hasAttribute("id")){for(var s=0,l=0;l<t.length&&(t[l].hasAttribute("id")&&t[l].id==e.id&&s++,!(s>1));l++);if(1==s)return a.unshift('id("'+e.getAttribute("id")+'")'),a.join("/");a.unshift(e.localName.toLowerCase()+'[@id="'+e.getAttribute("id")+'"]')}else if(e.hasAttribute("class"))a.unshift(e.localName.toLowerCase()+'[@class="'+e.getAttribute("class")+'"]');else{for(i=1,sib=e.previousSibling;sib;sib=sib.previousSibling)sib.localName==e.localName&&i++;a.unshift(e.localName.toLowerCase()+"["+i+"]")}return a.length?"/"+a.join("/"):null}

//**/
Nabil Kadimi
  • 10,078
  • 2
  • 51
  • 58
  • 3
    Just a note, if you're using some sort of sliding animations(carousel, etc) they will appear in this list too. – sudonitin Jun 18 '20 at 16:07
1

Adding a border to everything made the problem go away for me. The culprit was a drop-down menu hidden with opacity: 0. I actually found it by process of elimination - delete elements in the DevTools one by one, starting with parent elements and moving down the tree.

This would have done it for me:

* {
  opacity: 1 !important;
  visibility: visible !important;
}
Elad
  • 2,087
  • 1
  • 16
  • 30
Huon
  • 300
  • 3
  • 10
1

Actually what worked for me is deleting elements one by one. I tried some of the scripts / css here and they didn't work.

You can easily do a kind of tree search by hand that is quite efficient: Start at the children of the body tag, delete them one by one until the problem is fixed. Once you have the culprit, you restore it (reload page) and delete its children one by one until you find which of them is at fault. Repeat with its children and their children and so on.

Nobody
  • 192
  • 3
  • 12
0

add your chrome snippets >>> by inspect > sources > snippets > new snippet > add code $("*").css("border","2px solid #f00") >> click ctrl+enter

and the culprit appeared

In addition, it will be saved on the browser and used easily afterward

  • This does not provide an answer to the question. Once you have sufficient [reputation](https://stackoverflow.com/help/whats-reputation) you will be able to [comment on any post](https://stackoverflow.com/help/privileges/comment); instead, [provide answers that don't require clarification from the asker](https://meta.stackexchange.com/questions/214173/why-do-i-need-50-reputation-to-comment-what-can-i-do-instead). - [From Review](/review/late-answers/31001410) – Michal Feb 11 '22 at 00:58
0

style="white-space:pre-wrap; word-break:break-word"

Tamilselvan K
  • 1,133
  • 11
  • 10
0

in Nextjs, adding overflow-x:hidden to *{} in global.css solves the issue.

0

Try deleting elements from the DOM one by one using Chrome DevTools (Elements inspector). And determine which element's removal makes the horizontal scroll disappear.

sga4
  • 350
  • 4
  • 15
0

I had an element with width: 100% with padding. Setting box-sizing: border-box fixed the horizontal scroll for me, because the padding was being applied in addition to 100% width.

ie. the width was (100% + padding) prior to setting the box-sizing property.

w3-schools explains box-sizing property:

The box-sizing property allows us to include the padding and border in an element's total width and height. If you set box-sizing: border-box; on an element, padding and border are included in the width and height

sga4
  • 350
  • 4
  • 15
0

Go to the inspector and chechk the blue squares and press wich you see with what is doing the overflow

  • { outline: 1px solid #f00 !important; }
David P.
  • 11
  • 2
  • This solution has already been proposed multiple times in this thread – Sigurd Mazanti Mar 30 '23 at 07:59
  • This does not provide an answer to the question. Once you have sufficient [reputation](https://stackoverflow.com/help/whats-reputation) you will be able to [comment on any post](https://stackoverflow.com/help/privileges/comment); instead, [provide answers that don't require clarification from the asker](https://meta.stackexchange.com/questions/214173/why-do-i-need-50-reputation-to-comment-what-can-i-do-instead). - [From Review](/review/late-answers/34105179) – Syfer Apr 01 '23 at 10:27
0

In most cases you can't rely on "inspection borders", since a single element can cause others to also grow. In my case it was straight up misleading, since the border was completly within the viewport.
The most reliable method is to remove an element, then check if the content is still overflowing; so I wrote a snippet to do just that without dependencies.

(() => {
let allElements = document.body.querySelectorAll('*');
let elements = [];

// Get leaf nodes
allElements.forEach(element => {
    const descendants = element.querySelectorAll('*');
    if (descendants.length === 0) {
        elements.push(element);
    }
});

// Travel the dom tree upwards
while (elements.length > 0) {
    let el = elements.splice(0, 1)[0];
    // Hide current element
    el.style.display = "none";
    // Check if it solved the overflow
    if (document.body.clientWidth >= document.body.scrollWidth) {
        console.log("Found element causing overflow:", el)
        // Mark with red border
        el.style.border = "1px solid red"
        el.style.display = "";
        return
    }
    el.style.display = "";
    // Add its parent and continue
    if (el.parentElement !== document.body) elements.push(el.parentElement)
}})()

Noel Nemeth
  • 646
  • 11
  • 21