z-index not working with position absolute - html

I opened the console (chrome\firefox) and ran the following lines:
$("body").append("<div id=\"popupFrame\" style=\"width:100%;height:100%;background-color:black;opacity:0.5;position:absolute;top:0;left:0;z-index:1;\" />");
$("body").append("<div id=\"popupContent\" style=\"width:200px;height:200px;z-index:1000;background-color:white;\" >dasdasdsadasdasdasdasdasd</div>");
The #popupContent should be above all but it's affected by the #popupFrame opacity.
The content is not contained in #popupFrame which makes this very weird.
The goal is to create a firefox-like alert box.

The second div is position: static (the default) so the z-index does not apply to it.
You need to position (set the position property to anything other than static, you probably want relative in this case) anything you want to give a z-index to.

Old question but this answer might help someone.
If you are trying to display the contents of the container outside of the boundaries of the container, make sure that it doesn't have overflow:hidden, otherwise anything outside of it will be cut off.

Opacity changes the context of your z-index, as does the static positioning. Either add opacity to the element that doesn't have it or remove it from the element that does. You'll also have to either make both elements static positioned or specify relative or absolute position. Here's some background on contexts: http://philipwalton.com/articles/what-no-one-told-you-about-z-index/

z-index only applies to elements that have been given an explicit position. Add position:relative to #popupContent and you should be good to go.

I faced this issue a lot when using position: absolute;, I faced this issue by using position: relative in the child element. don't need to change position: absolute to relative, just need to add in the child element look into the beneath two examples:
let toggle = document.getElementById('toggle')
toggle.addEventListener("click", () => {
toggle.classList.toggle('change');
})
.container {
width: 60px;
height: 22px;
background: #333;
border-radius: 20px;
position: relative;
cursor: pointer;
}
.change .slide {
transform: translateX(33px);
}
.slide {
transition: 0.5s;
width: 20px;
height: 20px;
background: #fff;
border-radius: 20px;
margin: 2px 2px;
z-index: 100;
}
.dot {
width: 10px;
height: 16px;
background: red;
position: absolute;
top: 4px;
right: 5px;
z-index: 1;
}
<div class="container" id="toggle">
<div class="slide"></div>
<div class="dot"></div>
</div>
This's how it can be fixed using position relative:
let toggle = document.getElementById('toggle')
toggle.addEventListener("click", () => {
toggle.classList.toggle('change');
})
.container {
width: 60px;
height: 22px;
background: #333;
border-radius: 20px;
position: relative;
cursor: pointer;
}
.change .slide {
transform: translateX(33px);
}
.slide {
transition: 0.5s;
width: 20px;
height: 20px;
background: #fff;
border-radius: 20px;
margin: 2px 2px;
z-index: 100;
// Just add position relative;
position: relative;
}
.dot {
width: 10px;
height: 16px;
background: red;
position: absolute;
top: 4px;
right: 5px;
z-index: 1;
}
<div class="container" id="toggle">
<div class="slide"></div>
<div class="dot"></div>
</div>
Sandbox here

If you're a big 'ol dumdum like me (but know your positioning rules are 100% correct) trying to get something like this:
to look like this:
Your solution may be as simple as ensuring your background is not transparent for the element you want in front of/behind the other element.

I had the the same problem, and i tried to solve it by appending the element with absolute position in a div with a sticky position, my problem was with speeddial (reactjs + material), so i dont know if it will work with all cases.

It may be too late, but it can be preferred as an alternative method. The order of layering for displaying elements in the absolute position depends on the order in which the elements are inserted into the parent element. In other words, instead of using z-index, it is possible to send it to the back by adding it with $(parent).prepend(me), and to bring it to the front by adding it with $(parent).append(me).
function BringToFront(){
$("#parent").append($("#me"));
}
function SendToBack(){
$("#parent").prepend($("#me"));
}
#mySister{
position:absolute;
left:25px;
top:25px;
width:100px;
height:100px;
background-color: red;
}
#me{
position:absolute;
left:50px;
top:50px;
width:100px;
height:100px;
background-color: yellow;
}
#myBrother{
position:absolute;
left:75px;
top:75px;
width:100px;
height:100px;
background-color: blue;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="parent">
<div id="mySister"> </div>
<div id="me">Hello! this is me!</div>
<div id="myBrother"> </div>
</div>
<button type="button" onclick="BringToFront()">Bring to front</button>
<button type="button" onclick="SendToBack()">Send to back</button>

