Overflow Issues In CSS — Smashing Magazine


In this article, we will explore the causes of overflow issues and how to solve them. We will also explore how modern features in the developer tools (DevTools) can make the process of fixing and debugging easier.

If you’re a front-end developer, you may have come across horizontal scrollbar issues, especially on mobile. Because there are many causes of scrollbar problems, there is no straightforward solution. Some issues can be fixed quickly, and some need a little debugging skill.

What Is an Overflow Issue?

Before discussing overflow issues, we should ascertain what one is. An overflow issue occurs when a horizontal scrollbar unintentionally appears on a web page, allowing the user to scroll horizontally. It can be caused by different factors.

A wireframe example of a website with six boxes showing as placeholders for text or images
Overflow with a fixed-width element that is wider than the viewport. (Large preview)

It could occur because of unexpectedly wide content or a fixed-width element that is wider than the viewport. We will explore all of the causes in this article.

How to Spot Overflow

An important part of solving this issue is noticing it in the first place. If we know when and where it happens, we can home in on that part of a web page. There are different ways to detect overflow, from manually scrolling to the left or right or by using JavaScript.

Let’s explore the ways to detect overflow.

The first way to discover an overflow issue is by scrolling the page horizontally. If you’re able to scroll, this is a warning that something is wrong with the page.

An example of a web page being able to horizontally scroll through its content
Whenever you can scroll, there is an overflow in play. (Large preview)

Using JavaScript to Find Elements Wider Than the Body

We can add a snippet to the browser console to show any elements wider than the body. This is handy for pages with a lot of elements.

var docWidth = document.documentElement.offsetWidth; [].forEach.call( document.querySelectorAll('*'), function(el) { if (el.offsetWidth > docWidth) { console.log(el); } }
);

CSS Outline to the Rescue

Applying CSS’ outline to all elements on the page gives us a hint about elements that go beyond the page’s body.

* { outline: solid 1px red;
}
The same example showing with an element being portrayed outside the viewport
A scrollbar appear when an element is outside the viewport. (Large preview)

Even better, Addy Osmani has a script that adds an outline to each element on the page with a random color.

[].forEach.call($$("*"),function(a){a.style.outline="1px solid #"+(~~(Math.random()*(1<<24))).tostring(16)})>

Overflow Label in Firefox

Firefox has a helpful feature that tells you which elements are causing overflow. Hopefully, other browsers will add this!

The same wireframe example explained with the help of a useful feature in Firefox
An overflow badge displayed in the Firefox DevTools. (Large preview)

Deleting Page Elements

Another common way is to open the browser’s DevTools and start deleting elements one by one. Once the issue disappears, then the section you’ve just deleted is probably the cause. I found this method useful in cases where you’ve identified the issue but don’t know why it’s happening.

Once you’ve found where the overflow is happening, then it will be easier to make a reduced test case for further debugging.

Common Overflow Issues

Fixed-Width Elements

One of the most common causes of overflow is fixed-width elements. Generally speaking, don’t fix the width of any element that should work at multiple viewport sizes.

.element { /* Don’t do this */ width: 400px;
}
Mobile wireframe example showing fixed-width elements outside of the viewport
Mobile wireframe example showing fixed-width elements outside of the viewport. (Large preview)

Using Flexbox Without Wrapping

As useful as Flexbox is, not allowing items to wrap to a new line when no space is available is risky.

.parent { display: flex;
}

Here, flex items might cause horizontal overflow in case the space isn’t enough to fit them all in one line:

Flex items causing horizontal overflow by appearing outside the viewport
Flex items causing horizontal overflow by appearing outside the viewport. (Large preview)

Make sure to use flex-wrap: wrap when the flex parent is supposed to work at different viewport sizes.

.parent { display: flex; /* Do this */ flex-wrap: wrap;
}

CSS Grid

When you’re using CSS grid, designing responsively is important. Take the following grid:

.wrapper { display: grid; grid-template-columns: 1fr 300px 1fr; grid-gap: 1rem;
}

The example above will work great unless the viewport is narrower than 300 pixels. If it is, then overflow will occur.

Overflow showing while the grid item has a width of 300px
Overflow showing while the grid item has a width of 300px. (Large preview)

To avoid such an issue, use grid only when enough space is available. We can use a CSS media query like so:

.wrapper { display: grid; grid-template-columns: 1fr; grid-gap: 1rem;
} @media (min-width: 400px) { .wrapper { grid-template-columns: 1fr 300px 1fr; }
}

Long Words

Another common reason for overflow is a long word that doesn’t fit in the viewport. This happens more on mobile because of the viewport’s width.

An example of using long words that do not and cannot fit within the viewport’s width
An example of using long words that do not and cannot fit within the viewport’s width. (Large preview)

To fix this, we need to use the overflow-wrap property.

.article-content p { overflow-wrap: break-word;
}

I’ve written a detailed article on handling both short and long content with CSS.

This fix is particularly useful with user-generated content. A perfect example of this is a comments thread. A user might paste a long URL in their comment, and this should be handled with the overflow-wrap property.

Minimum Content Size in CSS Flexbox

Another interesting cause of overflow is the minimum content size in Flexbox. What does this mean?

Another example of using words that are too long to fit in
Another example of using words that are too long to fit in. (Large preview)

