CSS overflow-x: visible; and overflow-y: hidden; causing scrollbar issue
Asked Answered
I

10

663

Suppose you have some style and the markup:

ul
{
  white-space: nowrap;
  overflow-x: visible;
  overflow-y: hidden;
/* added width so it would work in the snippet */
  width: 100px; 
}
li
{
  display: inline-block;
}
<div>
  <ul>
    <li>1</li> <li>2</li> <li>3</li>
    <li>4</li> <li>5</li> <li>6</li>
    <li>7</li> <li>8</li> <li>9</li>
    <li>1</li> <li>2</li> <li>3</li>
    <li>4</li> <li>5</li> <li>6</li>
    <li>7</li> <li>8</li> <li>9</li>
    <li>1</li> <li>2</li> <li>3</li>
    <li>4</li> <li>5</li> <li>6</li>
    <li>7</li> <li>8</li> <li>9</li>
  </ul>
</div>

When you view this. The <ul> has a scroll bar at the bottom even though I've specified visible and hidden values for overflow x/y.

(observed on Chrome 11 and opera (?))

I'm guessing there must be some w3c spec or something telling this to happen but for the life of me I can't work out why.

JSFiddle

UPDATE:- I found a way to achieve the same result by adding another element wrapped around the ul. Check it out.

Iodous answered 21/6, 2011 at 7:45 Comment(6)
What is your desired result? jsfiddle.net/Kyle_Sevenoaks/3xv6A/2Pham
@kyle it should look a little more like: jsfiddle.net/3xv6A/5 Unfortunately if i set overflow-x hidden; it removes the scroll but as i need the li elements to hide the border at the bottom so it gives that desired dashed effect. I don't uderstand why overflow-x: visible creates a scroll bar. It shouldn't afaik.Iodous
@JamesKhoury can you elaborate a bit in your solution? I can't really make it workSarcoma
@GeorgeKatsanos The workaround: jsfiddle.net/3xv6A/9 relies upon the parent being overflow: hidden; and a child inserted around the <ul> being overflow: visible.Iodous
@JamesKhoury Do you think it can work for embed.plnkr.co/2rbaISwvzuKhyPEFpBKDSarcoma
@JamesKhoury I'm still seeing a scrollbar in all proposed solutions. Perhaps a new Chrome bug? Or was it supposed to be there (look at the bottom of the container).Wallop
I
935

After some serious searching it seems i've found the answer to my question:

from: http://www.brunildo.org/test/Overflowxy2.html

In Gecko, Safari, Opera, ‘visible’ becomes ‘auto’ also when combined with ‘hidden’ (in other words: ‘visible’ becomes ‘auto’ when combined with anything else different from ‘visible’). Gecko 1.8, Safari 3, Opera 9.5 are pretty consistent among them.

also the W3C spec says:

The computed values of ‘overflow-x’ and ‘overflow-y’ are the same as their specified values, except that some combinations with ‘visible’ are not possible: if one is specified as ‘visible’ and the other is ‘scroll’ or ‘auto’, then ‘visible’ is set to ‘auto’. The computed value of ‘overflow’ is equal to the computed value of ‘overflow-x’ if ‘overflow-y’ is the same; otherwise it is the pair of computed values of ‘overflow-x’ and ‘overflow-y’.

Short Version:

If you are using visible for either overflow-x or overflow-y and something other than visible for the other, the visible value is interpreted as auto.