Related

z-index wont work positions

I'm trying to achieve that the erf_fromto would have a higher z-index than left_side, cause left_side do have a border, while i want the erf_fromto to be over the border.
this is how it looks like currently, while I want the erf_fromto to be over the line.
<body class="parent" ng-app="myApp">
<div class="left_side child"></div>
<div class="right_side">
<div class="erf_block" style="position:relative;">
<div class="erf_fromto">2011 - 2012</div>
</div>
</div>
</body>
css:
.left_side {
width:35%;
float:left;
border-right: 3px solid #F6F6F6;
}
.parent {
overflow: hidden;
position: relative;
}
.child {
height: 100%;
position: absolute;
}
.erf_fromto {
position: absolute;
left: -122px;
border: 2px solid #F6F6F6;
padding: 5px;
font-weight: bold;
box-shadow: 0px 0px 2px #F6F6F6;
font-size: 15px;
z-index: 99;
overflow: hidden;
}
codepen: http://codepen.io/anon/pen/XjzwdN
z-index applies to an element and it's children. Since .erf_fromto is nested inside .erf_block, which is inside .right_side you'll want to ensure that it's .right_side that has the higher z-index than .left_side!
From MDN:
The z-index property specifies the z-order of an element and its descendants. When elements overlap, z-order determines which one covers the other. An element with a larger z-index generally covers an element with a lower one.
If you also put a position: relative; and z-index:0; to the .left_side child it will work
Maria,
If you add a background to left_side and erf_fromto you will see they are on the correct position.
I think you just need add background property on your erf_fromto class:
.erf_fromto {
...
background: white;
...
}
I hope it helps...
Good Luck!

Unexpected CSS Positioning Bug

