The idea.
If you wrote my previous series CSS Only: to the infinity and beyond you know I like to play with CSS to explore its limits, and today I woke up with a strange, but simple idea: Auto-incremental z-indexes.
The development is pretty simple and straightforward: Being able to have a container div with many .layer
divs inside of it, each one with an incremental z-index
, auto-calculated via CSS.
I did many tries and I'll try to explain them in a simple and quick way.
TL;DR: It doesn't work. Or, at least, I didn't find a way to.
Let's go!
The HTML
The HTML part is the easiest one as it's exactly the one explained above:
<div class="main">
<div class="layer">
1
</div>
<div class="layer">
2
</div>
</div>
The CSS - Part 1
I wanted to use some modern CSS and went for Custom Properties aka CSS Variables.
.main {
--z-index: 0;
}
.layer {
z-index: var(--z-index);
}
.layer + .layer {
--z-index: var(--z-index) + 1;
}
As soon as I wrote that, I remembered you can't do calcs like that in CSS. So I went for the calc() function.
The CSS - Part 2
.main {
--z-index: 0;
}
.layer {
z-index: var(--z-index);
}
.layer + .layer {
--z-index: calc(var(--z-index) + 1);
}
Buuuuut, it doesn't work either.
You can't calc things like that in CSS, so I had to find another way.
Eureka!
Have you ever read about CSS Lists And Counters? I did in the past, but I've never used them as I never had a chance to, so, I though, "Maybe I could give it a try!"
The CSS - Part 3
Let's go full counters then!
.main {
counter-reset: section;
}
.layer {
z-index: counter(section);
}
.layer + .layer {
counter-increment: section;
}
I started with a counter-reset and then counter-incremented it at every subsequent selector.
But the CSS counter() function returns a <string>
and the z-index property is looking for an <integer>
, so well.. It doesn't work.
Conclusion
I guess my dream will stay a dream for a little as I don't know any other possible CSS-only solution for this.
That's why I'm asking you to think about it and let me know if you can find a way to achieve my goal.
Can we do it with the current CSS specs? Will we ever be able to?
Let's #discuss it in the comments.
Wanna give it a try? Here's a Codepen you can fork.
Top comments (4)
Thank you for your article!
It really seems unsolvable.
For my purpose, there should be an autodecrement of the indexes, so the previous block is a bit on the top of the next (like 'tiles'). So decrementing z-indexes will help.
It seems there is no way to convert string to integer via calc() or something else.
Will search for another solution.
I track all DIVs intended to be moved, and manually adjust the zIndex value via JS. Focusing a DIV decrements all other higher zIndexes by 1, and sets the focused DIV zIndex to the list size minus 1. 'mousedown' will focus the DIV, 'mousemove' implements moving ops, and 'mouseup' finishes the 'mousemove' or, lacking that, activates the appropriate element. It seems very zippy and stable.
The layout elements are already autoincremental in z-index. z-index is an escape hatch when you have no other means to fix paint priority.
I know, it was just a test to try to deliberately separate layers in your layout. It was just a cool experiment :)