Wizard of Ogz
Wizard of Ogz

Reputation: 12643

Visible overflow in one direction with scrolling in the other direction

I need to have absolutely positioned element which scrolls with its parent. The absolutely positioned element may be wider than the scrollable container, in which case the content is currently being clipped. It appears that combining overflow-y: auto; and overflow-x: visible; does not work.

Here is a JSFiddle to illustrate the problem. Notice the popups cause horizontal scrolling.

And this is what it should look like here, only with scrolling.

Can this be accomplished through CSS?

Upvotes: 7

Views: 3826

Answers (4)

Venryx
Venryx

Reputation: 17999

I found a solution in my project, by hiding the horizontal scrollbar (I use a custom scrollbar ui), giving the container a padding-right of 300px and a margin-right of -300px. The padding and -margin make it so the normal children are aligned the same, except there's also extra room in the container in case an absolutely-positioned element extends out of that zone. (scrollable areas cut off anything outside the outer bounds)

Of course, if you have content to the right of the scroll area, this makes it extend out onto it. With a transparent background that isn't a visual problem; however it then blocks mouse events.

To solve that, I added two elements as siblings of the scroll-view, like so:

// this outer container resizes to match the size of scrollContainer
<div style={{position: "relative"}>
    <div id="scrollContainer" style={{paddingRight: 300, marginRight: -300}}>
        // stuff which might extend to the right
    </div>

    // the containers below resize with the outer container
    // however, notice that the 2nd one is positioned only over the possibly-extended-onto area

    <div id="insideArea" style={{position: "absolute", left: 0, right: 0, top: 0, bottom: 0}}
        onMouseEnter={()=> {
            // we're back inside, so enable scroll-container mouse-events
            $("scrollContainer").css("pointer-events", "auto");

            // prevent self from blocking mouse events for scrollContainer
            $("insideArea").css("display", "none");

            // re-enable extend-area div, so we know when mouse moves over it
            $("extendArea").css("display", "block");
        }/>

    <div id="extendArea" style={{position: "absolute", top: 0, bottom: 0, left: "100%", width: 300}}
        onMouseEnter={()=> {
            // we're over the extend-area, so disable scroll-container mouse events
            $("scrollContainer").css("pointer-events", "none");

            // prevent self from blocking mouse events for behind-extend-area elements
            $("#extendArea").css("display", "none");

            // re-enable inside-area div, so we know when mouse moves over it
            $("#insideArea").css("display", "block");
        }/>

What does the above do? It makes it so when your mouse enters the normal scroll-view area, pointer-events are enabled, letting you click on stuff inside -- but when your mouse moves into the special "extended" area, the scroll-view mouse-events are disabled, letting you click on the normal items behind that area.

This solution will probably never be used by anyone else, but I spent enough time finding it I thought I'd share it anyway!

Upvotes: 2

KayCee
KayCee

Reputation: 11

use max_width instead of width 400. That is the only solution.

Upvotes: 1

ryanfelton
ryanfelton

Reputation: 68

You have a hard coded width. The <div> will automatically take the full width of the page, so you want to do is restrict the maximum width that the div can contain so change the width: 400px to something like max-width: 90%

Here's a JSFiddle example: http://jsfiddle.net/c8DdL/3/

Upvotes: 3

Wizard of Ogz
Wizard of Ogz

Reputation: 12643

For posterity: The problem does require a JavaScript solution. Ultimately the project feature I was working on was changed to avoid this problem and resulted in a better design.

Upvotes: 1

Related Questions