Hacker News new | past | comments | ask | show | jobs | submit login
What No One Told You About Z-Index (2013) (philipwalton.com)
141 points by caffeinewriter on March 10, 2016 | hide | past | favorite | 26 comments



I think the problem is not that few people reads the spec, but having picked a name that was now declarative. Something like 'context-order' would give a better hint that the stacking is not as simple as one might think. Choosing css property names is like designing the UI of css


vertical-align is another example of the "this is not as simple as you might think" problem.


Good article. I've had that one bookmarked for a while, and it has saved me more than one headache. If you don't understand stacking context and z-index is not working as you expect, you need to go read this.


This saved my ass, and my head from exploding. I found it while dealing with an obnoxious situation where a sibling element's background was causing background-color to not work at all when positioned behind said background-color having element. And it was fascinating to read about how z-index works. One of those little-known quirks to CSS that everybody really should know.


In modern CSS we have even more ways to do this, specifically many values of "transform:" will also create a new context.


So, is Firefox breaking the spec, then? The `opacity:0.99` edit doesn't change the appearance of the boxes at all in Firefox 45 on Linux. https://ipfs.pics/ipfs/QmeuVESo8gBmsuPY7S1TaqBjfzSch8Wu3nJ2J...


Firefox 45 on Windows, the boxes are displayed as expected: http://i.imgur.com/HaKqrcG.png


Another solution of to the problem is to change the background-color property, which isn't against his rules ;)


Also allowing for breaking the rules, rules that don't exist in 'real life', was just to move the z-index property to the block defining all 3 colours. But it was breaking the rules that were there to illustrate the problem.


This is pretty rough, but I created a Chrome extension to help look up the closest parent stacking context: https://github.com/gwwar/z-context


Oh wow, this is great! Definitely pulled some hairs out regarding z-index more than once. What a great read.


There is another way to solve this using just CSS transform property!


Ha ha ha what a great and simple markup language we have


Do you have a proposal for a system that properly integrates alpha and layering without the notion of a stacking context?


If by "stacking context" you mean "one global context," then no. But if you mean stacking contextS as described by the article, then Win32, Cocoa, Swing, Qt, wxWidgets, and probably Gtk are all examples of a system where z-index doesn't involve reading an article.

I've come to the conclusion that HTML is great for content that looks like 1999. But in 2016, every time I use HTML and CSS I end up dealing with some subset of

- width/height are ignored for div/span, so I have to make a div or span, set display:inline-block to completely undo that. Nothing like '<div style="display: inline-block;"> to suggest your language needs help.

- Actually, it turns out that width is still ignored for inline-block if you have no content in the tag, but if you put any content, then it is honored. (Unless you have more content than fits, in which case it is ignored again, but at least that is somewhat sensible)

- vertical centering? That should be pretty easy, right? Hahahaha!

- to get z-indexing to work, you need an absolutely positioned outer element with relatively positioned inner elements. Win32, Cocoa, Qt, Swing, despite their flaws aren't that user-unfriendly (and by "user" that would be the developer). I get why it has to be that way, but a language where it has to be that way is no end of frustration.

- don't want to duplicate your CSS colors all over the place? Great, use CSS vars. Want your variables to be accessible to all your classes? No problem, just use the :root class, totally obvious. Oh, need support for slightly older browsers? Bummer.

- Well, you could put all your colors in a separate class. Great, I'll just have my classes inherit or mixin that color class. Actually, no, I'll be putting that class all over my HTML, which kind of violates separation of concerns, which was the whole point of CSS.

- Want borders on the cells of your table, but not "3D" borders that looked terrible even in 1996? Oh, that's fun!

It's like HTML fights me at every turn. It's high time we take the ideas that UI libraries have had for decades and make an HTML that is actually usable.

