The wrapper displays on the top of the first parent element. Good!
The problem:
However the second parent element is on the top of the wrapper element, and I can't figure it out why. It needed behind the child element like the first parent. (In real life it's a modal, but I tried to simplify the problem.)
The parent element is sticky (and I can't change it.)
The wrapper element must be an absolute position element.
I've tried to change z-indexes, add extra wrappers, asked openAI, with no luck.
Basically it looks like this (scss):
.parent {
width: 100px;
height: 100px;
background-color: blue;
z-index: -1;
position: sticky; // <-must be sticky
.wrap {
position: absolute; // <-must be absolute
top: -5px;
left: -5px;
z-index: 1;
width: 50px;
height: 210px;
background-color: red;
}
}
And the HTML:
<div class="parent">
<div class="wrap"></div>
</div>
<div class="parent"></div>
To see in live the simplified problem: https://codesandbox.io/s/sticky-parent-sp3v3b?file=/src/styles.scss
The second blue box need to be behind the red as well.
Any advice would be nice.
Okay so the solution was it needed to add different indexes to the parent element like this:
.parent {
width: 100px;
height: 50px;
background-color: blue;
position: sticky;
border: 1px solid white; // <-must be sticky
&:first-of-type {
z-index: 1;
}
&:last-of-type {
z-index: -1;
}
Related
I write css coded is the following lines. but not working z-index.
I want to know how I can make the z-index work while keeping the value of position as relative.
#foo {
position: relative;
z-index: -1;
width: 100%;
height: 30%;
background-color: lightblue;
}
#bar {
width: 50%;
height: 30%;
background-color: lightpink;
}
As far as I know, if you set the value of position to a non-static value, the z-index should work. Are there any other factors that affect the z-index?
Also if I change the value of position to absolute it works fine.
When position is relative
When position is absolute
everything is working as you need you can see I have added margin-bottom:-20px; to .foo so that you can se that in effect that .foo is behind .bar.
Understand that position won't take item out of flow, which will keep it at it's position. To see this in effect there must be some overlapping between two elements, than you can see the z-index in efffect.
html,
body {
width: 100%;
height: 100%;
}
#foo {
position: relative;
z-index: -1;
width: 100%;
height: 30%;
background-color: lightblue;
margin-bottom: -20px;
}
#bar {
width: 50%;
height: 30%;
background-color: lightpink;
}
<div id="foo">Foo</div>
<div id="bar">Bar</div>
I have 3 divs on top of each other having following css.
.d1 {
position: relative;
background-color: yellow;
height: 50px;
width: 100px;
overflow: hidden;
}
.d2 {
position: absolute;
background-color: green;
height: 25px;
width: 50px;
}
.d3 {
position: absolute;
left: 83px;
}
and the divs that have classes are as follows:
<div class="d1">
<div class="d2">
<div class="d3">text</div>
</div>
</div>
and as a result I see content of d3 cut off because of overflow:hidden in d1.
How can I avoid cut off content of d3 without modifying d1?
Getting around the overflow..
An element can overflow from a relative or absolute positioned parent by setting its position to fixed. An element that has position: fixed will have the default left,right,top, and bottom styles set as auto. This will position .d3 to the top-left of .d2, and then the left: 83px style will push it to the left from there.
Making up the additional space..
However, to get that additional movement to the right as the original markup, you will need to add margin-left: 8px, which will make-up the additional ~8px needed to replicate the original. Further adjustments to the position of .d3 will need to be done by setting the margin style (see below).
Your updated code should look like this..
.d1 {
position: relative;
background-color: yellow;
height: 50px;
width: 100px;
overflow: hidden;
}
.d2 {
position: absolute;
background-color: green;
height: 25px;
width: 50px;
}
.d3 {
position: fixed;
margin-left: 8px;
left: 83px;
}
Some considerations and caveats..
As a previous commenter mentioned, best practice would be to fix your html markup because this solution could cause issues if you ever need to move the position of .d3. For example, setting left,right,top, or bottom will cause the default setting of this style, auto, from being unset, and the element will be positioned relative to the viewport rather than the parent relative or absolute element.
I am trying to create a relative-positioned element with overflow:hidden that contains a few fixed-position elements. The goal is to have the fixed child elements become hidden as the parent element moves, sort of like if they were part of a background-image with attachment:fixed on the parent element.
By all accounts on StackOverflow and elsewhere on the web, this is not possible, because a fixed element only regards the browser window and ignores its parent element. However, for whatever reason it actually works as intended in Chrome only: http://jsfiddle.net/x6avvhuf/
Here's what the fiddle looks like, view it in Chrome vs. IE/Firefox to see the difference:
HTML
<body>
<div id = "headwrapper">
I am the relative parent element
<div class = "fixedchild">
I am a fixed child element
</div>
</div>
<div id = "content">
This is the main content portion of the page<br>
<!-- Repeat until the page scrolls -->
This is the main content portion of the page<br>
</div>
CSS
body {
background-color: yellow;
}
#headwrapper {
position: relative;
height: 300px;
width: 100%;
overflow: hidden;
z-index: -1;
background-color: black;
color: white;
text-align: center;
}
.fixedchild {
position: fixed;
width: 75%;
height: 40px;
z-index: 48;
top: 22.5%;
left: 50%;
margin: 0 0 0 -37.5%;
text-align: center;
color: red;
background-color: pink;
}
What is an alternative solution for this? I have read that it is possible to make an absolute element behave like a fixed element with CSS, but I have been unable to make this work so far. Thanks in advance for any help or advice! :)
UPDATE
Sometimes the best solutions are the most simple. Given the code you posted all you would have to do is set a background-color on #content (ex: yellow in this instance to match the body) since your fixed element has z-index: -1 and will sit behind it anyways:
#content{
background: yellow;
width: 100%;
}
CSS EXAMPLE 1
OR
You could set #content to position:relative which would allow you to order this and your fixed div with z-index (this is probably better, using z-index: -1 is kind of a hack):
CSS
.fixedchild {
position: fixed;
width: 75%;
height: 40px;
z-index: 1; //set to 1
top: 22.5%;
left: 50%;
margin: 0 0 0 -37.5%;
text-align: center;
color: red;
background-color: pink;
}
#content{
background: yellow;
width: 100%;
position: relative; //add
z-index: 2; //set higher
}
CSS EXAMPLE 2
(previous answer):
DISCLAMIER: This is not a CSS solution.
There may be a CSS solution for this. I don't happen to know one off the top of my head, but I do know this can be done pretty easily with Jquery
JS
$(window).scroll(function(){
var scrolled = $(this).scrollTop()+100; //offset starting position which I hard coded to top: 100px - you can change as needed
$(".fixedchild").css({"top": scrolled+"px"});
});
CSS
.fixedchild {
position: absolute;
width: 75%;
height: 40px;
z-index: 48;
top: 100px;
left: 50%;
margin: 0 0 0 -37.5%;
text-align: center;
color: red;
background-color: pink;
}
JS EXAMPLE
it's a known 'bug' that elements with fixed position loose their position if the container is translated. For example, if i've got a structure like this:
<div class="container">
<div class="fixed"></div>
</div>
and, say, the container is scrolled, when the conteiner gets transformed (say, translate(x,y), rotate(), or so..), then the fixed element behaves like it was positioned relative and it scrolls with the container. I can see it on the latest firefox, for example.
How can one fix this kind of problem? Is there any way?
This behaviour is not a bug. It's actually the specs recommended behaviour.
(See this post by Eric Meyer, or this question here on SO which accepted solution only provides a link to the same meyer's post)
For those who don't know this issue, and because you didn't provide a snippet into your question, here's one.
document.addEventListener('click', function() {
document.getElementById('container').classList.toggle('transformed')
}, false);
#bg {
border: 1px solid #AFA;
height: 100%;
width: 100%;
position: fixed;
top: 0;
left: 0;
}
#container {
border: 1px solid #FAF;
height: 50%;
width: 75%;
position: relative;
margin: 0 auto;
overflow: auto;
}
#content {
background: rgba(125, 175, 0, .7);
position: fixed;
width: 100%;
top: 0;
left: 0;
}
.transformed {
transform: translate(0, 5em);
}
<div id="bg">
<div id="container" class="transformed">
.<br>.<br>.<br>.<br>.<br>.<br>.
this is a scrollable paragraph
<br>.<br>the "fixed" content does scroll with the paragraph
<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.
you can click to toggle the transformation On/Off
<br>.<br>.<br>.<br>.<br>.
<span id="content">relatively fixed content</span>
</div>
</div>
However, I did find something that may help others facing the same issue.
It's not really a solution, since the "fixed" element will be only inside the container, (except for IE browsers where it will really be fixed to the document). But in my case, it's actually what I wanted and maybe it'll be fine for others too.
If you add a wrapper, set its height:100%; width:100%; and overflow:auto, then your "fixed" content won't scroll with the container.
Actually it's not you container which scrolls anymore, but the wrapper. So you might want to set the container's overflow:visible or hidden to avoid unwanted scrolling of the not so well "fixed" element.
Also, note that you need your wrapper be a block or inline-block element.
#bg {
border: 1px solid #AFA;
height: 100%;
width: 100%;
position: fixed;
top: 0;
left: 0;
}
#container {
border: 1px solid #FAF;
height: 50%;
width: 75%;
position: relative;
margin: 0 auto;
overflow: visible;
}
#wrapper {
height: 100%;
width: 100%;
overflow: auto;
}
#content {
background: rgba(125, 175, 0, .7);
position: fixed;
width: 100%;
top: 0;
left: 0;
}
.transformed {
transform: translate(0, 50%);
}
<div id="bg">
<div id="container" class="transformed">
<div id="wrapper">
.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.
<span id="content">relatively fixed content</span>
</div>
</div>
</div>
I am not familiar with this bug, but when you use positioned: fixed; the element is positioned relative to the browser window, so it doesn't really make any sense to put it inside a container.
This markup would be my recommendation:
<div class="fixed"></div>
<div class="container"></div>
Once you use position: fixed; on any element it is positioned relative to the view-port. Directly from page in MDN about position property.
fixed
Do not leave space for the element. Instead, position it at a specified position relative to the screen's viewport and don't move it when scrolled.
So what you are experiencing is a what it is actually supposed to work like and not a 'bug'.
Now if what you want is something that is positioned with relation to the .container div and translate with it than you will have to use absolute positioning here. Take a look at this fiddle. The important CSS is-
.container {
width: 200px;
height: 100px;
position: relative;
}
.absolute {
position: absolute;
width: 20px;
height: 10px;
top: 50px;
left: 50px;
}
Notice that with positioning the inner div as absolute I have also positioned the outer div as relative as the inner div takes its position in reference to the closest parent div positioned as anything different from static.
I am trying to overlap the div2 over div1
http://jsfiddle.net/user1212/QsLVB/
<div id="div1"></div>
<div id="div2"></div>
#div1{
width: 200px;
height: 200px;
background-color: olive;
float: right;
position: relative;
z-index: 1;
}
#div2{
width:100px;
height: 100px;
background-color: orange;
float: right;
position: relative;
z-index: 2;
}
I need both to float to the right.
There's a number of ways you could get them to overlap.
First example http://jsfiddle.net/QsLVB/3/
Use negative margins.
#div2{
margin: 20px -100px 0 0;
}
Second example http://jsfiddle.net/QsLVB/4/
Just make the div a child of the other one. In this case z-index will not do anything, since the child will always be shown above the parent.
<div id="div1">
<div id="div2"></div>
</div>
Also, you can go other routes and use position: absolute instead and like top/right values, etc.
#div1{
width: 200px;
height: 200px;
background-color: olive;
position: absolute;
z-index: 1;
right: 0;
}
#div2{
width:100px;
height: 100px;
background-color: orange;
position: absolute;
z-index: 2;
right: 0;
}
Actually you don't need negative margins or anything like that - you can just modify your existing css to solve the problem. I ran it using my code and it works great. This is the solution I would choose in your case.
Firstly to layer anything you need to use position: absolute or position: fixed (which work similarly for our needs here).
Secondly, once using position absolute (or fixed) you can choose to position one or more edges of each div using top: right: bottom: and left:. You don't need any of them, but providing at least one will guarantee that that edge will appear at that pixel position within it's containing div.
Assuming you place these two divs within the body tag or at least don't need them to be further right than their outer containing div, you can set "right: 0;" for each div and they will work similarly to float: right for relative positioned divs (As in your original code), but since they are absolute positioned they can occupy the same space.
Then use z-index to control which one appears on top of the other.
cheers :-D
You could also set the left or right property of div2
DEMO using left
#div2 {
...
left: 200px;
}
Or instead of using float:right, use position:absolute in conjunction with right
DEMO
#div1, #div2 {
/* float: right; // removed */
position: absolute; /* changed from relative */
right: 0; /* added */
}
This is easy to accomplish if you put div2 inside div1, giving div2 an absolute position and right: 0 while its parent, div1, has a relative position.
See it in action here: http://jsfiddle.net/heGJt/
Here's the simplified CSS:
#div1 {
position: relative;
width: 200px;
height: 200px;
background-color: olive;
float: right;
}
#div2 {
width:100px;
height: 100px;
background-color: orange;
position: absolute;
right: 0;
}
And the HTML:
<div id="div1">
<div id="div2"></div>
</div>