Z-index not working nested absolutes divs - javascript

I've one question that why z-index not working in nested absolutes:
Here my code:
.relative {
width: 400px;
height: 400px;
margin: 50px auto;
position: relative;
background-color: #E7E7E7;
}
.absolute {
width: 200px;
height: 200px;
position: absolute;
top: 20px;
left: 20px;
background-color: #16E186;
z-index: 4;
}
.absoluteChild {
width: 75%;
height: 200px;
position: absolute;
top: 20px;
background-color: #1665e1;
z-index: 1;
}
.absoluteGrandchild {
width: 90%;
height: 80px;
position: absolute;
top: 20px;
background-color: #ff0056;
z-index: 1;
}
<div class="relative">
<div class="absolute">
Hello World
<div class="absoluteChild">
<div class="absoluteGrandchild">
</div>
</div>
</div>
</div>

Within a stacking context, child elements are stacked according to the
same rules previously explained. Importantly, the z-index values of
its child stacking contexts only have meaning in this parent. Stacking
contexts are treated atomically as a single unit in the parent
stacking context.
...
Each stacking context is self-contained: after the element's contents
are stacked, the whole element is considered in the stacking order of
the parent stacking context.
Source
It works as intentional. They are stacked in the correct order within their parent.

Without any z-index value, elements stack in the order that they appear in the DOM (the lowest one down at the same hierarchy level appears on top). Elements with non-static positioning will always appear on top of elements with default static positioning.
Also note that nesting plays a big role. If an element B sits on top of element A, a child element of element A can never be higher than element B.

z-index is a third-dimensional graphical indexing. Imagine a table where lots of papers are present. In this analogy the paper above the other paper has a higher z-index. However, you believe you experienced a different behavior, however, you are mistaken. Imagine a closed book on the table. It has a first page, a second page and so on. While you can index the pages of the book, you cannot put any of the pages of the book above or below the book unless you take it out of the book. In more technical terms, z-index indexes siblings, but will not index child-parents.

It's actually supposed to work that way.
Let me explain with boxes. Whenever you give a z-index value to an element, it becomes a box. Consequently, we have three boxes.
A big box: .absoulte
A medium box: .absoluteChild
A small box: .absoluteGrandchild
You can give an order of how your want the sibling boxes in to be stacked, but you can't say that you want a smaller, child box to be on top of a bigger, parent box.
To the packaging man, aka the browser, you are saying with your z-index values:
Get a big box and give it the number 4.
In the big box, get a medium box and give it a number 1.
In the medium box, get a small box and give it a number 1.
A box with a lower value will go under a box with a higher value of the same size.
Warning
You must not take a littler box and stack it on top or below that of a bigger box! What happens in the box stays in the box! Not doing so will cause an unstable stack of boxes that will give all developers a massive headache!
Lastly, you start the sizes of the box from the first time you set a z-index value.
no value
no value
no value
value (big box)
value (medium box)
value (small box)
value (medium box)
value (small box)
value (small box)
value (small box)
value (big box)
value (medium box)
value (small box)
value (medium box)
value (small box)
value (small box)
value (small box)

Related

Allow elements behind iframe to be clickable

