Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is `overflow: hidden` changing the positioning of absolute children?

Tags:

css

I have an image gallery sliding images in an out only with css. See http://codepen.io/anon/pen/xmhzE?editors=110 for the example or the attached code.

It works fine as long as the #images-div does not have overflow: hidden set. When overflow is set to hidden, the absolute positioning of the single images does not work anymore. When I use negative values for the left-property of the images it also works with overflow hidden.

Does overflow:hidden change the way how absolute children are layouted?

Does anyone has a solution to this problem?


Sources

index.html:

<div id="images">
  <img id="image1" src="http://i.imgur.com/dL3io.jpg" />
  <img id="image2" src="http://i.imgur.com/qASVX.jpg" />
  <img id="image3" src="http://i.imgur.com/fLuHO.jpg" />
  <img id="image4" src="http://i.imgur.com/5Sd3Q.jpg" />
</div>
<div id="slider">
  <a href="#image1">1</a>
  <a href="#image2">2</a>
  <a href="#image3">3</a>
  <a href="#image4">4</a>
</div>

base.css:

body {
    text-align: center;
  }
#images {
  width: 400px;
  height: 250px;
  /*overflow: hidden; if this is set absolute positioning of images breaks*/
  position: relative;
  background-color: red;

  margin: 20px auto;
}
#images img {
  width: 400px;
  height: 250px;
  display: block;

  position: absolute;
  top: 0px;
  left: 400px;
  z-index: 1;
  opacity: 0;

  transition: all linear 500ms;
  -o-transition: all linear 500ms;
  -moz-transition: all linear 500ms;
  -webkit-transition: all linear 500ms;
}
#images img:target {
  top: 0px;
  left: 0px;
  z-index: 9;
  opacity: 1;
}
#slider a {
  text-decoration: none;
  background: #E3F1FA;
  border: 1px solid #C6E4F2;
  padding: 4px 6px;
  color: #222;
}
#slider a:hover {
  background: #C6E4F2;
}
like image 828
Sven Avatar asked Nov 01 '14 22:11

Sven


1 Answers

This puzzle kept me going. I just couldn't leave it be. So last evening I was fiddling with it, but couldn't fix it (untill just yet :) ).

Testcase 1

While simplifying things I removed the opacity from the image-elements and left only 1 image and one link. I've set the image to 390px initially so that I can make sure that it is at that position (you can see just a little bit of the left of it).

http://codepen.io/anon/pen/tpCrc

Conclusion:

So what's important to notice is that fact that the image initially is there where it should be. Then when clicking button 1 you can see it simply skips the transition. So the browser doesn't change the position of the element, because of overflow:hidden (like the title of this post suggests). It goes to the position mentioned in the CSS (in the :target part), but without the transition.

Testcase 2

Then I got wondering why the browser would act that way and I kept thinking that maybe the focussing of the image element had something to do with it. If you think about it: when clicking one of the buttons you add #target to the URL of the page and browser then tries to "scroll" to that element. To that, that element has to be visisble.

So I wondered: maybe the CSS has nothing to do with it. Let's try: so I completely removed the :target-part and the transitions.

http://codepen.io/anon/pen/IvfBE

Conclusion:

Wow! What do we see there? When clicking one of the buttons the image still jumps to left:0 !! I think we got a lead there. Still though, I didn't know how to actually fix that. Still seems like a browser-bug to me.

The fix

Then - after a good night of sleep - I woke up with a fresh new idea. What if we don't actually target the element we want to transition?

So I added a container to each image-element and target that instead.

<div id="images">
    <div id="img1container"><img id="image1" src="http://i.imgur.com/dL3io.jpg" /></div>
    <div id="img2container"><img id="image2" src="http://i.imgur.com/qASVX.jpg" /></div>
    <div id="img3container"><img id="image3" src="http://i.imgur.com/fLuHO.jpg" /></div>
    <div id="img4container"><img id="image4" src="http://i.imgur.com/5Sd3Q.jpg" /></div>
</div>
<div id="slider">
    <a href="#img1container">1</a>
    <a href="#img2container">2</a>
    <a href="#img3container">3</a>
    <a href="#img4container">4</a>
</div>

In the CSS the position of the image now has to be changed by "[parentElement]:target img" instead.

body {
    text-align: center;
}
#images {
    width: 400px;
    height: 250px;
    overflow: hidden; /* this did break it in the past ;) */
    position: relative;
    background-color: red;

    margin: 20px auto;
}
#images img {
    width: 400px;
    height: 250px;
    display: block;

    position: absolute;
    top: 0px;
    left: 400px;
    z-index: 1;
    opacity: 0;

    transition: all linear 500ms;
    -o-transition: all linear 500ms;
    -moz-transition: all linear 500ms;
    -webkit-transition: all linear 500ms;
}
#images div:target img {
    top: 0px;
    left: 0px;
    z-index: 9;
    opacity: 1;
}
#slider a {
    text-decoration: none;
    background: #E3F1FA;
    border: 1px solid #C6E4F2;
    padding: 4px 6px;
    color: #222;
}
#slider a:hover {
    background: #C6E4F2;
}

And the working example: http://codepen.io/anon/pen/lyzhi

Conclusion:

Yay!! Indeed, by not putting focus on the element you want to transition, it doesn't break. So, you've got your fix there, but it still seems like a browser/engine-bug to me. So I'd suggest you create a bugreport somewhere (if you've got time).

BTW: I've tested this in Chrome and IE - both the latest versions only. You might want to test this in Firefox and maybe some other browsers.

like image 128
vrijdenker Avatar answered Nov 15 '22 23:11

vrijdenker