(Probably some of the details here are inaccurate, because they are so convoluted that it's hard to actually remember them)


Most of your comments are addressed by the fact that CSS2 was designed originally for documents, while the other widget systems never were and simply don't support that type of layout. Nowadays, with flexbox, CSS fully supports natural UI layouts too.

If we adopted your suggestion of using a legacy toolkit like Win32 as the basis of a new HTML/CSS and throwing out the old, it would be much worse than HTML and CSS as they exist today. Win32, Cocoa, Swing, Qt, wxWidgets, and GTK are much worse than CSS for rendering, as far as both performance and layout are concerned.

You didn't address the z-index issue either, as none of these toolkits have things like opacity, which is what causes stacking contexts. To the extent that they do, it's backed by Core Animation as in Cocoa, and that in fact does have the notion of stacking contexts, just as CSS does. The Web isn't significantly more complex in this area. (CSS 2.1 Appendix E is too complex, to be sure, but not in the area you describe.)


Yeah, I think a lot of the problems are because HTML was designed for documents. But it obviously wasn't designed well. I'm not sure how to do it better, but I know that I like using real UI toolkits, and I hate fighting with HTML.

I don't know what benchmarks say about Win32, Cocoa, or Qt rendering, but I'd be surprised if they were "much worse" performance than CSS. Layout isn't great with Win32 or Cocoa, but I love Qt's Layouts (except until you figure out how to change the default margins), and Swings seem okay from what little I've used.

Win32 has had opacity since Windows 2000, Qt has opacity since about then. Cocoa has had NSView.alphaValue since OS X 10.5.


They do have much worse performance when compared to an optimized rasterizer like WebRender (disclaimer: I work on WebRender). That's because they use legacy immediate mode APIs like GDI for painting, which are a poor match for modern GPUs. By contrast, CSS is fully declarative, which allows for much better batching, global culling, etc. Native toolkits cannot fix this without breaking backwards compatibility: their programmatic CPU drawing is fundamental to how they work. The best they can be is GPU-assisted rather than GPU-accelerated.

HTML was designed well for documents overall. It's remarkable how it's "obvious" that HTML is terrible, but every single proposed document-based replacement for it has been significantly worse. Take LaTeX, for example (sometimes brought up as a system "designed right"): you basically can't do floats at all in the system. All packages that simulate them are hacks. If the Web used a system designed like that, the volume of complaints would be deafening at this point.

I'm the first to admit that CSS has a lot of problems. But they're not the problems people always cite. The core model of downward width dependencies and upward height dependencies, with floats as a first-class citizen positioned during line breaking, is sound. Where CSS went wrong is in all the complexity like margin-collapse, border-collapse, mismatched border styles, CSS 2.1 Appendix E painting order, etc. These are the biggest flaws in the design, but nobody cites them as problems: in fact, frequently authors want more and more features that don't make sense and would make CSS worse.


I think several core HTML5 and CSS features actually come from Cocoa (via WebKit/Safari), notably Canvas, transforms and CSS animation.

The whole stacking context business basically seems to describe WebKit's rendering model (and maybe other browsers too, but did they have hardware acceleration before Safari?). I think the W3C spec was derived from the implementation, to a greater extent than the impl being driven by the spec.


Stacking contexts aren't about hardware acceleration. They're needed for things like opacity to work at all. (Think about the alpha blending functions when you have multiple objects stacked on top of one another.)


Don't forget the complete absence of any kind of error reporting. Typos, syntactic errors, semantic errors are all silently swallowed. Bugs in your layout are basically impossible to diagnose without altering your layout at random and trying to reverse engineer the underlying layout algorithms.

Not to mention that the layout model itself is painfully limited. The other day I tried to implement a card layout --- that is, a box containing a bunch of components all arranged in the same place, with the box itself being the maximum size of the components inside. As far as I can tell this is simply impossible in HTML without explicitly sizing your layout, which rather defeats the point.

I'm currently working on a web app based on Polymer. This helps a lot, as it gives me a nice modular framework with composeable components and local namespaces, which takes a lot of the edge off some of the pain of CSS. But that just casts the pain of trying to design UIs in HTML into stark relief.

...I did once find a pure Javascript layout engine; it didn't use HTML layouts at all, and positioned everything using code (and CSS transforms). They claimed to be actually faster than stock HTML.


> The other day I tried to implement a card layout

It sounds like you wanted a circular dependency: widths in CSS depend on parents' widths, not children's widths. (This is important for document layouts to work at all.)

> ...I did once find a pure Javascript layout engine; it didn't use HTML layouts at all, and positioned everything using code (and CSS transforms). They claimed to be actually faster than stock HTML.

I've seen these pure-JS layout engines, and they are invariably much slower than the browser's implementation.


> It sounds like you wanted a circular dependency: widths in CSS depend on parents' widths, not children's widths. (This is important for document layouts to work at all.)

But aren't there are HTML elements everywhere where the size is determined by their content --- trivially, the P element which is showing this text. Less trivially, I've just put an explicitly sized DIV inside an unsized inline-block DIV, and the outer one is definitely sized according to its child.

> I've seen these pure-JS layout engines, and they are invariably much slower than the browser's implementation.

I think this is it: http://famous.org/

Although I can't find their blog post on performance. And I've never used it, of course.


> But aren't there are HTML elements everywhere where the size is determined by their content

The height is. Not the actual width. Remember, widths are computed top-down, while heights are computed bottom-up.

> Less trivially, I've just put an explicitly sized DIV inside an unsized inline-block DIV, and the outer one is definitely sized according to its child.

That's because inline-block uses intrinsic width (specifically, shrink to fit width), which is computed separately from actual width in a bottom-up pass. Intrinsic width is a weird thing that is kind of a hack, and an ill-specified one to boot (although a useful one). It doesn't fundamentally change the fact that widths depend on parents' widths only.

> I think this is it: http://famous.org/

Famous is slow compared to CSS when you're using it for CSS-like designs.


I've never encountered width/height being ignored for a div, which defaults to display block btw. Unless you are talking about emails, which is a whole different ball game.


I just found this article on google after struggling with some z-index issues today, came to hacker news, and it's on the front page. The last time I read it was three years ago. What a coincidence.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: