Why this z-index behaviour? - html

This is my code :
<div id="first">
<div id="first-internal"> </div>
</div>
<div id="fixed"> </div>
#first
{
position:relative;
}
#first-internal
{
position:relative;
z-index:100;
background-color:blue;
width:400px;
height:400px;
}
#fixed
{
position:absolute;
top:0;
left:0;
width:200px;
height:200px;
background-color:red;
z-index:41;
}
Why I can't see #fixed? It is after #first, so it must have more "z-index point" then #first. The content of #fixed (also if childrens of #first have z-index:9000) must be displayed.

The block with greater z-index should be always on top. If you read the spec you can see that putting a z-index will create a new stack context, which mean that it will basically create a layer on top of other layers with a smaller z-index, no matter the order in the HTML or css.
So in your case #fixed has a lower z-index than #first-internal, so #first-internal is on top. That's all ;)
BTW, this stack context is badly implemented in IE and it will act differently.

It's all about stacking contexts as linked to in the css visual formatting model documentation. n the context of body:
#first (no z-index) qualifies as a positioned descendant with stack level 0 this element does not start a new stacking context (see below for details)
#fixed (z-index > 0) has a positive stack level and renders on higher
Because of that, regardless of how high you set z-index of #first decsendants, they will still remain in a lower stack relative to #first
These behaviors are identical to those of layers 6 & 7 respectively, as described in the linked documentation.
Update:
I've always found MDN docos easier to understand. Basically #first does not start a new stacking context (it is relatively positioned, but it has the default z-index:auto).
This means that #first-internal and #fixed render within the same stacking context, and the one with higher z-index is rendered on top! This is layer 6 behavior as described in the original spec linked.

When you make an element to position:absolute it doesn't takes any space in the document. Rather it behaves as if its floating. And its a basic nature of HTML/CSS that position:absolute objects have lesser z-index than position:relative.
This is because position:relative objects has its own existance, it doesn't float as the absolute elements.
I have posted few links below you can have a short study on these two properties :
http://webdesign.about.com/od/advancedcss/a/aa061307.htm
http://www.onextrapixel.com/2009/05/29/an-indepth-coverage-on-css-layers-z-index-relative-and-absolute-positioning/
Hope this clarifies your query.

Related

is it possible to create a new stacking context WITHOUT the element being painted as if it's positioned?

what is the question?
Under the current spec of CSS, for any element, creating a new stacking context is equivalent to being painted as if it's positioned.
Various properties creating a new context like opacity, isolation and so on inevitably lead the browser to handle the element with the property as positioned.
For example, if you just add to an element only opacity less than 1 and no position, the browser will paint the element as positioned. This means an element with opacity less than 1 and no position is always over any non-positioned elements.
Any property creating a new stacking context like isolation are the same.
You can check this info from this discussion.
https://github.com/w3c/csswg-drafts/issues/2717
So does anyone know any "hack" for creating a new stacking context WITHOUT the element being painted as if it's positioned?
why am i asking it?
background
I'm now developing a personal browser extension which adds popups, rect and so on to the web page the user is opening, through DOM scripting.
I don't wanna change anything about the original DOM including style, because I want the basic view of the web page to be kept as the original.
All I can do is just add/insert some new DOMs without destroying the web page.
the main problem
In the development mentioned above, i wanna insert some elements with position: relative between two div elements: one is without any setting of position and the other is without any setting of position but with float setting.
Please run the below snippet. I wanna insert some positioned elements between them.
<!DOCTYPE html>
<html lang="en">
<body>
<div class="cover">float: left and no-position</div>
<div class="target">no-float and no-position</div>
</body>
</html>
<style>
.target {
color: white;
background-color: red;
height: 200px;
width: 200px;
}
.cover {
color: white;
background-color: blue;
height: 100px;
width: 180px;
float: left;
}
</style>
Of course, just inserting some elements with position: relative fails, because positioned elements are painted always over non-positioned elements.
Here, if i can create a new stacking context between them, the goal will be achieved.
However, again, under the current spec of CSS, for any element, creating a new stacking context is equivalent to being painted as if it's positioned. That means newly created stacking contexts are always over the floated elements...
So anyone has a solution?? Thank you for taking your precious time!

Does fixed positioned element always stay above all the other divs?

I have a project: the name (div "h_name") has a fixed position. It's the first div in body, so it should, as I know, stay under all the elements. Unfortunately, somehow it stays above everything. How do I make it go under all other divs? Z-index doesn't work for it too.
Codepen -- https://codepen.io/polina-sotnikova/pen/VwQyXYG
<h1 class="h_name">dyslexia</h1>
You need a background on the content element or the stacking order will make no difference to what you see on the page. Here is a very simplified example based on the code you provided:
.h_name {
...
background:red;
z-index:-1;
}
.header {
background:blue;
}
And a full snippet here: https://codepen.io/29b6/pen/KKQZoMg
use a id for your class and apply below css.Hope it works...
HTML
<h1 class="h_name" id="h_name">dyslexia</h1>
CSS
#h_name{
z-index:-1!important;
}

Why does opacity property carry over to an "irrelevant" element? [duplicate]

I'm coding a "popup window" in JavaScript and I've come across an interesting thing:
The navy square under the popup window is visible even though I would expect it to be hidden. The popup was added after the square, so it should be on the top.
CSS opacity property of the navy square is 0.3. From what I've tried, it seems that every number from the interval (0,1) would yield the same result. If I change it to 1, then it behaves as expected (i.e. the part of the square under the popup is hidden).
I've tried to set the z-index property to 10 for the square and 100 for the popup, but it doesn't change anything.
What am I missing? Why is part of square displayed?
Tested browsers:
Firefox 3.6.x
Chrome 4
This is not a bug and is actually how it's supposed to work. It's a bit confusing as the elaborate description of Stacking Contexts doesn't mention anything about it. However, the visual formatting module links to the color module where this particular gotcha can be found (emphasis mine):
Since an element with opacity less than 1 is composited from a single
offscreen image, content outside of it cannot be layered in z-order
between pieces of content inside of it. For the same reason,
implementations must create a new stacking context for any element
with opacity less than 1. If an element with opacity less than 1 is
not positioned, implementations must paint the layer it creates,
within its parent stacking context, at the same stacking order that
would be used if it were a positioned element with ‘z-index: 0’ and
‘opacity: 1’. If an element with opacity less than 1 is positioned,
the ‘z-index’ property applies as described in [CSS21], except that
‘auto’ is treated as ‘0’ since a new stacking context is always
created. See section 9.9 and Appendix E of [CSS21] for more
information on stacking contexts. The rules in this paragraph do not
apply to SVG elements, since SVG has its own rendering model ([SVG11],
Chapter 3).
It's not a problem of opacity being more important than z-index, rather than z-index being relative to their stacking context (see z-index in the CSS2 specification).
In other words, z-index are only significant within the context of a positioned ancestor (whether its relative, absolute or fixed). What you need to do to fix your problem is add a position: relative; to the element that contain both your popup and your navy square, and probably add it a z-index: 1; . Seeing your screenshot it will probably be a top element such as a wrapper div.
Workaround for two elements, like divs: add a 0.99 opacity to your top element, and the order of both is reestablished.
opacity: 0.99;
An alternative to using opacity, is to use a transparent colour (with an alpha value)
So, rather than using
{
background: gray;
opacity: 0.5;
}
You could try
{
background: rgba(128,128,128,0.5);
}
It isn't identical, but I was encountering the same issue you were having, and the above fixed it.
Example code might be needed to debug this problem.
You might put overflow: hidden and possibly position: relative in a DIV which surrounds all the editor objects to try to force the elements to only be drawn within that DIV, e.g:
<div style="overflow: hidden; position: relative">
(Editor object buttons go here)
</div>
As a last resort, you could also try a iframe in between the two elements to try to stop them seeping through.
You might try to set the popup window's DIV like this using !important so the style doesn't change on applying new style or class:
background-color: white !important;
z-index: 100 !important;
opacity: 1.0 !important;
Then, make new CSS class:
.PopupElement
{
z-index: inherited;
opacity: inherited;
}
And add class to all elements in the window, like this for example:
<input value="posx" class="some_class PopupElement"/>
My guess is that this would work, since there is no priority in applying CSS attributes... as far as I know. =)
I had the same issue. Using rgba instead of color/opacity solved my problem. Working with LESS (in the Bootstrap framework), the fade() function did the conversion for me.
Although #Guillaume Esquevin already gave a great answer, I will try to expand on it in case someone ignores what a stacking context is (like I did).
As you can read here, there is something called stacking context, which refers to a group of elements sharing a parent that move together in the stack. An example could be a div and all its children.
There are three ways to create a stacking context: in the root of the document (the html element), by positioning the parent element, and by changing the opacity of the parent to something lower than 1.
Then, if you have a div with opacity lower than 1 and you want some sibling element of this div to appear behind it (and its children), you can create a new stacking context on such sibling by setting its position to relative or by changing its opacity as well.

CSS z-index seems unresponsive

I am working on a page where I am trying to create the illusion of a colored band wrapping around and behind a canvas.
To do this I have exported my graphics as two images - one which is to be located behind the canvas and one which is to be located in front.
For the canvas (.footer-container in the link below) I set position:relative and a z-index of 2, for the "behind" layer I set position:absolute and a z-index of 1 and for the "in-front" layer i did the same thing but with a z-index of 3.
But no matter what I do, I cannot seem to get any of my pictures to go behind the canvas. Currently the two IMG's are nested in the div of the canvas, but I also tried same procedure where they where not. Also, I did a similar thing another place on the same page and it works - I really can't seem to sort out what I am doing wrong?
Here is a link to the implementation:
http://dl.dropbox.com/u/706446/SFB%20html%20mockups/z-index-problem.html
Thanks!
I found a solution:
Don't set a z-index on the div#footer-container.
Set the z-index of div.footer-stripes_back to -1.
You can delete the z-index of div.footer-stripes_front, it's not neccessary and you can leave the DOM structure as it is.
Works for me in Chrome.
It's difficult to see the result, because the containers don't have a background.
#footer-top {
background:#fff;
position:relative;
z-index:3; }
#footer-back {
background:#fff;
position:relative;
z-index:3; }
.footer-stripes_front {
position:absolute;
z-index:4; }
.footer-stripes_back {
position:absolute;
z-index:2; }

Clicking through layers/divs