According to the specification:

“By default, flex items won’t shrink below their minimum content size (the length of the longest word or fixed-size element). To change this, set the min-width or min-height property.”

This means that a flex item with a long word won’t shrink below its minimum content size.

To fix this, we can either use an overflow value other than visible, or we can set min-width: 0 on the flex item.

.card__name { min-width: 0; overflow-wrap: break-word;
}
A before and after comparison or breaking long words to fit in on the next line and stay within the viewport
A before and after comparison or breaking long words to fit in on the next line and stay within the viewport. (Large preview)

Minimum Content Size in CSS Grid

As with Flexbox, we have the same concept of minimum content size with CSS Grid. However, the solution is a bit different. CSS-Tricks refers to it as “grid blowout”.

An example of a grid blowout in which content does not fit into the given size or width
An example of a grid blowout in which content does not fit into the given size or width. (Large preview)

Let’s explore the issue. Suppose we have a wrapper with an aside and a main section laid out with CSS grid.

.wrapper { display: grid; grid-template-columns: 248px 1fr; grid-gap: 40px;
}

Also, we have a scrolling section in the main section, for which I’ve used flexbox.

.section { display: flex; gap: 1rem; overflow-x: auto;
}

Notice that I didn’t add flex-wrap, because I want the flex items to be on the same line. This didn’t work, however, and it’s causing horizontal overflow.

To fix this, we need to use minmax() instead of 1fr. This way, the main element’s minimum content size won’t be auto.

.wrapper { display: grid; grid-template-columns: 248px minmax(0, 1fr); grid-gap: 40px;
}

Negative Margins

An element positioned off screen can cause overflow. Usually, that is because the element has a negative margin.

In the following example, we have an element with a negative margin, and the document’s language is English (i.e. left to right).

.element { position: absolute; right: -100px;
}
An element that is positioned off-screen shown on the right
An element that is positioned off-screen shown on the right. (Large preview)

Interestingly, when the element is positioned on the opposite side, there is no overflow. Why is that?

An element that is positioned off-screen shown on the left
An element that is positioned off-screen shown on the left. (Large preview)

I faced this issue lately and wrote about it. It turns out that this behavior is intentional. According to the CSS specification:

“UAs must clip the scrollable overflow area of scroll containers on the block-start and inline-start sides of the box (thereby behaving as if they had no scrollable overflow on that side).”

For an English document, the inline-start side is the left side, so any element positioned off-screen on the left will be clipped, and thus there will be no overflow.

If positioning an element off screen is really necessary, make sure to apply overflow: hidden to the parent to avoid any overflow.

Images Without max-width

If you don’t take care of large images ahead of time, you will see overflow. Make sure to set max-width: 100% on all images.

img { max-width: 100%;
}

Viewport Units

Using 100vw does have a downside, which is that it can cause overflow when the scrollbar is visible. On macOS, 100vw is fine and won’t cause horizontal scroll.

On Mac OS with scrollbars hidden that works fine
On Mac OS, scrollbars are hidden. (Large preview)

On Windows, scrollbars are always visible by default, so overflow will occur.

On Windows there is a horizontal overflow when scrolling
On Windows, there is a horizontal overflow when scrolling. (Large preview)

The reason for this is that with the value 100vw, there is no awareness of the width of the browser’s vertical scrollbar. As a result, the width will be equal to 100vw plus the scrollbar’s width. Unfortunately, there is no CSS fix to that.

An example of a page with a viewport of 100vw and 14px on the right being used for the scrollbar
An example of a page with a viewport of 100vw and 14px on the right being used for the scrollbar. (Large preview)

However, we can use JavaScript to measure the viewport’s width excluding the scrollbar.

function handleFullWidthSizing() { const scrollbarWidth = window.innerWidth - document.body.clientWidth document.querySelector('myElement').style.width = `calc(100vw - ${scrollbarWidth}px)`
}

Injected Ads

Ads injected on page load can cause overflow if they’re wider than their parent. Add overflow-x: hidden to the parent element to prevent this.

Mobile viewport with an overflow caused by an ad that is wider than the viewport
Mobile viewport with an overflow caused by an ad that is wider than the viewport. (Large preview)

Double-check every ad on the website to ensure that it’s not causing overflow.

Is Applying overflow-x: hidden to body a Good Idea?

Opting for overflow-x: hidden is like putting on a bandage without addressing the problem. If you have overflow, then it’s better to solve the root issue.

Moreover, applying overflow-x: hidden to the body element is not a good idea because position: sticky won’t work if a parent has overflow-x: hidden.

How to Avoid Overflow in CSS

Below are things to check to reduce overflow issues in CSS. I hope you find it useful!

Test With Real Content

Nothing beats testing with real content on a website. In doing so, you ensure that the layout can handle different varieties of content.

Account for User-Generated Content

For a component like a comments thread, account for cases in which the user will paste a long URL or type a long word, as explained above.

Use CSS Grid and Flexbox Carefully

As useful as CSS grid and flexbox are, they can easily cause overflow if used incorrectly. As we discussed, not using flex-wrap: wrap can cause overflow, as can grid-template-columns: 1fr 350px when the screen is narrower than 350 pixels.

Further Reading on SmashingMag:

Smashing Editorial (vf, il, al)