overflow: clip vs hidden vs scroll
The
overflow property decides what happens when a box's content is bigger than the box itself. There are four possible values, and while hidden and clip look nearly identical visually, they behave differently in ways that trip people up — especially around JavaScript scrolling.visible — the default
Content that's too big simply spills outside the box's edges, rendering on top of whatever is nearby. No clipping, no scrollbars, nothing contained:
CSS
.box {
width: 200px;
height: 100px;
overflow: visible; /* default — content overflows visibly */
}hidden — clips, but still programmatically scrollable
overflow: hidden clips the overflowing content so it never renders outside the box, and it removes any visible scrollbars. But the box is still a scroll container under the hood — it just doesn't expose UI to scroll it:CSS
.box {
width: 200px;
height: 100px;
overflow: hidden; /* clips visually, no scrollbar shown */
}hidden content can still be scrolled with JavaScript or focus
Because the box remains a scroll container, code can still call
element.scrollTo() or element.scrollIntoView() on it, and focusing a scrolled-off form field inside it can programmatically scroll it into view — even though there's no scrollbar for the user to drag. This is occasionally surprising and occasionally exactly what you want (e.g. clipping visually while still allowing a "scroll to error field" script to work).scroll / auto — adds scrollbars
scroll always reserves space for scrollbars, even if the content fits. auto only shows scrollbars when content actually overflows — it's the value you want almost all of the time you need a scrollable box:CSS
.box {
width: 200px;
height: 100px;
overflow: auto; /* scrollbar appears only if content overflows */
}clip — the newest value
overflow: clip clips overflowing content just like hidden does visually, but it does not turn the box into a scroll container at all. There is no scroll position to track, so scrollTo() and scrollIntoView() have no effect, and the browser has slightly less bookkeeping to do — a small but real performance advantage for elements that should never scroll under any circumstance:CSS
.box {
width: 200px;
height: 100px;
overflow: clip; /* clips visually, no scroll container is created */
}Value | Clips overflow | Creates scroll container | Scrollbar shown |
|---|---|---|---|
visible | No | No | No |
hidden | Yes | Yes (scrollable via JS/focus) | No |
scroll | Yes | Yes | Always |
auto | Yes | Yes | Only if content overflows |
clip | Yes | No | No |
hidden vs clip is a subtle but real distinction
Both
hidden and clip look identical on screen for static content. The difference only shows up when something tries to scroll the box programmatically: it works on hidden and silently does nothing on clip. If you rely on scrollIntoView() to bring hidden content into view (a common pattern for validation errors or tabs), reach for hidden — not clip — or the scroll call will be a no-op.overflow: clip also supports an independent inset via overflow-clip-margin, letting you clip a bit outside the box's own edge rather than exactly at it — something hidden can't do.Next
See how a scrollable container can also prevent a fast scroll from chaining into the page behind it: overscroll-behavior.