I have the following code :
<!DOCTYPE html>
<html>
<head>
<title>Kastflix</title>
<style type="text/css">
.moviepane { background-color: #181816; top: 41px; left: 181px; position: fixed; width: 100%; height: 100%; }
.movietile { background-color: #181816; margin-top: 13px; margin-left: 12px; margin-right: 12px; width: 135px; height: 235px; display:inline-block; vertical-align: top }
.movieposter { width: 135px; height: 197px; border:1px solid #000000; border-radius: 3px; transition: all 0.5s; position: absolute; }
.movieposter:hover { border:1px solid #0094ff; }
.linkoverlay { width: 137px; height: 199px; background-color: #000000; opacity: 0; transition: all 0.5s; pointer-events: none; }
.movieposter:hover + .linkoverlay { opacity: 0.6; }
</style>
</head>
<body>
<div class="moviepane">
<div class="movietile">
<a href="a">
<img class="movieposter" src="\movies\Delivery%20Man%20(2013)%20%5B1080p%5D\Delivery%20Man%20(2013)%20%5B1080p%5D.jpg"></img>
<div class="linkoverlay"></div>
</a>
<p class="moviename">Delivery Man</p>
<p class="movieyear">2013</p>
</div>
</div>
</body>
</html>
When I hover over a movie tile, It looks like this :
As I see it, the movie poster is positioned absolute, so it will be relative to the closest parent container with a non-static position type. But In this case, there is none. So shouldn't it be relative to the document? Why is the movieposter relative to the movietile?
Any help is appreciated!
You haven't specified any offsets on the element despite it being absolutely positioned, so it will not move from its static position regardless of its containing block (i.e. regardless of whether any of its ancestors are themselves positioned or if it is anchored to the initial containing block otherwise).
This is intended behavior; see my answer to this question for why exactly it works this way when the offsets are not specified.
Note however that absolutely positioning this element does affect its following sibling (the overlay), because absolute positioning removes the element from normal flow and so its following sibling is no longer aware of its position.

Floating Div Over An Image

I'm having trouble floating a div over an image. Here is what I am trying to accomplish:
.container {
border: 1px solid #DDDDDD;
width: 200px;
height: 200px;
}
.tag {
float: left;
position: relative;
left: 0px;
top: 0px;
z-index: 1000;
background-color: #92AD40;
padding: 5px;
color: #FFFFFF;
font-weight: bold;
}
<div class="container">
<div class="tag">Featured</div>
<img src="http://www.placehold.it/200x200">
</div>
In this image:
I want the "Featured" box to float over top of the image but instead it seems to "clear" the float and cause the image to wrap to the next line, as though it was displaying as a block element. Unfortunately, I can't figure out what I am doing wrong. Any ideas?
Never fails, once I post the question to SO, I get some enlightening "aha" moment and figure it out. The solution:
.container {
border: 1px solid #DDDDDD;
width: 200px;
height: 200px;
position: relative;
}
.tag {
float: left;
position: absolute;
left: 0px;
top: 0px;
z-index: 1000;
background-color: #92AD40;
padding: 5px;
color: #FFFFFF;
font-weight: bold;
}
<div class="container">
<div class="tag">Featured</div>
<img src="http://www.placehold.it/200x200">
</div>
The key is the container has to be positioned relative and the tag positioned absolute.
Change your positioning a bit:
.container {
border: 1px solid #DDDDDD;
width: 200px;
height: 200px;
position:relative;
}
.tag {
float: left;
position: absolute;
left: 0px;
top: 0px;
background-color: green;
}
jsFiddle example
You need to set relative positioning on the container and then absolute on the inner tag div. The inner tag's absolute positioning will be with respect to the outer relatively positioned div. You don't even need the z-index rule on the tag div.
Actually just adding margin-bottom: -20px; to the tag class fixed it right up.
http://jsfiddle.net/dChUR/7/
Being block elements, div's naturally have defined borders that they try not to violate. To get them to layer for images, which have no content beside the image because they have no closing tag, you just have to force them to do what they do not want to do, like violate their natural boundaries.
.container {
border: 1px solid #DDDDDD;
width: 200px;
height: 200px;
}
.tag {
float: left;
position: relative;
left: 0px;
top: 0px;
background-color: green;
z-index: 1000;
margin-bottom: -20px;
}
Another toue to take would be to create div's using an image as the background, and then place content where ever you like.
<div id="imgContainer" style="
background-image: url("foo.jpg");
background-repeat: no-repeat;
background-size: cover;
-webkit-background-size: cover;
-mox-background-size: cover;
-o-background-size: cover;">
<div id="theTag">BLAH BLAH BLAH</div>
</div>
You've got the right idea. Looks to me like you just need to change .tag's position:relative to position:absolute, and add position:relative to .container.
You can achieve this with relative position.
But why isn't your code working?
An element with position:relative keeps it's position and also still affects all other following elements. That's the reason why your div won't overlap the image by just using z-index.
You'll still need to position the div element with, for example: top:-28px where the amount would be the height of the element with tag class.
Note: top has no effect on non-positioned elements. It works with absolute, relative and sticky.
If you add top:-28px to the tag element it will only overlap the image if the z-index it has a higher number. This is the importance of z-index in this case.
.container {
width: 200px;
height: 200px;
}
.tag {
position: relative;
z-index: 1;
float: left;
padding: 5px;
color: #FFFFFF;
font-weight: bold;
background-color: #92AD40;
}
img{
position:relative;
z-index:0;
top:-28px;
}
<div class="container">
<div id='tag' class="tag">Featured</div>
<img id='img' src="https://i.stack.imgur.com/rUDax.png">
</div>
If you want to play a bit with this concepts
I added some JS code to toggle between different styles
const tag = document.getElementById('tag')
const img = document.getElementById('img')
const label1 = document.getElementById('label1')
const label2 = document.getElementById('label2')
function togglePosition(){
if(!tag.style.position){
tag.style.position = 'relative'
img.style.position = 'relative'
label1.innerHTML = 'Relative position added'
}
else{
tag.style.position = null
img.style.position = null
label1.innerHTML = 'Add relative position'
}
}
function toggleZindex(){
if(!tag.style.zIndex){
tag.style.zIndex = '1'
img.style.zIndex = '0'
label2.innerHTML = 'z-index (1 and 0) added to elements'
}
else{
tag.style.zIndex = null
img.style.zIndex = null
label2.innerHTML = 'Add z-index to elements'
}
}
.container {
margin-top:20px;
width: 200px;
height: 200px;
}
.tag {
float: left;
padding: 5px;
color: #FFFFFF;
font-weight: bold;
background-color: #92AD40;
}
img{
top:-28px;
}
<input type='checkbox' onclick='togglePosition()'/>
<label id='label1'>Add relative position</label>
<br/>
<input type='checkbox' onclick='toggleZindex()'/>
<label id='label2'>Add z-index to elements</label>
<div class="container">
<div id='tag' class="tag">Featured</div>
<img id='img' src="https://i.stack.imgur.com/rUDax.png">
</div>
you might consider using the Relative and Absolute positining.
`.container {
position: relative;
}
.tag {
position: absolute;
}`
I have tested it there, also if you want it to change its position use this as its margin:
top: 20px;
left: 10px;
It will place it 20 pixels from top and 10 pixels from left; but leave this one if not necessary.

How to apply an opacity without affecting a child element with html/css?

I want to achieve this using html and css:
I have tried to set the opacity of the container to 0.3 and the box to 1, but it doesn't work: both divs have 0.3 opacity.
jsFiddle of my try here
The effect I am trying to achive is a popup box that comes on top of the page. It is highlighted by fading the content below (by lowering the opacity).
You can use opacity in combination with background color, like this:
#container {
border: solid gold 1px;
width: 400px;
height: 200px;
background:rgba(56,255,255,0.1);
}
#box {
border: solid silver 1px;
margin: 10px;
width: 300px;
height: 100px;
background:rgba(205,206,255,0.1);
}
<div id="container">
containter text
<div id="box">
box text
</div>
</div>
​Live demo
As far as I know you can't do it in a simple way. There a couple of options here:
Use absolute positioning to position box "inside" the container.
#container {
opacity: 0.3;
background-color: #777788;
position: absolute;
top: 100px;
left: 100px;
height: 150px;
width: 300px;
}
#box {
opacity: 1;
background-color: #ffffff;
position: absolute;
top: 110px;
left: 110px;
height: 130px;
width: 270px;
}
<div id="container"></div>
<div id="box">
<p>Something in here</p>
</div>
Use Javascript - almost the same as above, but position and size don't have to be hardcoded.
You can't apply an opacity property without affecting a child element!
"Opacity applies to the element as a whole, including its contents, even though the value is not inherited by child elements. Thus, the element and its children all have the same opacity relative to the element's background, even if they have different opacities relative to one another... If you do not want to apply opacity to child elements, use the background property instead." https://developer.mozilla.org/en-US/docs/Web/CSS/opacity
If you want the opacity to be applied only to the background, without affecting the child elements, use:
background-color: rgba(255, 255, 255, .3)
However, you can achieve the desired effect if you place them inside a div parent element and use CSS position property:
.parent {
border: solid green 3px;
position: relative;
width: 400px;
height: 200px;
}
.sibling-one {
border: solid red 3px;
position: absolute;
box-sizing: border-box;
width: 400px;
height: 200px;
opacity: .3;
}
.sibling-two {
border: solid blue 1px;
margin: 10px;
width: 200px;
height: 100px;
position: absolute;
transform: translateY(50%);
}
<div class="parent">
<div class="sibling-one">
<p>A sibling's one element</p>
</div>
<div class="sibling-two">
<p>A sibling's two element</p>
</div>
</div>
Try using rgba as a 'pre content' overlay to your image, its a good way to keep things responsive and for none of the other elements to be effected.
header #inner_header_post_thumb {
background-position: center;
background-size: cover;
position: relative;
background-image: url(https://images.pexels.com/photos/730480/pexels-photo-730480.jpeg?w=1260&h=750&auto=compress&cs=tinysrgb);
border-bottom: 4px solid #222;
}
header #inner_header_post_thumb .dark_overlay {
position: relative;
left: 0;
top: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.75);
}
header #inner_header_post_thumb .dark_overlay .container .header-txt {
padding-top: 220px;
padding-bottom: 220px;
color: #ffffff;
text-align:center;
}
header #inner_header_post_thumb .dark_overlay .container .header-txt h1 {
font-size: 40px;
color: #ffffff;
}
header #inner_header_post_thumb .dark_overlay .container .header-txt h3 {
font-size: 24px;
color: #ffffff;
font-weight: 300;
}
header #inner_header_post_thumb .dark_overlay .container .header-txt p {
font-size: 18px;
font-weight: 300;
}
header #inner_header_post_thumb .dark_overlay .container .header-txt p strong {
font-weight: 700;
}
<header>
<div id="inner_header_post_thumb">
<div class="dark_overlay">
<div class="container">
<div class="row header-txt">
<div class="col-xs-12 col-sm-12">
<h1>Title On Dark A Underlay</h1>
<h3>Have a dark background image overlay without affecting other elements</h3>
<p>No longer any need to re-save backgrounds as .png ... <strong>Awesome</strong></p>
</div>
</div>
</div>
</div>
</div>
</header>
See a working codepen here
Using background-color: rgba(#777788, 0.3); instead of opacity could maybe fix the problem.
Apply this css rule
.alpha60 {
/* Fallback for web browsers that doesn't support RGBa */
background: rgb(0, 0, 0);
/* RGBa with 0.6 opacity */
background: rgba(0, 0, 0, 0.6);
/* For IE 5.5 - 7*/
filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#99000000, endColorstr=#99000000);
/* For IE 8*/
-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#99000000, endColorstr=#99000000)";
}
In addition to this, you have to declare background: transparent for IE web browsers.
For more details visit the following link:
http://robertnyman.com/2010/01/11/css-background-transparency-without-affecting-child-elements-through-rgba-and-filters/
Any child of an element with opacity set will take on that opacity.
To achieve this style you could use rgba colours and filters for IE for the background, and opacity on the textual elements. So long as the second box isn't a child of one of the text elements, then it won't inherit the opacity.
Another workaround is to simply use an overlay background to create a similar effect.
I personally like a black overlay with about a 65% opacity, but for what you are trying to do you may want to use a white overlay at round 70%.
Create a small (100 x 100 or less) PNG in Photoshop or GIMP that has the color and opacity you want. Then just set that as the background of your light box.
If you create multiple PNGs at different opacities you can easily switch between them with JS or dynamically at load via backend scripting.
It's not technically what you are trying to do, but aesthetically it can give a very similar effect and UX wise accomplishes the same thing. It is also very easy to do, and widely supported across pretty much everything.
Opacity will always inherits by the child element regardless whatever the element in there, there is no workaround up to today have suggested, when the moving of the child element outside the transparency background is not an option like in a popup menu/dialog box creation, use of background with the rgba is the solution.
Here is a input box that i created that i can turn on or off with the class property invisible by javascript
<div id="blackout" class="invisible">
<div id="middlebox">
<p>Enter the field name: </p>
<input type="text" id="fieldvalue" />
<input type="button" value="OK" id="addfname" />
</div>
</div>
CSS
#blackout {
z-index: 9999;
background: rgba(200, 200, 200, 0.6);
height: 100%;
width: 100%;
display: block;
padding: 0px;
clear: both;
float: left;
position: absolute;
margin-top: -10px;
margin-right: 0px;
margin-bottom: 0px;
margin-left: -10px;
}
#blackout #middlebox {
border: thick solid #333;
margin: 0px;
height: 150px;
width: 300px;
background-color: #FFF;
top: 50%;
left: 50%;
position: absolute;
-ms-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
padding: 10px 50px 0px 50px;
}
#middlebox p {
float: left;
width:100%;
clear:both;
}
#middlebox input {
clear:both;
margin-bottom:10px;
}
#middlebox input[type=text]{
width:100%;
}
#middlebox input[type=button]{
float:right;
width:30%;
}
.invisible{
visibility:hidden !important;
}
Use such elements that you can add :before or :after. My solution
<div class="container">
<div>
Inside of container element is not effected by opacity.
</div>
</div>
Css.
.container{
position: relative;
}
.container::before{
content: '';
height: 100%;
width: 100%;
position: absolute;
background-color: #000000;
opacity: .25
}
This might not be the most orthodox method but you can use a small semi-transparent background image for each div / container that repeats. It does seem that in this day and age you should be able to achieve this in pure (simple not hackish) css with no js but as the answers above show it isn't that straight forward...
Using a tiled image might seem dated but will work no worries across all browsers.
You can add a container's sibling absolutely positioned behind container, with the same size, and apply opacity to it.
And use no background on your container.
Now container's children have no opaque parent and the problem vanishes.