Iodous answered 22/6, 2011 at 0:13 Comment(25)
@kevin If you see the update in my question you'll see that i added an extra element. I can't specifically say this will work for you. jsfiddle.net/3xv6A/9Iodous
I understand that the W3C specifies it this way, but what is the motivation behind it? I find it quite weird and inconsistent behavior, resulting in messy work-arounds which require adding trivial HTML-elements.Bambara
@Bambara I agree, Hopefully someone decides to update the spec.Iodous
You're right but it makes no sense. The most common reason you'd even want x and y is so you can make one hidden and the other visible.Tude
This is crippling. Why can't we allow overflow-x:visible during overflow-y:hidden without a parent/child hack? Pretty bunk, IMO.Viddah
@Erwin: They probably decided that having an element with content overflowing in both x and y directions and having one clipped and the other showing would look weirder than forcing content to either be clipped in both directions or not at all (not to mention the potential layout issues that come with visible vs any other value). See these proofs-of-concept for what it would look like had they allowed overflow-x: visible with overflow-y: hidden and with overflow-y: auto.Instrumentation
Given that the OP was trying to achieve something completely different than what is shown in my examples, and that everybody seems to be kvetching about the same problem as the OP, I suspect there is a different problem at hand that is somehow necessitating setting conflicting overflow values, though given the lack of a description I don't know what it might be. The code given in the question does not even sufficiently reproduce the problem, let alone begin to describe it.Instrumentation
This is totally crippling. I was trying to make a bunch of dropdown links in a Bootstrap navbar scroll horizontally, but that breaks the dropdowns, which rely on overflow-y: visible. Boo CSS!Joshia
BoltClock's message and clever JSFiddle demonstration of what it would look like if separate overflows is very important and shows potential reasons why it is a bad idea but there are many examples, such as floating sub-menus, where absolute or relative positioning without scroll-bars just needs separate overflow control (to avoid other complicated solutions). W3C could allow separate overflow control and just highlight the issues and problems it causes.Gemmagemmate
There is of course the quite simple solution to this problem which should work in most scenarios (but isn't ideal) of having two containing elements for the content, one inside the other and with one having overflow-x or overflow-y set to overflow or to contain and scroll and the other element set the opposite axis and set to the opposite containment.Gemmagemmate
@Edward: "W3C could allow separate overflow control and just highlight the issues and problems it causes." Yeah, and authors will still complain mindlessly like they've been doing here - except about the issues and problems themselves instead, but likewise without stopping for a second to think about why they occur in the first place. Bonus points should the issues and problems manifest differently in different browsers. There is a reason why overflow values other than visible cause a block box to establish a new block formatting context.Instrumentation
@BoltClock: That's not mindless complaining. This behaviour is anti-intuitive and seriously degrades the usefulness of overflow-[xy]. I don't care about the technical reasons why the spec is bad, and everyone here agrees that the implementation in Firefox and Edge is how it should work.Drumhead
@wortwart: What implementation are you referring to? All UAs clamp visible to auto in the manner described by the spec - and I find it to be perfectly intuitive behavior, even though I agree that it does degrade the usefulness of overflow-[xy], e.g. in situations where you can guarantee that content isn't going to overflow in the axis with overflow: visible.Instrumentation
@Instrumentation No, Firefox doesn't: jsfiddle.net/0d34oyxL/1 (I was wrong about Edge - my original usecase was with SVG which complicated matters)Drumhead
@wortwart: Firefox doesn't render scrollbars until a minimum height (the value of this minimum depends on the OS theme, but in general Firefox cannot scale its scrollbar controls), but the computed value of overflow-y is still auto, and the content can still scroll normally. Granted, the scrollbars are what people seem to be complaining about...Instrumentation
W3C say about combination of visible with auto or scroll but nothing about combination of visible with hiddenDuvalier
Your linked spec (the WD) says nothing about overflow, it's probably been changed since. Do you know what this means, or where to find your snippet in official specs?Cyclostyle
Okay, MDN links to CSS overflow module 3 spec, which only mentions about the restriction in the last section (computed value column).Cyclostyle
It's quite unfair and ad hominem to label the complaints "mindless". The fact is that the API offers what appear to be two independent variables that are very poorly documented to, in certain specific cases, automatically change themselves based on the value of the other. An improvement to the API would make it impossible to even attempt to set x: auto, y:hidden (and similar).Insignificant
Just dropping by to pile on that this is severely unintuitive behavior. Why in the world would anyone specifically setting x: visible/y: scroll want x: auto/y: scroll?Iconostasis
That's not reallly a solution thoSkillful
This is the worst CSS decision ever made.Scourings
Why is anybody surprised that CSS has a badly designed feature? This is honestly the worst designed language I've seen, but nobody can touch it because any non-backwards compatible change to it would destroy parts of the webNit
The quote mentioned in the answer doesn't seem to cover the case of overflow-x: hidden; overflow-y: visible. However, I have found another statement in the (newer?) CSS Overflow Model 3 spec which does explain the behavior we are all so annoyed by: "The visible/clip values of overflow compute to auto/hidden (respectively) if one of overflow-x or overflow-y is neither visible nor clip."Christean
The unintuitive overflow-x and overflow-y behavior is a CSS bug worth breaking the internet to fix.Barbera
L
212

another cheap hack, which seems to do the trick:

style="padding-bottom: 250px; margin-bottom: -250px;" on the element where the vertical overflow is getting cutoff, with 250 representing as many pixels as you need for your dropdown, etc.

Laurentian answered 18/9, 2016 at 4:9 Comment(7)
This makes the horizontal scrollbar appear that far downAstereognosis
This also blocks pointer events for 250px below the element. But I found a way around that, and this solution is what I'm using.Devlin
In my particular scenario, where removing position: relative or using wrappers was not possible, this was the only solution that worked, although it did also require adding a lot of ugly margins to child elements inside the element which I wanted to set overflow-x: hidden on to compensate for the hacky padding. This saved me, though, so thanks!Typewriting
I tried this horizontally it results in the vertically scrollable div being horizontally scrollable too.Brookebrooker
2020, this helped me...although for me it didn't work to do it that way. I had to add the padding, but then add a negative margin to the preceding element, in order to close the gap. Still, this set me in the right direction, thanks!Loriloria
99.9% of us who suffer from this problem don't have the option to make the container taller.Prussia
this hides the scrollbar any way to work around it?Milamilady
P
110

I originally found a CSS way to bypass this when using the Cycle jQuery plugin. Cycle uses JavaScript to set my slide to overflow: hidden, so when setting my pictures to width: 100% the pictures would look vertically cut, and so I forced them to be visible with !important and to avoid showing the slide animation out of the box I set overflow: hidden to the container div of the slide. Hope it works for you.

UPDATE - New Solution:

Original problem -> http://jsfiddle.net/xMddf/1/ (Even if I use overflow-y: visible it becomes "auto" and actually "scroll".)

#content {
    height: 100px;
    width: 200px;
    overflow-x: hidden;
    overflow-y: visible;
}