If I have two layers on a page, split horrizontally, with the second layer overlapping part of the first layer, is it possible to make it "click through"?
I have links in the first layer, which the second layer overlaps, which stops the links from being clickable. Is there a way to make the layer display, but be click through, while still having it's own links clickable?
edit:
Here is an example, with html and a stylesheet.
The test links become unclickable when inline with the header in Layer3, but below that they are fine. Is there a way to rectify this?
<title>Test</title>
<link rel="stylesheet" href="test.css" type="text/css">
<body>
<div id="Layer0">
<div id="Layer1" class="Layer1">
<h3 align="left">Brands</h3>
</div>
<div id="Layer2" class="Layer2"><h1>TEST</h1>
<div id="rightlayer">
TEST><p>TEST><p>TEST><p>TEST><p>TEST><p>TEST><p>TEST><p>TEST><p>TEST><p>TEST><p>TEST><p>TEST><p>TEST><p>TEST><p>TEST><p>TEST><p>TEST><p>TEST><p>TEST><p>TEST><p>TEST><p>TEST><p>TEST><p>TEST><p>TEST><p>TEST><p>
</div>
</div>
<div id="Layer3" class="Layer3"><h1>Ed Hardy Auctions</h1>
</div>
</div>
</body>
</html>
And the css
#Layer0 {
width:100%;
height:100%;
}
body {
margin:10px 10px 0px 10px;
padding:0px;
color:#999999;
font-family:"Trebuchet MS",arial,sans-serif;
font-size:70.5%;
}
#Layer1 {
position:absolute;
left:10px;
width:200px;
margin-top:17px;
font-size:1.0em;
padding-left:12px;
padding-top:8px;
}
#Layer2 {
background:#fff;
margin-left:199px;
color:#000;
}
#rightlayer {
float:right;
}
.Layer3 {
position:absolute;
top:67%;
padding:20px;
width: 100%;
}
Thought I would update this as I'd been struggling with this for a few hours and think i've found a solution. Looked into using Jquery but the CSS property:
pointer-events:none;
...did exactly what I wanted.
It is not possible if you want the divs to stay in their current x,y, (and most importantly) z - only the "top" layer is clickable.
Addendum post OP edit:
Think of CSS layout as if you were physically working with bits of paper (this is much easier to visualise if you give all your "layer" divs a different background colour). The rendering engine cuts out a bit of paper in the dimensions you give it (or it works out) for each element it finds. It does this in the order it encounters them putting each bit of paper on the page as it goes - the last item is going to be on top.
Now you've told the rendering engine to put your 3rd div in a position where it overlaps the 2nd. And now you expect to be able to "see" the covered content. Wouldn't work with paper, won't work with HTML. Just because it's transparent doesn't mean it's not taking up space.
So you have to change something.
Looking at your CSS and markup (which honestly could be cleaned up, but I'll assume there's other mark-up you're not showing us which justifies it) there's a couple of easy win ways:
1). Set a z-index of -1 on Layer3 - z-index is how you can change the layering order from the default (as encountered). This just moves the entirety of Layer3 below the rest of the page so what was hidden becomes exposed, but also vice versa depending on content.
2). Change the width from 100% to e.g. 80%, or more likely given your use of pos:abs set left:0px and right:199px; (I'm guessing that padding-left on Layer2 is an intended column width?). The cost of this is that your Layer3 is no longer 100% width
3). Google "CSS column layout" and find a pattern that reflects what you need and adapt that. Every CSS layout which can be done has been done a million times already. Standard techniques exist which solve your problems. CSS is hard if you haven't built up the experience, so leverage the experience of others. Don't reinvent wheels.
It would be a mammoth job, but it is possible.
You would need to capture the click event on the top layer/div, and find the cursor x-y position.
Then find all links in the layer/div underneath the top layer, and see if it's position on the screen falls around the current mouse position.
You could then trigger the click of the matched link.
I would use jQuery (if you are not already) for this and then re-post with a jQuery tag if you run into troubles.
It is hard to tell without seeing some code.
You could try setting z-index on the bottom layer but that works on elements that have been positioned with absolute, relative or fixed (position:absolute).
edit after seeing code:
Add position:relative; z-index:100; to #rightLayer.
Or you could remove the width:100% from .Layer3.
You may want to refactor your code and go with a two column layout for #rightLayer and .Layer3.
css
#Layer0 {
width:100%;
height:100%;
}
body {
margin:10px 10px 0px 10px;
padding:0px;
color:#999999;
font-family:"Trebuchet MS",arial,sans-serif;
font-size:70.5%;
}
#Layer1 {
width:200px;
margin-top:17px;
font-size:1.0em;
padding-left:12px;
padding-top:8px;
}
#Layer2 {
background:#fff;
margin-left:199px;
color:#000;
}
#rightlayer {
float:right;
}
.Layer3 {
}
html
<div id="Layer0">
<div id="Layer2" class="Layer2">
<h1>TEST</h1>
</div>
<div id="Layer1" class="Layer1">
<h3 align="left">Brands</h3>
</div>
<div class="content">
<div id="rightlayer">
TEST><p>TEST><p>TEST><p>TEST><p>TEST><p>TEST><p>TEST><p>TEST><p>TEST><p>TEST><p>TEST><p>TEST><p>TEST><p>TEST><p>TEST><p>TEST><p>TEST><p>TEST><p>TEST><p>TEST><p>TEST><p>TEST><p>TEST><p>TEST><p>TEST><p>TEST><p>
</div>
<div id="Layer3" class="Layer3">
<h1>Ed Hardy Auctions</h1>
</div>
</div>
</div>
I'm assuming from the example that the links in the rightlayer are the only links that need to be clicked, and that you don't have links in the other layers. If so, you could solve the problem by changing the z-index order of the divs.
Layer1 and Layer3 have position absolute, so if you add a position style (absolute or relative) to Layer2, you will be able to pull that div to the front, also pulling the rightlayer div to be in a higher layer than Layer3.
I added the following to the CSS:
#Layer2 {
position: relative;
z-index: 1;
}
From what I can see that leaves the current page setup just the way it is, but pulls all the elements (including the rightlayer with the links) to the front, so you'd be able to click all the links in it.
For debugging purposes I suggest adding background colors to all the different layers to get an idea of the z-index order of the different layers. With the background color in place it was quite easy to spot the layer that was falling over the links, but also to verify that the new z-index order makes the links available.
Hope this helps!
I submitted a bug years ago to the Firefox Bugzilla saying that there was this very bug in Firefox.
I was told by a Mozilla engineer that this was not actually a bug and that it is the correct behaviour as per the HTML/CSS specifications.
Unfortunately I can't find the original bug to reference as it was about 6 years ago.
The reason I submitted the bug was because I could click through the top div onto the links below when using IE (6 I think) but Firefox would not let me.
As usual, it turned out hat IE had the incorrect implementation and Firefox was working as intended by the spec.
Just because a div is transparent does not mean you should be able to click through it.
I'm not sure how you could get around this with JavaScript or CSS. I would take a step back and have a re-think about what you're trying to achieve and how you're trying to achieve it.
Greg
Can you not simply set the width of the div to auto (the default for absolute positioning - i.e. just delete the width:100% from .Layer3).
That way the div will only be as wide as is necessary, rather than unnecessarily overlapping the links.