CSS I want a div to be on top of everything

How do I make an html div tag to be on top of everything? I tried adding z-index: 1000, but it remains the same.
In order for z-index to work, you'll need to give the element a position:absolute or a position:relative property. Once you do that, your links will function properly, though you may have to tweak your CSS a bit afterwards.
Yes, in order for the z-index to work, you'll need to give the element a position: absolute or a position: relative property... fine.
But... pay attention to parents!
The element's z-index may be limited by its parent's z-index value.
You have to go down the nodes of the elements to check if at the level of the common parent the first descendants have a defined z-index.
All other descendants can never be in the foreground if at the base there is a lower definite z-index.
In this snippet example, div1-2-1 has a z-index of 1000 but is nevertheless under the div1-1-1 which has a z-index of 3.
This is because div1-1 has a z-index greater than div1-2.
.div {
}
#div1 {
z-index: 1;
position: absolute;
width: 500px;
height: 300px;
border: 1px solid black;
}
#div1-1 {
z-index: 2;
position: absolute;
left: 230px;
width: 200px;
height: 200px;
top: 31px;
background-color: indianred;
}
#div1-1-1 {
z-index: 3;
position: absolute;
top: 50px;
width: 100px;
height: 100px;
background-color: burlywood;
}
#div1-2 {
z-index: 1;
position: absolute;
width: 200px;
height: 200px;
left: 80px;
top: 5px;
background-color: red;
}
#div1-2-1 {
z-index: 1000;
position: absolute;
left: 70px;
width: 120px;
height: 100px;
top: 10px;
color: red;
background-color: lightyellow;
}
.blink {
animation: blinker 1s linear infinite;
}
#keyframes blinker {
50% {
opacity: 0;
}
}
.rotate {
writing-mode: vertical-rl;
padding-left: 50px;
font-weight: bold;
font-size: 20px;
}
<div class="div" id="div1">div1</br>z-index: 1
<div class="div" id="div1-1">div1-1</br>z-index: 2
<div class="div" id="div1-1-1">div1-1-1</br>z-index: 3</div>
</div>
<div class="div" id="div1-2">div1-2</br>z-index: 1</br><span class='rotate blink'><=</span>
<div class="div" id="div1-2-1"><span class='blink'>z-index: 1000!!</span></br>div1-2-1</br><span class='blink'> because =></br>(same</br> parent)</span></div>
</div>
</div>
More simply :
For z-index:1000 to have an effect you need a non-static positioning scheme.
Add position:relative; to a rule selecting the element you want to be on top
You need to add position:relative; to the menu. Z-index only works when you have a non static positioning scheme.
z-index property enables you to take your control at front. the bigger number you set the upper your element you get.
position property should be relative because position of html-element should be position relatively against other controls in all dimensions.
element.style {
position:relative;
z-index:1000; //change your number as per elements lies on your page.
}
I gonna assumed you making a popup with code from WW3 school, correct?
check it css. the .modal one, there're already word z-index there. just change from 1 to 100.
.modal {
display: none; /* Hidden by default */
position: fixed; /* Stay in place */
z-index: 1; /* Sit on top */
padding-top: 100px; /* Location of the box */
left: 0;
top: 0;
width: 100%; /* Full width */
height: 100%; /* Full height */
overflow: auto; /* Enable scroll if needed */
background-color: rgb(0,0,0); /* Fallback color */
background-color: rgba(0,0,0,0.4); /* Black w/ opacity */
}
It seems like nesting an element inside a <dialog> element puts it on top of everything. It is placed both horizontally and vertically centered to the screen if you use showModal() but you lose the interactivity with other elements in the page.
document.querySelector("dialog").showModal();
<dialog>
<div class="element">I am on top of everything else</div>
</dialog>
<div class="backdrop">Backdrop element</div>
If you still want interactivity with the background elements, you can use the show() method. It is placed only horizontally centered to the screen.
document.querySelector("dialog").show();
<dialog>
<div class="element">I am on top of everything else</div>
</dialog>
<div class="backdrop">Backdrop element to check if I am underneath or not.</div>