The new solution -> http://jsfiddle.net/xMddf/2/ (I found a workaround using a wrapper div to apply overflow-x and overflow-y to different DOM elements as James Khoury advised on the problem of combining visible and hidden to a single DOM element.)

#wrapper {
    height: 100px;
    overflow-y: visible;
}
#content {
    width: 200px;
    overflow-x: hidden;
}
Paff answered 2/7, 2013 at 18:3 Comment(11)
How does this apply? It does not seem to work on overflow-x or overflow-y.Iodous
I added a better / clear example of what I was talking about, actually is quite the same solution as OP updated on his postPaff
@Macumbaomuetre That is clearer, thank you +1. It is similar to the "update" I added. Originally I wasn't able to alter the wrapping div and my solution ended up similar to: jsfiddle.net/3xv6A/338Iodous
This solution does not apply. The question is overflow-x:visible; and overflow-y:hidden. Not the other way around.Guevara
@Gemmagemmate how would you swap them? I tried it in chrome with this fork: jsfiddle.net/ad1941k9 and it seems like it doesn't work as expected.Satang
@TomasJansson Sorry, I just thought that it would be easy to swap them but I didn't test it. Jakobosky's comment about the solution not applying is true currently. I have removed my untrue comment.Gemmagemmate
@TomasJansson @Gemmagemmate It does work, you just have to swap where you apply the overflow-x and -y: updated fiddle.Casablanca
The wrapper hack works except for some kinds inner elements. In my case, I found that if the inner element is a fieldset element, adding a div as a wrapper will not get the hack to work. Also some inner elements (span) need to have display:block explicitly stated in order for the wrapper hack to work.Tedesco
this fails as soon as the wrapper gains a width for some reason - jsfiddle.net/ad1941k9/16Residency
The image link in your original problem jsfiddle is deadCacophonous
And so is the one in the solution fiddleCacophonous
G
36

