131

In CSS the overflow:hidden is set on parent containers in order to allow it to expand with the height of their floating children.

But it also has another interesting feature when combined with margin: auto...

If PREVIOUS sibling is a floating element, it will actually appear juxtapose to it. That is if the sibling is float:left then the container with float:none overflow:hidden will appear to the right of the sibling, no newline - just as if it was floating in the normal flow. If the previous sibling is float:right then the container will appear to the left of the sibling. Resizing this container will accurately show it centered inbetween the floating elements. Say if you have two previous siblings, one float:left the other float:right, the container will appear centered inbetween the two.

So here's the problem...

How do I maintain that type of layout WITHOUT masking children?

Googling all over the web gives me ways on how to clear:both and expand a container... but I can't find any alternative solution to maintaining the left/right previous-child centering. If you make the container overflow:visible then the container suddenly ignores the layout flow of the floating elements and appears layered ontop of the floating element.

So question:

I have to have the container overflow:hidden to preserve layout...

how can I make it so the children aren't masked? I need to have the child absolutely positioned relative to the parent outside the container.

OR

How do I overflow:visible so I can absolutely position a child relative to the parent outside the container... YET preserve the sibling float-like-layout-flow?

Luke
  • 4,825
  • 2
  • 30
  • 37
marknadal
  • 7,534
  • 4
  • 25
  • 22

6 Answers6

94

You can use the clearfix to do "layout preserving" the same way overflow: hidden does.

.clearfix:before,
.clearfix:after {
    content: ".";    
    display: block;    
    height: 0;    
    overflow: hidden; 
}
.clearfix:after { clear: both; }
.clearfix { zoom: 1; } /* IE < 8 */

add class="clearfix" class to the parent, and remove overflow: hidden;

craigpatik
  • 941
  • 13
  • 25
Frexuz
  • 4,732
  • 2
  • 37
  • 54
  • Hmm! Clever, I am just now experimenting with it. What I am currently getting is that the generated content behaves correctly, being preserved in the flow of the layout, however the parent will still ignore it and layer ontop of the floating elements. However, this is a very good idea and I will play with it more to see if I can get it to behave correctly, and comeback to vote. Thank you :). – marknadal Jan 29 '12 at 10:39
  • @user1671639 your example doesn't really apply for a clearfix. You need something else, so I suggest you post a question with your problem. – Frexuz Jul 17 '13 at 14:31
  • 2
    This doesn't work in the same way as `overflow:hidden` at all. Applying a clearfix to the parent div doesn't allow all child components to be "contained within" the same height as the parent. – Khom Nazid May 07 '20 at 02:02
15

This is an old question but encountered it myself.

I have semi-solutions that work situational for the former question("Children visible in overflow:hidden parent")

If the parent div does not need to be position:relative, simply set the children styles to visibility:visible.

If the parent div does need to be position:relative, the only way possible I found to show the children was position:fixed. This worked for me in my situation luckily enough but I would imagine it wouldn't work in others.

Here is a crappy example just post into a html file to view.

<div style="background: #ff00ff; overflow: hidden; width: 500px; height: 500px; position: relative;">
    <div style="background: #ff0000;position: fixed; top: 10px; left: 10px;">asd
        <div style="background: #00ffff; width: 200px; overflow: visible; position: absolute; visibility: visible; clear:both; height: 1000px; top: 100px; left: 10px;"> a</div>
    </div>
</div>
Feuermurmel
  • 9,490
  • 10
  • 60
  • 90
Thomas Davis
  • 1,886
  • 15
  • 14
  • Here is a crappy example just post into a html file to view.
    asd
    a
    – Thomas Davis Jan 19 '11 at 05:45
  • 5
    Thanks for trying to answer, but this doesn't work because fixed position automatically positions the element relative to the viewport, meaning it does *not* move with the parent. In fact, if you have a scrolling page, it'll stay at 10px,10px as you scroll. – marknadal Jan 20 '11 at 08:42
  • "If the parent div does need to be position:relative, the only way possible I found to show the children was position:fixed." Thanks for that. I had a popover help bubble that needed to overflow even though the parent had overflow: scroll. I ended up having an absolute div, with a relative inner, and then a fixed content area. – JackMorrissey Mar 03 '15 at 15:24
  • Thanks, that worked for me. I had a parent with position relative, and that was needed because its position was set using `left`. Using `margin-left` instead would achieve the same effect, so I didn't need to use the position relative anymore. – Felipe Castro Nov 13 '15 at 16:41
14

Neither of the posted answers worked for me. Setting position: absolute for the child element did work however.

reflexiv
  • 1,693
  • 1
  • 21
  • 24
  • 36
    But wouldn't the parent DIV mask it out if it went beyond the boundaries of the parent DIV (which has overflow:hidden)? – marknadal Jul 15 '12 at 18:16
  • 10
    Afaik it doesn't, as long as the parent does not have position:relative. Then the child is positioned relative to its first positioned (not static) ancestor element, taking it out of the regular (parent's) dom flow. – Pim Schaaf Jul 02 '13 at 13:47
  • If the parent does have position:relative and doesn't require it you can make it position:unset. – yeahlad Jun 06 '19 at 05:07
  • 2
    True, if it's `position: fixed` or absolute positioned relative to something _outside_ the parent that has `visibility: hidden`, it will be visible. However, you often need (want) to position it relative to the parent to be more robust to code changes. Then these solutions are not an alternative. – ArneHugo Jan 22 '20 at 19:28
  • 1
    @marknadal this is exactly the problem I am having now which lead me to this so question – Fiddle Freak Feb 22 '21 at 18:34
2

For others, if clearfix does not solve this for you, add margins to the non-floated sibling that is/are the same as the width(s) of the floated sibling(s).

Walf
  • 8,535
  • 2
  • 44
  • 59
-3

For others if this does not work try giving height in vh in the component where you need the scrollbar.

.parent {
     overflow: hidden;
}

.child {
     overflow: overlay;
     height: 100vh;
}
Kunal Tyagi
  • 2,341
  • 1
  • 15
  • 26
  • Yes, it worked! I guess this would be more clear for others `.parent { overflow: hidden; } .child { overflow: overlay; height: 100vh; }` – Rajesh Jul 01 '21 at 14:58
-3

just add a position: static to parent. (bootstrap dropdown example)

HTML

<div class="menu px-3">
  <li class="dropdown tab"> <!-- this is one you should add position: static to -->
    <a role="button" data-bs-toggle="dropdown" class="nav-link dropdown-toggle">
    Click to show dropdown<span class="caret"></span>
    </a> 
    <ul class="dropdown-menu show" style="position: absolute; inset: 0px auto auto 0px; margin: 0px; transform: translate3d(122px, 130px, 0px);" data-popper-placement="bottom-end">
      <li>
        <a href="#" class="dropdown-item text-16 gray-1 tab">
        Link one
        </a>
      </li>
      <li>
        <a href="#" class="dropdown-item text-16 gray-1 tab ">
        Link two
        </a>
      </li>
    </ul>
  </li>
</div> 

CSS

div.menu {
  overflow-y: hidden;
  overflow-x: auto;
}
li.dropdown {
  position: static;
}

Please return to this link for more info

Safwat Fathi
  • 758
  • 9
  • 16