Z-index Child Higher Than Parent

12 views
Skip to first unread message

Ogier Dudley

unread,
Jul 25, 2024, 7:20:45 PM7/25/24
to merovipun

I need a certain dynamic element to always appear on top of another element, no matter what order in the DOM tree they are. Is this possible? I've tried z-index (with position: relative), and it doesn't seem to work.

To display exactly the same when rendered. And for flexibility purposes (I'm planning on distributing a plugin that needs this functionality), I'd really like to not have to resort to absolute or fixed positioning.

For what it's worth, to perform the function I was wanting, I made a conditional statement where the overlapping child element would become transparent in the case it was blocking the view of its parent. It's not perfect, but it's something.

I figured out a way to actually put the child element behind its element by creating a pseudo-element which mimics the parent. Useful for stuff like dropdown-menus - hope it helps, user from eight years ago!

You simply have to give the child element a higher z-index. The code from the previous answer would not work, providing no z-index. Remember: only elements that carry the position attribute can make use of the z-index property.

Each rectangle is a div tag and I'll refer to them by their colours. Black is the main content of the page and has to be below red which is the footer. However I have an image (green) within red which extends over the text in black but must always lie below the text. The text in black is contained within a span tag (but this could be a div as well if it needs to be).

This would make the above picture possible. However, browsers won't allow a child element to have a higher z-index than its parent so the above is not possible. The text always has an inherited z-index of 1, and therefore lies below green.

Yeah unforunately it's actually not - assuming that the text is inside the black div. It doesn't matter what the z-index of the text is set to, it will always inherit the z-index of its parent div and will therefore have a lower z-index than the green div.

Would it be possible to separate the text in the black div from the div itself, put it into a div of its own as a child of or whatever, and then give that a higher z-index, background: transparent; and absolute position things to line them up? Just a thought.

Yeah I thought of that, and it's basically a good idea, but the content of the black div is loaded by AJAX and so the length is undetermined. I'd have to use javascript to measure the height of the div containing the text and then make the black div that same height. Perfectly possible, yes. But is it really necessary?

The problem lies in setting the position and size of the background layer when this layer is not a child of the text layer. If the text layer has a fixed position and size, you can simply copy these over to the background layer. However, with flexible layer heights, I don't see a way to match the size of a sibling.

We couldn't do it for layout columns and so we had to use techniques like faux columns or floats with clears to make two columns appears to have equal heights. It appears that this problem is very similar to the columns issue.

So what this means is that you must go up the dom from the element you are testing and make sure that if there is a positioned parent then its these parents you must address for the stacking order. Also note that only positioned elements can have a z-index applied. If you apply a z-index to a non positioned element then it is ignored. This means for static elements you must add position:relative (without coordinates) for the element to partake in the stacking strategy.

However if any of the parents of the overlay have a z-index lower than 99 and position:relative applied then the overlay will not cover the header. If you apply a z-index of 100 to the parent of the overlay (and position:relative) then the overlay will once again cover the header. However, it looks like you want a fixed header and when you now scroll the page the whole page content will go on top of the header and cover it up.

There is another solution if the above is not possible and that is to remove the overlay form its current context. The overlay is a fixed element and assuming you are doing what I think then it does not need to be in that structure.

Thanks but in this particular thing i do need to have the overlay inside the parents, because the parent in this case is a

  • that is a part of an image-slider. Inside this
  • there is an img, and when this image is clicked the overlay appears with a high-res version of the image that overlays the whole screen.

The z-index property accepts a numerical value which can be a positive or negative number.Elements will appear above another element if they have a higher z-index value.If no z-index is set on your elementsthen the default behaviour is that document source order dictates the Z axis.This means that elements further down the document sit on top of elements that appear before them.

In normal flow,if you set a specific value for z-index and it isn't working,you need to set the element's position value to anything other than static.This is a common place where people struggle with z-index.

Because .my-element now has a position value that's not staticand a z-index value that's not auto,it has created a new stacking context.This means that even if you set .child to have a z-index of -999,it would still not sit behind .my-parent.

In this example,the first parent element has a z-index of 1,so creates a new stacking context.Its child element has a z-index of 999.Next to this parent, there is another parent element with one child.The parent has a z-index of 2 and the child element also has a z-index of 2.Because both parents create a stacking context,the z-index of all children is based on that of their parent.

You don't need to apply z-index and position to create a newstacking context.You can create a new stacking context by adding a value for properties which create a new composite layersuch as opacity, will-change and transform.You cansee a full list of properties here.

To help with performance,the browser creates new composite layers which are layered on top of the canvas.These are a bit like post-it notes:moving one around and changing it doesn't have a huge impact on the overall canvas.A new composite layer is created for elements with opacity,transform and will-change because these are very likely to change,so the browser makes sure that change is performant as possible by using the GPU to apply style adjustments.

Except as otherwise noted, the content of this page is licensed under the Creative Commons Attribution 4.0 License, and code samples are licensed under the Apache 2.0 License. For details, see the Google Developers Site Policies. Java is a registered trademark of Oracle and/or its affiliates.

The first thing to know when you are setting a z-index is that it can only be applied to a positioned element. That means you have to set position: relative or absolute, or fixed. Anything other than static.

The moment you set a z-index other than auto on an element you are manually ordering the stack of how things are displayed on the page. And this gives you a lot of power. In this case, using less is more. The less you set the z-index on a page the less trouble it will cause you down the road.

By default, the child of an element is restricted to the z-index of its parent. If you manually set the z-index of a parent element it locks the children to its subset of z-index ranges. Here is a JsFiddle showing this in action.

Negative z-indexes behave pretty much the same as regular z-indexes. It is just important to know that if the parent has a z-index of anything other than auto it will still keep the negative one above it. This stack exchange has a very good example of it.

Now, I had a time where I needed to use a ::before element inside of a div to darken it but I needed to keep the text on top of it. The method I went with is setting its parent to 0 and then setting the ::before to -1. That way the div itself has its stacking context set and the ::before will be stuck in it and not go below the element it on top of.

In our case, none of the elements have a z-index value. So their stacking order is determined by their order of appearance. According to this rule, elements that come later in the markup will be on top of elements that come before them.

What this means is that adding the transform to the .cat-bottom element makes it behave as if it had a z-index of 0. Even though it doesn't have its position or z-index set at all! (W3.org has some informative but rather dense documentation on how this works with the opacity property)

The solution to this is to set position: relative and explicitly set z-index on at least the white block. You could go one step further and set position: relative and a lower z-index on the cat elements, just to be extra safe.

Reply all
Reply to author
Forward
0 new messages