For my use case, adding overflow-x:visible; overflow-y:clip onto the div that has the overflow seems to give me the desired effect of hiding overflow on the Y axis while not giving me a scrollbar on the X axis (i have a carousel slider that was loading images full-size before scaling them back down again, and these images were taking up 75% of the page height on load, hence wanting no overflow-y).

No parent wrapper div was needed, just a fixed height set on the overflowing element. I realise this solution may not work for everyone, but it could certainly help some.

Gala answered 29/10, 2021 at 10:4 Comment(10)
Be aware that overflow: clip is not yet supported on Safari.Diatribe
@TimDown Support was added on 2nd Feb 2022, though I'm not sure if this is live yet. Please see the dev notes here -> developer.apple.com/safari/technology-preview/release-notes and here -> trac.webkit.org/changeset/288973/webkitGala
Yes, I've used this aswell works fineSkillful
EDIT : just like @TimDown said it is NOT comptable with safari... I have the Monterey OS, Safari v15.4 and it's not supported.Skillful
@AndrewWest it might be live but considering that a lot of people I know CAN'T make the updates because of the storage the clip method is still considered "not supported" :/Skillful
@Skillful You need to update your Safari version then. It only works on >15.6. I'm not sure what you mean by "unable to update due to storage" but if you're simply referring to the fact that you have no HDD/SSD space available, then that has nothing to do with the feature support.Gala
@Skillful What?? You stated you couldn't update due to having no storage available. You don't need a whole new mac, just a replacement and/or additional storage drive, so that you can update. But if you think you'll be able to run a machine with no storage available, you're only fooling yourself, because that's going to run terribly slow. macOS Monterey ships with Safari 16, so why you're still on 15.4 is another question entirely, unless you've upgrade from an even earlier version, but then back to my original point, you won't be able to keep using a machine that has no storage available.Gala
I guess it is more correct to fix the JS code of your slider so it makes original big images hidden until they are loaded, and then make them visible after they are ready, than to just clip out big images so a user can see regions of them during page loadHair
@Skillful So don't use the clip property then... find your own solution instead of chewing my ear off. I never stated that this was a fix-all answer, but you seem to have taken that impression.Gala
It's late 2023 and support seems pretty good now: caniuse.com/mdn-css_types_overflow_clip. I reckon it's the best solution right now.Pentane
F
19

I've run into this issue when trying to build a fixed positioned sidebar with both vertically scrollable content and nested absolute positioned children to be displayed outside sidebar boundaries.

My approach consisted of separately apply:

  • an overflow: visible property to the sidebar element
  • an overflow-y: auto property to sidebar inner wrapper

Please check the example below or an online codepen.

html {
  min-height: 100%;
}
body {
  min-height: 100%;
  background: linear-gradient(to bottom, white, DarkGray 80%);
  margin: 0;
  padding: 0;
}

.sidebar {
  position: fixed;
  top: 0;
  right: 0;
  height: 100%;
  width: 200px;
  overflow: visible;  /* Just apply overflow-x */
  background-color: DarkOrange;
}

.sidebarWrapper {
  padding: 10px;
  overflow-y: auto;   /* Just apply overflow-y */
  height: 100%;
  width: 100%;
}

