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
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:
The parent's position cannot be static or relative (one can use an absolutely positioned parent inside a relatively positioned container);
The rect coordinates do not support percentages, though the auto value equals 100%, ie. clip: rect(auto, auto, auto, auto);;
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.
IE8 shows the menu well, but menu links are not clickable;
IE9 does not show the menu under the fold;
iOS Safari <5 does not show the menu well;
iOS Safari 5+ repaints the clipped content on scroll after scrolling;
FF (at least 13+), IE10+, Chrome and Chrome for Android seem to play nice.
EDIT 2014-11-02: Demo URL has been updated.
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
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.
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.
on parent element add clip-path: inset(0 0 0 0);
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.
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/
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/
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>
Related
It is not entirely clear to me how CSS transforms affect the flow layout of the document and the positioning of an element. According to the documentation on MDN and W3C, CSS transforms do not interfere with the flow layout:
From MDN on CSS transforms (emphasis mine):
By modifying the coordinate space, CSS transforms change the shape and position of the affected content without disrupting the normal document flow.
Thus, if we translate an element, the original flow layout should remain intact and the result of the transformation should be purely visual.
A trivial example of this is demonstrated below:
.container {
background: white;
margin: 0 auto;
border: 1px solid grey;
}
.block {
width: 100%;
height: 100px;
}
.blue {
background: blue;
}
.red {
background: yellow;
}
.transform {
transform: translateY(-200%);
}
<div class="container">
<div class="block red transform"></div>
<div class="block blue"></div>
</div>
In this example, there are two div elements and the upper element was translated vertically so that it is not visible anymore. However, the flow layout remains unchanged and there is no overflow in the document. That is, the result of the transformation is purely visual.
Now, consider a page layout with a wrapper of fixed width, such that the width of the child elements is bounded by the wrapper element. Now add a positioned element that is wider than the wrapper and add an offset (e.g. left). In "narrow enough" windows, the body overflows and we are able to scroll horizontally. However, if we translate the same element and re-center it, the overflow disappears, implying that the transformation is not purely visual.
A demonstration of this effect is shown in the example below. Initially, the offset element is not transformed. You may try resizing your window to see the overflow and then toggle the transformation with the button in the center.
document.getElementById('toggle').addEventListener('click', function(event) {
const blocks = document.querySelectorAll('.block.wide');
for(let i=0;i<blocks.length;i++) {
const block = blocks[i];
block.classList.toggle('transform');
}
});
html, body {
background: #ddd;
}
.container {
background: white;
max-width: 1152px;
margin: 0 auto;
}
.content {
border: 1px solid grey;
}
.block.wide {
background: yellow;
max-width: 1380px;
width: 100vw;
position: relative;
left: 50%;
}
.block.wide.transform {
transform: translateX(-50%);
}
<div class="container">
<div class="content">
<div class="block">
<h1>Lorem ipsum dolor sit amet</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
<p><strong>Click the button below to toggle the transform and see the overflow vanish</strong></p>
<button id="toggle">Toggle Transform</button>
</div>
<div class="block wide">
<h1>Lorem ipsum dolor sit amet</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
</div>
</div>
Is this the intended behavior according to the specifications? How do offsets and transformations interact?
In all my test cases, the CSS transform achieves the desired result. However, I feel that I am relying on luck rather than a technical specification.
There's several points to cover here.
From the CSS Transforms spec, Section 3. The Transform Rendering Model says:
For elements whose layout is governed by the CSS box model, the transform property does not affect the flow of the content surrounding the transformed element. However, the extent of the overflow area takes into account transformed elements. This behavior is similar to what happens when elements are offset via relative positioning. Therefore, if the value of the overflow property is scroll or auto, scrollbars will appear as needed to see content that is transformed outside the visible area. Specifically, transforms can extend (but do not shrink) the size of the overflow area, which is computed as the union of the bounds of the elements before and after the application of transforms.
Which means transforms are supposed to affect the overflow and scrolling. However, in your first example, the overflow is to a negative coordinate space, and that overflow is always clipped, so it doesn't generate any new scrollbars.
But your second example, on a direct reading, seems to be in contradiction to the specification, with the transform shrinking the overflow area. What I think is happening here is that position relative shifts, and transforms are, as acknowledged by the quote above, very similar operations, and the transform is undoing the effect of the relative positioning.
In other words, the overflow area is being computed as the union of the bounds of the elements before and after the application of relative positioning and transforms.
I would like to have a fixed header, all of the content in the header should be fixed at the top. I am having trouble because I have 2 backgrounds that will sandwich some content. So basically if you look at the code snippet, i would like 1-header-holidaybg.png on top then the paragraph then 3-header-holidaybg.png and after that is the main content that is not fixed and scrolls behind the header. There cannot be any space between the background and paragraph like i have now but I am having a lot of trouble accomplishing this.
header {
position: fixed;
top: 0px;
z-index: 100;
}
#headerbg {
background: url("https://secure.feedingamerica.org/images/content/pagebuilder/1-header-holidaybg.png") no-repeat;
width: 100%;
background-size: 100%;
height: 190px;
}
#hbottom {
background: url("https://secure.feedingamerica.org/images/content/pagebuilder/3-header-holidaybg.png") no-repeat;
min-height: 60px;
}
.container {
margin: 0px 120px;
}
header p {
background: #fff;
padding: 10px 0px;
color: #333;
}
#main-content {
margin-top: 45%;
padding-top: 20px;
background: url("https://secure.feedingamerica.org/images/content/pagebuilder/holiday-bg.png") repeat;
color: red;
}
<header>
<div id="headerbg">
</div>
<p>this content should display below the 1-header-holidaybg.png backbround but above the 3-header-holidaybg.png background</p>
<div id="hbottom"></div>
</header>
<div id="main-content"><p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p><div>
I've put together a CodePen for you that may be what you're looking for.
Move the background: #fff up to the header element. This prevents the items scrolling behind from showing through.
Add a position: relative to the main-content div and align it to the top using top: 0. This will position the container relative to its parent container, which in this case is the body. (I added a height: 2000px just for testing)
I'd also suggest tossing in a container inside main-content that will house your paragraph text; paragraphContent for this example. You'll then want to add position: relative to that container. This makes the section a little more dynamic so you can add more content without having to worry about styling the paragraphs too much.
The unfortunate part of position: fixed is that since it takes items out of the standard flow of the document, things can easily be overlapped, so you want to take this into consideration when hitting smaller viewports. In your example, the paragraph text in the header wraps to multiple lines on small viewports, which pushes the background down over the main content. To prevent this is the pen, I threw in a media query that kicks in when the viewport is under 415px.
I have div of variable width which I want to center using this code:
div {
background: red;
max-width: 400px;
position: absolute;
left: 50%;
transform: translateX(-50%);
}
https://jsfiddle.net/xooqvyqL/1/
this works well for centering, however the problem becomes when you shrink window size down (lets say you view it on smaller screen/mobile) then you get like a 'padding' around the element taking space, which is not wanted behavior.
This is different as if was like this:
https://jsfiddle.net/xc4w4aph/5/
Note: this is not centered because of variable width (I would use negative margin if it was known width or javascript but I want to do this with pure css) but just for demo purposes if you shrink window size on this example you dont get any kind of 'padding' outside the div taking space.
I am missing something with translate? I dont want this 'padding' behavior.
Because you have set the div to position absolute, it collapses and the margins are reset and the div no longer has a default width of 100%
To restore the maximum, but restricted width, add width:100% before the max-width and everything goes back to normal.
JSfiddle Demo
div {
background: red;
width: 100%;
max-width: 400px;
position: absolute;
left: 50%;
transform: translateX(-50%);
}
<div>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Facilis sint enim molestias modi officia fuga corporis, ipsa dicta tenetur, aut dignissimos, perspiciatis cumque assumenda, voluptas harum quis qui cum eligendi voluptatibus dolore! Quos hic
architecto odio repudiandae aliquid quisquam quidem beatae voluptatem sint praesentium. Tempore eveniet dolorum aspernatur, asperiores neque.</p>
</div>
Use this css code :
*{
margin:0;
padding:0;
}
div {
background: red;
max-width: 400px;
position: absolute;
left: 50%;
transform: translateX(-50%);
}
Is there elegant solution to hover only for top element, not for underlying; or i should to do this using javascript?
<div class="WithHover1">
<div class="WithHover2">
I am Top and I want to be the only div hightlighted
</div>
I want to be hightlighted too, but I dont want to be hightlighted when the nested one is
</div>
You can't do this in just CSS, yet. The has selector is in draft for level 4/5 (I forget) CSS selectors, which will be awesome.
For now, javascript/jquery would be the easiest and most practical method.
$(".WithHover2").mouseover(function() {
$(".WithHover1").removeClass("highlight");
$(this).addClass("highlight");
});
Here's a CSS3 solution, using the ::after pseudo-element, with a bottom border that overrides the background color of the bottom text.
The negative z-index prevents the border from covering up the text, and overflow: hidden prevents WithHover1 from expanding due to the large border.
It works in IE11 (at least), Chrome, Firefox, Safari, and Opera:
div.WithHover1 {
font: 14px verdana;
position: relative;
overflow: hidden;
}
div.WithHover1:hover {
background: yellow;
position: relative;
z-index: 1;
}
div.WithHover2:hover {
background: orange;
}
div.WithHover2:hover::after {
content: '';
display: block;
position: absolute;
border-bottom: 1000px solid white;
width: 100%;
z-index: -1;
}
<div class="WithHover1">
<div class="WithHover2">
I am Top and I want to be the only div highlighted
</div>
I want to be highlighted too, but I dont want to be highlighted when the nested one is.
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum
</div>
This isn't what you want? Your post wasn't that clear to me what you needed when hovering over each.
.WithHover2:hover, .WithHover3:hover {
background-color: yellow;
}
<div class="WithHover1">
<div class="WithHover2">
I want to be the only div hightlighted
</div>
<div class="WithHover3">
I dont want to be hightlighted when the nested one is
</div>
</div>
This question already has answers here:
Fixed position but relative to container
(31 answers)
Closed 4 years ago.
I am relatively new to CSS. I have run into a problem where I am trying to fix an element next to its parent element. I am able to do so with the following code:
Parent element:
#search_results{
position:relative;
}
Child element:
.total {
position: fixed;
top:10px;
width:250px;
left: 75%;
/*overflow: hidden;*/
margin-left: -125px;
}
This works fine until the browser window is resized. When that occurs, the fixed element overlaps its parent element. You can see my problem here:
Twittiment
I am trying to fix the child element to the top of the page and the right-hand side of the parent element. Any ideas?
Edit:
You can use position: sticky; which can be relative to the parent element.
body > div {
height: 300px;
background-color: #ddd;
overflow: auto;
margin-top: 70px;
}
div > div {
height: 1000px;
position: relative;
}
span {
display: block;
height: 20px;
background-color: tomato;
position: sticky;
top: 0;
}
<div>
<div>
<span>This is a relatively sticky header</span>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Delectus voluptas pariatur ullam, dolores veritatis vero possimus nisi corrupti, provident aspernatur harum ab aliquam expedita assumenda, blanditiis aliquid id consequuntur distinctio.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Delectus voluptas pariatur ullam, dolores veritatis vero possimus nisi corrupti, provident aspernatur harum ab aliquam expedita assumenda, blanditiis aliquid id consequuntur distinctio.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Delectus voluptas pariatur ullam, dolores veritatis vero possimus nisi corrupti, provident aspernatur harum ab aliquam expedita assumenda, blanditiis aliquid id consequuntur distinctio.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Delectus voluptas pariatur ullam, dolores veritatis vero possimus nisi corrupti, provident aspernatur harum ab aliquam expedita assumenda, blanditiis aliquid id consequuntur distinctio.</p>
</div>
</div>
Old Answer:
As per CSS Spec, the element positioned fixed is fixed to the viewport and not the containing element.
So the short answer is NO, you cannot have a fixed position element relative to it's parent element. You can use position: absolute; instead and tweak the top left right bottom parameters on the run using jQuery/JS.
Of course you can, just need an extra div!
<div class="fixed-wrapper">
<div class="close-wrapper">
<div class="close"></div>
</div>
</div>
body
background: gray
height: 8000px
.fixed-wrapper
position: fixed
top: 20px
left: 0
right: 0
.close-wrapper
max-width: 1200px
position: relative
.close
background: #fff
width: 30px
height: 30px
position: absolute
right: 0
border: 1px solid #515151
&:before,&:after
width: 25px
height: 1px
background: #515151
content: ''
position: absolute
top: 50%
left: 50%
display: block
#include transform(translate(-50%, -50%) rotate(45deg))
&:after
transform: translate(-50%, -50%) rotate(-45deg)
See this fiddle I made for you :-)
http://codepen.io/marinagallardo/pen/mJyqaN
The best way to achieve this is to give parent element a transform css.
eg:
.relative{
transform: translateX(0); // this will act like relative parent
}
.fixed{
position: fixed;
left:0;
top:0;
width:100%; // width will be relative to the width of .relative
}
What you want to use is position:absolute . This places the child element according to it's parent element.
Some readings here : http://www.w3schools.com/cssref/pr_class_position.asp