I'm trying to embed a third party chatbot (via iframe) into my web application (ASP.NET MVC). As with any other chatbot, in this case as well, a button is displayed to initiate a chat (RHS below of the screen) and on click of the button, the the chatbot expands to take up the the entire RHS of the webapp (overlapping the buttons, which were present on the parent window). Following is the snippet of code:
<div id="chatBot">
<iframe frameborder="0" id="chatwindow" src="#System.Web.Configuration.WebConfigurationManager.AppSettings["ChatBotUrl"]"></iframe>
</div>
CSS:
#chatwindow {
height: 100vh;
width: 100%;
right: 15px;
}
#chatBot {
position: fixed;
right: 0;
bottom: 0;
height: 100vh;
width: 390px;
z-index: 11111;
}
Now the issue which I'm facing is that, as the chatbot div is taking up entire RHS real estate, any buttons or links behind the div is not clickable. I did try the following options:
Setting pointer-event: none
Subscribing to click event with in the iframe and manipulating attributes (this is kind of hacky way, but this does not work in my case due to cross domain restriction).
Using windows blur, to deduce a click (but this doesn't as the way to close the chatbot is via a button, embedded within the iframe).
Please do let me know, how to go about resolving the same.
Your chatbot div is taking up entire RHS because you tell it to do so in css by setting height: 100vh;. And combining that with position: fixed; and the width: 390px; means that the RHS for 390 pixels from your window is used by your <div id="chatBot".... Also using z-index: 11111; you are sure to have it overlay over everything on that page.
So this has nothing to do with your iframe. Is just pure css. But I imagine the problem is that you want your chat window to get to full width when is opened. Than you should build a javascript solution (or if you use some framework that allows you to conditionally render a class use that) to dynamically set the width to 100% or 100vh only when the chat is opened, and remove that when the chat is closed.
I also recomand you to use z-index only when you really need it, and try to not use such big numbers because is hard to maintain code like this.
Edit:
You can do that by creating a greater z-index context. But then your buttons will display over your chat iframe.
You can try creating the same z-index context for your chatBot div and also for the container of the buttons, that give the iframe display relative and z-index: 1
But it would be easier to work with contexts if you don't use such big numbers for z-index. (this is why I said you should use smaller z-index). Anyway this can work too. It doesn't matter that much. Is just not a very good practice.
Continuing: please note that if you have an element positioned relative, absolute or fixed with a z-index that is already a context. So if you have another element with positioned but with z-index slightly greater (let's say first has z-index:1 and second has z-index:2) that second context will be grater than the first, no matter what. So if you have inside the first element (with no z-index) another element, you can give what ever z-index you want (z-index: 99999 for example)it will only have that huge index in the first context. So will display under the second element if the overlap.
Example:
.big-z-index {
position: absolute;
z-index: 9999;
background:red;
width: 100px;
height:50px
}
.small-z-index {
position: absolute;
z-index: 2;
background:blue;
width: 50px;
height:20px
}
<div style="position: absolute; z-index:1">
<div class="big-z-index"></div>
</div>
<div class="small-z-index"></div>
So if you have z-index context on containers, only if you have the same context you can position certain elements.

put radio button for fingerprint in bootstrap

Is it possible to integrate radio buttons with a hand image for fingerprinting in Bootstrap? Is it possible to have an exact positioning for radio buttons to put just upper each finger and it stay unchanged for popular browsers (IE, Firefox and Chrome)? Indeed, I want something like this:
To get this done you can use technique of element absolute positioning (radio-button) within parent element (image container).
/*
Set container position to relative
Note: This will not affect parent's current position
*/
.image-container {
position: relative;
}
/*
Now all children with position: absolute
would be position within their parent
*/
input[type="radio"] {
position: absolute;
top: 50%;
left: 40%;
}
For more details please take a look at the DEMO I have created. It also includes transparent labels so clicking on the finger will actually select a radio button.

position relative-absolute child margin bug?

Can anyone explain how I can prevent the margin of a sibling div from affecting the other one? It does not logically make sense to me why the browser is laying it out this way.
I am trying to get the yellow box to have it's top/left relative to the parent, but the blue box with a margin-top is affecting the yellow one.
http://jsfiddle.net/oufdfoLy/
section{
position: relative;
}
div.options{
position: absolute;
left: 10px;
top: 10px;
display: inline-block;
background: #ff0;
padding: 50px;
}
div.content{
height: 100px;
width: 100%;
background: #09c;
margin-top: 50px;
}
<article>
<section>
<div class='options'>
</div>
<div class='content'>
<h1>hello world</h1>
</div>
</section>
</article>
This is known as collapsing margins.
8.3.1 Collapsing margins
In CSS, the adjoining margins of two or more boxes (which might or might not be siblings) can combine to form a single margin. Margins that combine this way are said to collapse, and the resulting combined margin is called a collapsed margin.
One solution would be to set the overflow property of the parent element to something other than the default value, visible.
Values such as auto or hidden would produce the expect results.
(See the link above for alternative approaches to work around this.)
Updated Example
section {
position: relative;
overflow: auto;
}
Changing the overflow property's value establishes a new block formatting context.
9.4.1 Block formatting contexts
Floats, absolutely positioned elements, block containers (such as inline-blocks, table-cells, and table-captions) that are not block boxes, and block boxes with 'overflow' other than 'visible' (except when that value has been propagated to the viewport) establish new block formatting contexts for their contents.
In a block formatting context, boxes are laid out one after the other, vertically, beginning at the top of a containing block. The vertical distance between two sibling boxes is determined by the 'margin' properties. Vertical margins between adjacent block-level boxes in a block formatting context collapse.

Achieving Absolute positioning without Position attribute, using Margin/Padding

I am working on building Email Based HTML. Now as we know, Position attribute is not well supported in Email clients so i will have to go on without that. Now, looking at my options... i can go for either Margin or padding to position the elements.
The input elements can be relatively positioned or absolute. I'll just take the absolute part for now. So, my input will be for example
One Parent DIV (top:0, left:0)
A Child DIV (top:20, left:20)
Second Child DIV (top:20, left: 200)
Now, in a normal browser based HTML, these elements would easily be placed on their appropriate positions. But without the position: absolute or even top, left attributes. It get's tricky as the margin attribute arranges the elements relative to the other elements. Here is a sample run:
<div style="width: 600pt; height: 600pt; border:2px solid red; margin-left:20pt; margin-top: 30pt">
<div style="width: 100pt; height: 100pt; border:2px solid black; margin-left:20pt; margin-top: 30pt"></div>
<div style="width: 100pt; height: 100pt; border:2px solid black; margin-left:20pt; margin-top: 30pt"></div>
<div style="width: 100pt; height: 100pt; border:2px solid black; margin-left:20pt; margin-top: 30pt"></div>
</div>
Fiddle
My Expected outcome was, all the black divs overlapping each other, placed on the same position. That is possible if it calculates the margins according the the "Parent Element" but it is margining left from parent and top from the previous elements.
So My question now is, Is there a side way of using marging-left, top as top, left attributes and producing the same behavior as they would with position:absolute? Or simply, placing these three elements on top of each other using margin or padding attributes (No position, as it is not supported by Email clients)
I also know, using Divs for email isn't the best approach and i should consider using tables but trust me, the kind of HTML i am dealing with can only be generated using Divs and some playing around with margin or paddings. Any help will be appreciated.
You can use negative margins to achieve overlapping.
margin-top: -50pt
http://jsfiddle.net/pkdqh7kt/1/
Here is an example of stacking your divs horizontally:
http://jsfiddle.net/pkdqh7kt/2/
Also you can check this table to find out which CSS properties are currently supported by major email clients.

Simulating a "Card Layout" when using Flexbox

I'm having a rather complex problem here. I'd like to make a Layout in CSS featuring multiple Layers which means basically having multiple <div> elements stacked ontop of each other (or at least make it look like this) and only the top one is visible.
In many other GUI Environements this is known as a Card Layout.
So the plan was:
Create all <div class='layer'> elements in one parent <div class='container'> element
Make them have display: none initially
invoke $.show() or $.hide() to show or hide them
HTML:
<div id="containerOne">
<div class="layer a"></div>
<div class="layer b">
<div class="inner b1"></div>
</div>
<div class="layer c"></div>
</div>
CSS:
#containerOne {
width: 150px;
height: 150px;
background: red;
}
#containerOne .layer {
display : none;
width: 100%;
height: 100%
}
.a {
background: green;
}
.b {
background: orange;
}
.b1 {
width: 50%;
height: 50%;
background: yellow;
}
.c {
background: blue;
}
This works at first since the elements will not have any space reserved on the page initially and will only occupy space when shown.
Now if i have a nested element inside a Layer and i want it to have a size of 50% x 50% this also works well: Even if the layer div is set to display: none initially.
Now by default my Container div is set to display: block and all the size calculation seems to work fine and here's where my problem begins:
I need the Container div to have display: flex to take advantage of the Flexbox features of modern browsers. Instead of setting a fixed width for my Layers i now configure them to have flex: 1 so they grow to the full size of the container.
This also works as expected. With one exception: The nested Element that should have a size of 50% x 50% won't have a size at all. Debugging this in JavaScript shows that this is because at the moment the Layers are created they will all have a size of 0 x 0 and will first get their size assigned when they are shown by $.show().
What i would expect is that once they are shown, the nested element will grow to its 50% x 50% size but it doesn't.
Is there anything i can do about it? (good solutions and back-hack-workaround solutions).
I also made a Fiddle to demonstrate the problem and to play around with.
The thing you're expecting to happen should happen, but it doesn't (in Chrome) due to a bug. It actually works correctly in Firefox.
Here's a simplified version of your testcase with no dynamic changes:
http://jsfiddle.net/CN7e8/4/
This behavior was actually recently changed in the flexbox spec, to the behavior you're expecting. The issue is that your 50% height on b1 is resolving against an auto-height element (the flex item, b) and Chrome is treating that auto-height as an invalid percent basis, even though the auto-height can actually be resolved to the container's height. (It'll become the container's height due to the default align-items: stretch on the flex container, which makes auto-height flex items take on the container's height).
For reference, the spec change to clarify this is mentioned under ISSUE 3, part (a), in this post:
http://lists.w3.org/Archives/Public/www-style/2014Mar/0350.html
ANYWAY. To work around the Chrome bug, you can't have an auto-height on your flex item b, given that you're depending on it being a percent-basis. You have to give it an explicit height, e.g. height:100% (which more directly resolves against the container's height). Here's your fiddle, with that changed: http://jsfiddle.net/CN7e8/5/

Categories