.element {
  position: absolute;
  top: 0;
  right: 100%;
  background-color: CornflowerBlue;
  padding: 10px;
  width: 200px;
}
<p>Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?</p>
<div class="sidebar">
  <div class="sidebarWrapper">
    <div class="element">
      I'm a sidebar child element but I'm able to horizontally overflow its boundaries.
    </div>
    <p>This is a 200px width container with optional vertical scroll.</p>
    <p>Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?</p>
  </div>
</div>
Fink answered 26/1, 2017 at 14:2 Comment(3)
I'm pretty sure this is the same solution as others have presented except with auto instead of hidden.Iodous
Hi, I have a similar problem. Could you please have a look at my question here: #76568778. Thanks.Laborsaving
Thanks I ran into this very issue with a scrollable list where each item scales up when hovered so I needed overflow-y to be visible while overflow-x scrolls. The main issue as described in the docs is those two settings don't mix since overflow-y will become auto. Setting the list to overflow: visible allows elements to break outside the container without being clipped (in both directions), and then setting overflow-x: auto on the new parent container makes it scroll in the x direction instead of being visible, perfect!Determinative
S
19

There is now a new way of addressing this issue - if you remove position: relative from the container which needs to have the overflow-y visible, you can have overflow-y visible and overflow-x hidden, and vice versa (have overflow-x visible and overflow-y hidden, just make sure the container with the visible property is not relatively positioned).

See this post from CSS Tricks for more details - it worked for me: https://css-tricks.com/popping-hidden-overflow/

Stockroom answered 17/9, 2018 at 20:53 Comment(2)
but that would require some javascript to position the element correctly if it is absoluteJunitajunius
At this point you might as well use position: fixed. Keeping any ancestors from being positioned isn't very realistic.Silures
M
15

I was facing the same issue, the following solution worked (styles are applied to the parent block)

overflow-y: visible;
overflow-x: clip;
Microphone answered 7/6, 2022 at 12:37 Comment(0)
C
10

I used the content + wrapper approach... but I did something different than mentioned so far: I made sure that my wrapper's boundaries did NOT line up with the content's boundaries in the direction that I wanted to be visible.

Important NOTE: It was easy enough to get the content + wrapper, same-bounds approach to work on one browser or another depending on various CSS combinations of position, overflow-*, etc., but I never could use that approach to get them all correct (Edge, Chrome, Safari, etc.).

But when I had something like:

#hack_wrapper {
    position:absolute; 
    width:100%; 
    height:100%; 
    overflow-x:hidden;
}

#content_wrapper {
    position:absolute; 
    width:100%; 
    height:15%; 
    overflow:visible;
}
<!-- #hack_wrapper div created solely for this purpose --> 
<div id="hack_wrapper">
    <div id="content_wrapper">         
          ... this is an example of some content with far too much horizontal content... like, way, way, way too much content.
    </div>
</div>

... all browsers were happy.

Cobalt answered 14/4, 2016 at 19:57 Comment(0)
H
3

This is what worked for me:

On the container:

  .container {
      overflow-y: visible;
      overflow-x: clip;
  }

On the contained item:

  .item {
      width: 500px; /* any fixed value or it did not render in the browser */
  }
Hypotenuse answered 11/4, 2023 at 14:12 Comment(1)
Thank you so much, I've never heard of clip, that is super helpful when you need to hide one axis and make the other visible. Cheers, man!Isotherm
J
-6

A small "hack" that works very well if you only want the first row visible (but still need overflow):

set gap really high so you are sure the second row is pushed out of the screen - eg:

gap: 10000rem;

It is really hacky but works great for something like a desktop nav with menus that need to overflow...

Jameejamel answered 11/7, 2021 at 19:35 Comment(1)
The gap property only applies (and is only designed for) flexbox and grid layouts. If you aren't using display: grid or display: flex, it does not do anything.Thiol

© 2022 - 2024 — McMap. All rights reserved.