parent & child with position fixed, parent overflow:hidden bug
Asked Answered
B

9

78

I don't know if there is an issue, but I was wondering why the overflow:hidden does not function on fixed parent/children element.

Here's an example:

CSS and HTML:

.parent{
  position:fixed;
  overflow:hidden;
  width:300px;
  height:300px;
  background:#555;
}
.children{
  position:fixed;
  top:200px;
  left:200px;
  width:150px;
  height:150px;
  background:#333;
}
<div class="parent">
  <div class="children">
  </div>
</div>

Live demo: jsFiddle

Barto answered 17/9, 2012 at 16:40 Comment(0)
I
58

Because a fixed position element is fixed with respect to the viewport, not another element. Therefore since the viewport isn't cutting it off, the overflow becomes irrelevant.

Whereas the position and dimensions of an element with position:absolute are relative to its containing block, the position and dimensions of an element with position:fixed are always relative to the initial containing block. This is normally the viewport: the browser window or the paper’s page box.

ref: http://www.w3.org/wiki/CSS_absolute_and_fixed_positioning#Fixed_positioning

Ical answered 17/9, 2012 at 16:45 Comment(0)
K
107

You could consider using CSS clip: rect(top, right, bottom, left); to clip a fixed positioned element to a parent. See demo at http://jsfiddle.net/lmeurs/jf3t0fmf/.

Beware, use with care!

Though the clip style is widely supported, main disadvantages are that:

  1. The parent's position cannot be static or relative (one can use an absolutely positioned parent inside a relatively positioned container);
  2. The rect coordinates do not support percentages, though the auto value equals 100%, ie. clip: rect(auto, auto, auto, auto);;
  3. Possibillities with child elements are limited in at least IE11 & Chrome34, ie. we cannot set the position of child elements to relative or absolute or use CSS3 transform like scale.

See http://tympanus.net/codrops/2013/01/16/understanding-the-css-clip-property/ for more info.

EDIT: Chrome seems to handle positioning of and CSS3 transforms on child elements a lot better when applying backface-visibility, so just to be sure we added:

-webkit-backface-visibility: hidden;
-moz-backface-visibility: hidden;
backface-visibility: hidden;

to the main child element.

Also note that it's not fully supported by older / mobile browsers or it might take some extra effort. See our implementation for the menu at bellafuchsia.com.

  1. IE8 shows the menu well, but menu links are not clickable;
  2. IE9 does not show the menu under the fold;
  3. iOS Safari <5 does not show the menu well;
  4. iOS Safari 5+ repaints the clipped content on scroll after scrolling;
  5. FF (at least 13+), IE10+, Chrome and Chrome for Android seem to play nice.

EDIT 2014-11-02: Demo URL has been updated.

Kingkingbird answered 25/5, 2014 at 20:36 Comment(6)
A brilliand solution, cheers! iOS Safari 5+ repaints the clipped content on scroll after scrolling; iOS 8 Safari (even after the update) still seems to behave that way. The rect coordinates do not support percentages but we can give the .parent the needed percentage dimensions.Synergism
@Imeurs Great solution. One caveat is that clip is now deprecated. Going forward we should be using the clip-path property. In addition to clip: rect(auto, auto, auto, auto);, we should also include clip-path: inset(0 0 0 0);Dakotadal
@Dakotadal clip may be deprecated, but clip-path is still not supported in IE11 or Edge. I will be using clip for now.Cube
Chrome renders clip-path very-very-very slowly. Hope they never deprecate clipConcentre
The shortest answer is: clip-path: inset(0)Xmas
Clip-path together with position:fixed caused performance issues in Chrome/Mac for me (causing elements to randomly disappear and devtools to seizure). I wanted to have an element in the background, and in that case background-attachment: fixed was sufficient.Acth
I
58

Because a fixed position element is fixed with respect to the viewport, not another element. Therefore since the viewport isn't cutting it off, the overflow becomes irrelevant.

Whereas the position and dimensions of an element with position:absolute are relative to its containing block, the position and dimensions of an element with position:fixed are always relative to the initial containing block. This is normally the viewport: the browser window or the paper’s page box.

ref: http://www.w3.org/wiki/CSS_absolute_and_fixed_positioning#Fixed_positioning

Ical answered 17/9, 2012 at 16:45 Comment(0)
V
42

2016 update:

You can create a new stacking context, as seen on Coderwall:

<div style="transform: translate3d(0,0,0);overflow:hidden">
   <img style="position:fixed; ..." />
</div>

Which refers to http://dev.w3.org/csswg/css-transforms/#transform-rendering

For elements whose layout is governed by the CSS box model, any value other than none for the transform results in the creation of both a stacking context and a containing block. The object acts as a containing block for fixed positioned descendants.

Vulva answered 8/7, 2016 at 14:13 Comment(3)
It works in Edge, but it does not work in Internet Explorer 11.Cube
There is still a problem - transform property introduces a new local coordinate system. so if I wanted my img to be fixed relative to viewport, now it is fixed relative to this overflow container element.Helbona
However, position: fixed; of child doesn't work as expected.Camouflage
A
27

on parent element add clip-path: inset(0 0 0 0);

Authenticity answered 14/4, 2022 at 6:19 Comment(0)
A
8

As an alternative to using clip you could also use {border-radius: 0.0001px} on a parent element. It works not only with absolute/fixed positioned elements.

Amye answered 9/6, 2018 at 11:43 Comment(1)
Does not work in firefox, though. Would have loved this, much more reliable than repositioning all of your junk in javascript.Avron
A
3

If you want to hide overflow on fixed-position elements, the simplest approach I've found is to place the element inside a container element, and apply position:fixed and overflow:hidden to that element instead of the contained element (you must remove position:fixed from the contained element for this to work). The content of the fixed container should then be clipped as expected.

In my case I was having trouble with using object-fit:cover on a fixed-position element (it was spilling outside the bounds of the page body, regardless of overflow:hidden). Placing it inside a fixed container with overflow:hidden on the container fixed the issue.

Amy answered 15/12, 2016 at 16:40 Comment(0)
W
0

I had a similar, quite complex problem with a fluid layout, where the right column had a fixed width and the left one had a flexible width. My fixed container should have the same width as the flexible column. Here is my solution:

HTML

<div id="wrapper">
    <div id="col1">
    <div id="fixed-outer">
        <div id="fixed-inner">inner</div>
    </div>
    COL1<br />Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
    </div>
    <div id="col2">COL2</div>
</div>

CSS

    #wrapper {
    padding-left: 20px;
}

#col1 {
    background-color: grey;
    float: left;
    margin-right: -200px; /* #col2 width */
    width: 100%;
}

#col2 {
    background-color: #ddd;
    float: left;
    height: 400px;
    width: 200px;
}

#fixed-outer {
    background: yellow;
    border-right: 2px solid red;
    height: 30px;
    margin-left: -420px; /* 2x #col2 width + #wrapper padding-left */
    overflow: hidden;
    padding-right: 200px; /* #col2 width */
    position: fixed;
    width: 100%;
}

#fixed-inner {
    background: orange;
    border-left: 2px solid blue;
    border-top: 2px solid blue;
    height: 30px;
    margin-left: 420px; /* 2x #col2 width + #wrapper padding-left */
    position: absolute;
    width: 100%;
}

Live Demo: http://jsfiddle.net/hWCub/

Willardwillcox answered 18/2, 2013 at 13:10 Comment(0)
M
0

This isn't the exact answer but a handy trick to work around the issue if your use case makes sense. The accepted answer is correct.

A simple hack is to use z-index on the parent relative container in conjunction with another hiding element below and/or above.

example

body {
  margin: 0px;
  padding: 0px;
}

.parent {
  background-color: blue;
  height: 500px;
  padding: 30px;
  position: relative;
  text-align: center;
  z-index: 1;
}

.child {
  padding: 10px;
  position: fixed;
  top: 100px;
}

.sibling {
  background: white;
  min-height: 500px;
  padding: 30px;
  position: relative;
  z-index: 2;
}
<div class="parent">
  <button class="child">
    Click Me
  </button>
</div>

<div class="sibling">
  <h1>Some Header</h1>

  <p>
    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?
  </p>
</div>
Marchant answered 8/2, 2022 at 19:18 Comment(0)
M
-1

Fixed position elements are positioned relative to the browser window, so the parent element is basically irrelevant.

To get the effect you want, where the overflow on the parent clips the child, use position: absolute instead: http://jsfiddle.net/DBHUv/1/

Marrowbone answered 17/9, 2012 at 16:47 Comment(2)
jsfiddle link brokenCarbone
was this only down-voted because of the link? The answer is straightforward and works as intended.Aloke

© 2022 - 2024 — McMap. All rights reserved.