ChatGPT解决这个技术问题 Extra ChatGPT

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

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; }

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

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.

What is your desired result? jsfiddle.net/Kyle_Sevenoaks/3xv6A/2
@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.
@JamesKhoury can you elaborate a bit in your solution? I can't really make it work
@GeorgeKatsanos The workaround: jsfiddle.net/3xv6A/9 relies upon the parent being overflow: hidden; and a child inserted around the <ul> being overflow: visible.
@JamesKhoury Do you think it can work for embed.plnkr.co/2rbaISwvzuKhyPEFpBKD

c
callum

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.


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.
@Erwin I agree, Hopefully someone decides to update the spec.
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.
This is crippling. Why can't we allow overflow-x:visible during overflow-y:hidden without a parent/child hack? Pretty bunk, IMO.
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!
J
Justin

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.


This makes the horizontal scrollbar appear that far down
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.
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!
I tried this horizontally it results in the vertically scrollable div being horizontally scrollable too.
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!
M
Mosh Feu

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;
}

How does this apply? It does not seem to work on overflow-x or overflow-y.
@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/338
This solution does not apply. The question is overflow-x:visible; and overflow-y:hidden. Not the other way around.
@TomasJansson @Edward It does work, you just have to swap where you apply the overflow-x and -y: updated fiddle.
this fails as soon as the wrapper gains a width for some reason - jsfiddle.net/ad1941k9/16
A
Andrea Carraro

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; }

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?


I'm pretty sure this is the same solution as others have presented except with auto instead of hidden.
T
TylerH

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/


but that would require some javascript to position the element correctly if it is absolute
A
Andrew West

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.


Woo!! Finally a real solution :D
Worked for me seamlessly.. thanks!!
man you're saint
Be aware that overflow: clip is not yet supported on Safari.
@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/webkit
T
TylerH

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; }

... this is an example of some content with far too much horizontal content... like, way, way, way too much content.

... all browsers were happy.


V
Victor

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

overflow-y: visible;
overflow-x: clip;

L
Lars Ejaas

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...


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.