Csswg-drafts: Make child visible outside of `overflow: hidden`

Created on 8 Jul 2019  Â·  16Comments  Â·  Source: w3c/csswg-drafts

Suggestion

A way to force a child element to appear visible outside of a hidden overflow container.

Example use case

I have a modal element with rounded borders. Because this modal contains an image, I need to use overflow: hidden in order to mask the image inside of the modal element's border—so the image doesn't overflow the modal element's border.

image

This modal element contains another child element which should be allowed to overflow this element—an input with an autocomplete list. Unfortunately however, the overflow: hidden prevents _all_ children from overflowing, so the autocomplete list is clipped:

Here is a reduced test case:

https://jsbin.com/cuxabik/6/edit?html,css,output

What we want:

What we have:

I am not aware of any existing CSS features which solve this problem, but it's quite a common problem to have.

The autocomplete list could exist outside of the overflow container, but then you lose the ability to define its layout in terms of its parent.

Perhaps we could instruct the child element to appear visible outside of its overflow container:

.autocompleteList { container-overflow: visible; }

Related issues/articles

This problem has also been described here: https://css-tricks.com/popping-hidden-overflow/. (Their solution was to revert to JS for calculating layout.)

This problem is potentially related to:

Needs Data Needs Design / Proposal Needs Thought

Most helpful comment

+1 I run into this constantly.

All 16 comments

Thanks for the detailed use cases.

For the case where overflow: hidden is only used to trim the corners of an image, my first instinct is whether there could be another way to do this — a new clip-path value that references the parent's border box, maybe? That way, you're not hiding overflow unless you really want to hide content.

But that doesn't help with the case where you want to extend outside of a scrolling container, but still be positioned relative to an element inside that scroller.

a new clip-path value that references the parent's border box, maybe?

I love the sound of this.

In your particular example, isn't this solved by having a wrapper around the image and adding overflow: hidden to that and you can also add border-radius to it. Like so https://jsbin.com/lewacofiji/1/edit?html,css,output ?
The CSS tricks issue doesn't really seem related.

+1 I run into this constantly.

isn't this solved by having a wrapper around the image and adding overflow: hidden to that and you can also add border-radius to it

That does workaround the issue, but it feels like a hack, no? (Duplicating styles.)

Also, sometimes you don't know what content will appear inside ahead of time because it's dynamic. We just need to clip everything inside _except_ "these" elements.

@domenic and others have begun discussing this to improve the controls/components story for this specific reason, here is the issue: https://github.com/whatwg/html/issues/4633

I agree that this should live in CSS as it is effectively trying to bring the window focusing model that OSes have. As denoted in that thread I think there needs to be some research done as this is effectively trying to do z-index: top but magically to ensure it's the top thing since it's the most recently focused or notification type result. We'll need to define that behavior and what constitutes the winner of this top layer. That said, I'm supportive of us investigating this and making it happen as we'll need it for any popup scenario in controls.

Yeah. @tabatkins and I discussed some potential CSS properties that would make this work, but I'm hesitant to even write them up here, because I still think priority number one is research of the type outlined in https://github.com/whatwg/html/issues/4633. Jumping to particular API proposals or solutions without having that grounding seems problematic to me, so I'm still really hoping to make some time to dig in to the questions listed there.

I think a z-index type of thing that effectively pushed the element out of its container would be the way to go and very useful.

For this particular use case, you can use border-top-left-radius: inherit on the image instead of clipping the parent, if you just want to round the corner to match.

Technically, CSS already has one possibility to do this: it's absolutely positioned elements whose containing block is outside the overflowed container. So another one possible solution regarding your example is to remove position: relative from the .content element.

However, it would be great if we can control this explicitly!

@SelenIT Copying your code comment here for reference:

/* the downside is that you can't use 100% of container width anymore */

The downside of doing this is you lose the ability to define the absolute element's size in terms of its parent, inside the overflow container.

@domenic completely agree. Added a few labels to denote that as such.

@OliverJAsh yeah, that's the goal :)

This isn't going to be useful feedback, but these suggestions probably sound terrifying to implementers. One of the reasons an OS window system can do this is because it doesn't have anything like the complexity of CSS layout. It just draws bitmaps in a particular order (and they often still fall short in some of the examples above).

Take the select or pop-up menu. In a native control, that is a modal window that appears over everything. If you swap windows (apps), it goes away. You can't scroll the originating window while the overlay is up. (You might be able to programatically scroll the original window, but I wouldn't be surprised if the overlay doesn't move). All this is special behaviour for a particular UI interaction.

If you stick to native controls in CSS, then maybe it will work. The native select does what was requested, for example. However, if you're asking for the ability to have anything escape its container, and possibly its window, then things will get really difficult. For one thing, do they become modal? Under what circumstances do they fall out of this mode? etc.

@grorg Thanks for the feedback, much appreciated - it's actual useful feedback because it let's me know you're freaked out to implement it :)

It just draws bitmaps in a particular order (and they often still fall short in some of the examples above).

Interestingly enough, this is precisely how I'd summarize what I'd want it to do, it's the heuristic we need to work out (eg: this will not be another z-index).

However, if you're asking for the ability to have anything escape its container, and possibly its window, then things will get really difficult.

Along with the other form control styling investigations we're doing, this is actually at the top of the list of the first things I plan to dig into. I posit that you don't need it to escape the window. But, I'll need to go add some telemetry and get end user feedback to see if that holds true. That said - I don't think we're in a position to actually propose something for this yet. As I wind down some of my other work I'll begin digging into <select> including this item in this repo and will hopefully be able to begin determining a solution along with the brilliant folks that build out component libs & design systems every day; and all of you wonderful UA implementers/standards folks as well :)

It is absolutely not ever going to be allowed for arbitrary web content to escape the window. That would mean there is zero trustable UA pixels in the window; we're already at a dangerous minimum of trustability today.

@tabatkins If you think I implied that - that was not what I meant at all. I'm saying that we need to look hard at the situation we are currently facing, with numerous top properties replacing the <select> for their own custom build ones to a varying degree of fidelity; and for many different reasons. All I was trying to say was that I want to add telemetry regarding @grorg point because I think if this was such a major problem then there wouldn't be such a prevalence of custom dropdowns today.

There's also a way to do it like this:

<div style="overflow: hidden">
    <div style="position: absolute">
        <div style="position: fixed">
        </div>
    </div>
</div>

The downside of this one is that you'll have to set the initial position with the absolutely positioned parent element and be able to adjust it only with transform property.

Was this page helpful?
0 / 5 - 0 ratings