Hacker News new | past | comments | ask | show | jobs | submit login
The top layer: a solution to z-index:10000 (chrome.com)
118 points by feross on Aug 25, 2022 | hide | past | favorite | 100 comments



"In 2022 we brought you z-index:10000 and a lot of web UI developers used this to create masterful new models of interactivity within the browser.

But we've heard your feedback, and today, in 2023, we bring you the "topper-layer", accessed using z-index:12000.

You might be wondering if we're going to stop here. The answer of course, is no. We have a roll-out plan for the next 8 years which will culminate in z-index:100000.

Some of you might be asking if our plans for the super-topper-most-mostest-layer are really just reducing this all back to "normal" z-index stacking in the document flow. We'll leave that as a discussion for the forums, while we get back to work."


You joke, but z-index really is one of the worst decisions in the CSS spec.

So. Many. Footguns.

There really is almost no case in which a combination of DOM hierarchy and positioning isn't sufficient.


At the risk of reading too much into a joke, what about the top layer / stack suggests this would later beg for a "topper layer"?


z-index YYYYMMDD


Actually not that bad. If everyone assumed today's date to be the max value, one could always add something new on top without having to guess whatever value someone else has used, and risk exhausting the range because someone uses the max value.


It's not half bad, the problem is that you'd have to throw an error when attempting to use higher values (or in CSS's case just not render it or something), because currently z-index will happily accept >max values and just consider them max.


But what's today for me is yesterday in New Zealand and if I'm on the West Coast of the US or Hawaii then that can go on for a 'long time'? If I then go +1 then that's just going to end up in the same rat race / breakages.


If CSS would up it to be a 64 bit integer then timestamp could fix all that. That's a common approach to DNS serials, there they are 32 bit but there is logic about handling rollovers that wouldn't apply to layers. Or if you want to keep it human readable UTC.


I was thinking: does this solve a problem, or does it introduce another problem?


Popups already exist on the web. Typically they are implemented by injecting an element as the last child of the body element, and then use absolute positioning on it. Last inserted element wins. This proposal just allows the same effect with simpler code and no need for DOM injection.


Many comments assume this is just a way to get z-indexes "above everything else", leading to lots of clever jokes.

This is not the point though. If I understand correctly, the "top layer" allows positioning elements on the z-axis independent of the parent stacking context. So kind of like absolute positioning on the z-axis.

z-index: 10000 is not something you actually need, it is typically the result of someone desperately trying to stack an element over another in a different stacking context. Stacking context are not always well understood, and most developers would intuitively expect an element with z-index 8 to cover an element with z-index 7. But this is only the case inside the same stacking context, not if they are in different subtrees.

The use cases for breaking out of the stacking context is where something like "portals" in React is used: https://reactjs.org/docs/portals.html

> A typical use case for portals is when a parent component has an overflow: hidden or z-index style, but you need the child to visually “break out” of its container. For example, dialogs, hovercards, and tooltips.

But portals are a complex hack, where "top layer" allows you to keep the logical document structure.


Sure but how do you put items above the top layer? Eg say I want a ‘x’ graphic on top of my modal? Or behind it?

If there’s value here I can’t see it from their blog post and demos.


The elements in the "top layer" are stacked in the order they are "promoted" - for dialog elements this is when showModal() is called. So the element on which showModal() was most recently called is on top. If you want another dialog on top, call showModal on that.

https://developer.mozilla.org/en-US/docs/Web/API/HTMLDialogE...


Thanks, though that wasn't quite my question - do you still stack elements within a top layer using z-index?


Elements promoted to the top layer stack according to the order they are promoted. Inside a promoted element, child elements are stacked according to the regular layout rules, i.e. same as if the element wasn't promoted.

Think of the "top layer" as similar to inserting an element as the last child of the document body. This is how modals and overlays are usually implemented - by inserting the element last (and position it absolutely) it will automatically stack higher than anything else in the document. At least until something else is inserted last.

Z-index is actually not that useful for stacking elements (whether in top layer or not) since it only works inside the scope of a stacking context. Element order is a better way to control stacking.


I always wanted a relative z-index.

Example:

  <year dropdown> over <date picker> over <modal form> over <desktop style app>
A complex “desktop style” UI, that shows a modal form over it, and the modal form contains a custom date input component. Click the date input and a custom date entry pop up component is drawn above the modal form to pick the date. On the custom date entry pop up is a year picker, which you click and a custom year dropdown is shown. This was an actual example from my past (I’m not saying it couldn’t have been done better, but this was before there were many better ways to do it). Using absolute z-index required complex coordination between components.

The top-layer at least solves the problem of covering the viewport and providing a backdrop (difficult to do reliably, especially 10 years ago). Although I can think of other issues one still needs to solve: disabling inputs and events behind “modal” pop up, disabling iPad background scrolling, must be accessibility, can need multiple layers of popups e.g. loading spinner, problem of tab key handling, et cetera.


I believe CSS has an option that you set to make all z-indexes relative to the element. Making the page hierarchical.

It's not exactly what you asked for, but it does void the need to coordinate between too many components.


Yes, set position:relative on a parent element, then set position:absolute with a z-index on the child element. The z-index will be relative to the parent, not to the document.


One of the wonders of CSS (well, browsers) is that you can devote a decade to learning all the various details, and still not know something so fundamental. Thank you. I don’t want to believe I could miss that, but I have been humbled enough times to be doubtful about my beliefs.


"Stacking context" creation is one of those concepts that many coders skip while learning as "intuitive enough not to dive deeper", and then stare in disbelief on list of properties that affects this, as pointed out in https://news.ycombinator.com/item?id=32600047 .

Who would have thought that `will-change: mask-image` would have similar effect similar to `position: relative`?


Somebody posted the documentation of stack isolation in another thread.

If you want exactly that, and only that, my conclusion is that the best way is to use `isolation: isolate`.


But if "A over C and B over C", is A over B?


This is a topological sort without a unique solution.

https://en.wikipedia.org/wiki/Topological_sorting#Uniqueness


I imagine it would just pick an order unless you also wrote a rule for A relative to B


Yes, that's the most reasonable thing to do, but an absolute index has much less room for that. Though you then need to allow decimals, so things can be positioned between things that are already adjacent.

The other issue it doesn't have is if you specify "A over B and B over A".


Isn't that the same as giving two elements the same z-index?


I once wrote such a system in JS. For every element, up could specify which elements it needed to cover (complete with a priority rule for cycles). It worked perfectly, but it was slow, because the number of constraints rises quickly if you rely on it too much (and it needs to add all kinds of intermediate constraints to maintain the default visual hierarchy).


Stacking is best controlled by order and nesting in the document structure. If the year dropdown is nested inside the data picker which is nested inside the modal form etc., then you get the desired stacking automatically, without having to set z-index on any of them.


This feels like the same kind of kludge as "!important" and will probably be similarly abused.


I am beginning to think that perhaps the world's largest advertising corporation should not be trusted with developing the leading web browser.


Beginning?


Some people are slow on the uptake. Better late than never, though.


Neat. Yes please. The Web becomes usable again just by blocking the top layer.


Indeed, this is great. All newsletter popups, cookie popups, "are you sure you want to leave" popups, give us feedback popups... They will all go on the top layer so your adblocker could hide it all at once.


For that reason two dialogs will be opened in the same place. One on the top layer, and one on the layer below it.


That is the reason why the top layer will not be chosen


Except if that happened, they just wouldn't use it.


They don't care about the 1% of users who will figure this out.


Wow, that would be great actually. Right now heuristics to block “please sign up for the newsletter” dialogs is difficult to do. But hopefully in the future we can just selectively allow access to top layer for certain domains.


Wait till we need to place elements higher than on the top layer. This will surely be abused by plugins.


1. This is straight up <https://devblogs.microsoft.com/oldnewthing/20110310-00/?p=11...> and <https://devblogs.microsoft.com/oldnewthing/20050607-00/?p=35...>. Since the Chrome team probably have at least one team member who reads that blog, they'll probably do the same thing and make this the "the buck stops here" rule for anything that doesn't have special privileges, like the browser itself or extensions.

2. There should be a webext-exclusive API for placing items above the top layer.


They could have defined `z-index: omega` to be on top of all other natural number z-indices. And they we can have `z-index: omega+1`, `z-index: omega+2`, ..., `z-index: omega*2`, `z-index: omega*2+1`, ..., `z-index: omega*3`, ..., `z-index: omega*omega`, ..., and so on and so forth.

And then maybe next year they will propose a new syntax for setting z-index to epsilon zero.


I suggest using this archive: http://bytepointer.com/resources/old_new_thing/20050607_141_... because devblogs.microsoft.com has repeatedly deleted all the comments and broken links and will do so again.


The problem with those blog posts is that they apply just as equally well to the existing "topmost" flag as they do to the hypothetical "super topmost" flags. The answer to "what if two programs have the topmost flag set?" wasn't "you violate the laws of metaphysics", it was "well then they order relative to each other the usual way". The same thing would presumably apply for even higher-level topmost flags; it's just a hierarchical ordering mechanism, which is in no way logically inconsistent as Raymond makes them appear.

Moreover, Windows literally added support for the "even more topmost" feature later - they're called "bands", and supported by CreateWindowInBand(), except IIRC Microsoft later restricted support for that function to its own signed binaries, presumably to prevent vendors from abusing it. Needless to say, the addition of that function didn't violate the accepted rules of metaphysics.


It sems you are agreeing with Raymond, but make it sound like you don’t?


I'm pretty sure I'm disagreeing? He's claiming having a "super-topmost" feature would somehow defy logic, whereas I'm saying it's perfectly fine—you can (and later Microsoft literally did) implement a "super-topmost" flag perfectly fine, and it would literally mean "this is on top of all topmost windows", just as the customer had requested. Of course logically it couldn't always be on top of other super-topmost windows, but that's not what the customer asked for either.


> just as the customer had requested.

but that's what those blogposts were about! The customer wanted their window to be on top of every other window - even if the other window is asking to be on top of every other window!

If you have a secret "super-duper-topmost" window flag, then you're not really satisfying the customer's request. but if you do indeed have this super-duper-topmost window flag, what happens if two windows tried to ask for the same? How do you decide which goes ultimately on top?


He’s arguing that there is no point to having another level of topmost if all applications currently using topmost are all going to use that new super topmost level anyway. If they’re currently using topmost, you can practically guarantee that will be the case.

If what you say is true, the only way they prevented that is by not making the new super topmost accessible to users, which isn’t really fulfilling the users request.


From the oldnewthing blog:

> And it’ll try something nastier, like enumerating all the processes on the system, attaching to each one with debug privilege, and suspending all the threads.

This is like playing corewars with Windows desktop software :)

> “Note to self: Do not get into a walls-and-ladders contest with Raymond.”

Don't play with the person who knows all the lower levels :)


Fun, but entirely missing the point. You can't force a window to cover a window from an independent program, since you have no authority over that other program. But obviously you can design a popup to cover other windows in the same program. The scope of this "top layer" is the web page - it does not enable you to force-close other tabs containing your competitors web site.

Popups have existed on the web for ages. This just proves a more convenient syntax without having to inject dom elements at the end of the body element (which is how popups are traditionally done).


I’d run other software in a maximized vm window and hide it entirely when required. Try escape that. More abstractly, when parties cannot negotiate, you should set up a supervisor for them. On linux/x11 it would be a custom wm script which knows the priority of window classes and stacks them accordingly, regardless of their requests. Windows wm delegates geometry to apps and by that creates the whole issue.

There should be a webext-exclusive API for placing items above the top layer.

Together with a priority in extension settings.


Still even Microsoft plays such army race game.. https://github.com/tablacus/TablacusExplorer/issues/140#issu...


I've been toying with a CRT theme with scanline effects in CSS. Since this is an effect that would apply to the whole viewport it would need to be above everything else... I'm currently using z-index.

Well, since I control the whole content and know there's no dialog or anything else like that on my blog I could put it in toplevel, but what if I had? What if multiple stacked dialogs were to be opened (Win 3.1 style)? Is it possible to order things inside this toplevel? Maybe using z-index?

In any case, I'm just discovering this but it seems to be more about having a container with specific positioning than just replacing z-index (which is merely a consequence of that container loving outside of the <html> object). Also makes me want to have a bottom-level as well (e.g implementing cool effects on the background, think X11 root window).


top-layer-index: 1 will be the default, and on top of that will be top-layer-index: 2


.futureproofHeader {

z-index: 999 !important; top-layer: 999 !important; -webKit-actually-paint-me-last: true !inportant;


.futureproofHeaderMax { z-index: 10000 !important; top-layer: 10000 !important; -webKit-actually-paint-me-last: true !important; -webkit-no-backsies: true !important;}


So last created layer wins the display? or can you indicate priority via css?


Just like the ordinal number in the study of infinite sets


I thought we went over this almost two decades ago. http://bytepointer.com/resources/old_new_thing/20050607_141_...


The "top layer" as a solution to the z-index: 10000 problem, sounds like "this goes to 11" as the solution to having a bigger guitar amp output...


I'm a dancer. "Take it from the top" means to start a run through of the current piece from the beginning.

Except … we were practicing a section of a piece. And then we started digging into the details on a very specific portion of footwork in the middle of that section. And our choreographer, instead of saying "start from the section", said, "start from the top". And humans being what they are, we all understood, somehow, and the right thing was done without complaint.

But then came the need to start from the beginning, at which point she now had to differentiate from what she had been calling (erroneously) "top", and uttered "start from the top top". Some amount of playful joshing followed … and then the term stuck.


I'm not saying they haven't earned this kind of treatment necessarily, but it is a little exhausting how much negativity and assumption of bad faith there is here in the commentary on more or less everything Google does. This even is just an explainer of a concept that's implemented by all the vendors, and as far as I know isn't something Google has railroaded.


The only reason they talk about dialog and "how great it is" is because they want to kill a alert/prompt/confirm. https://dev.to/richharris/stay-alert-d

Even if they were talking about removing dialog entirely https://twitter.com/voxpelli/status/1423207772498415616 (and none of the issues with dialog have been resolved since)

So this top layer bullshit is just a hack to make another hack work. It's not a usable long-term solution, and expect more hacks to deal with this hack in the future.


Google is turning into Microsoft the 90s and 2010s.

They're not only monopolistic, they abuse that monopoly power often just because they can, in a careless way that only the obscenely powerful can do.

That has soured people's opinion of them. Long gone are the days of "Do no evil" in their mission statement. Now evil is just a casual stepping stone on the path of squeezing out every eyeball-second from the products.. err.. I mean "customers".


I mean have you read the Twitter thread defending the web components APIs to a very polite Rich Harris pointing out some rather strange design choices? They’re not nice. They’re an ad company that made good products in the early 2000s.


The blog post keeps mentioning that you "promote" things to the top layer... but how do you do that? I see absolutely nothing in the HTML, CSS or JS of the examples in the post that references anything new.

Is this just a new way the browser displays the <dialog> element exclusively? I'm pretty confused.


Exact same question. I'm glad I'm not alone.


This post is sort of an introduction to a topic that has already existed (in a low-key sort of way) for some time. I'll grant that the article is a little unclear when it comes to getting to the point, but maybe this'll help:

The CSS2.1 spec [1] describes how stacking contexts work when painting the browser window. Traditionally, our mechanism for interacting with an element's stacking context has been more or less exclusively to set its z-index.

The Fullscreen API spec [2] introduces a new stacking context called the "top layer", which has some unique properties. Most notably, things rendered in the "top layer" are always rendered on top of everything else, regardless of z-index. There is exactly one top layer per document.

Parts of this spec also describe operations which can add and remove elements from the top layer. For example, the "fullscreen an element" operation adds it to the document's top layer. [3] This operation is invoked as part of the steps taken when a developer calls `requestFullscreen()` on a DOM element [4].

Now, the `<dialog>` element as specified in the latest HTML spec [5] also interacts with the page's top layer. When you call `.showModal()` on a dialog element, it gets added to the document's top layer. Note that although this is a completely different API, the commonality here is that we're also interacting with the top layer by adding and removing elements from it.

The article also references some ongoing discussion [6] on a possible "popup" API which would also interact with the top layer, and which would be used for implementing various controls such as datepickers and dropdown lists.

Hope that helps!

1: https://www.w3.org/TR/CSS2/zindex.html

2: https://fullscreen.spec.whatwg.org/

3: https://fullscreen.spec.whatwg.org/#fullscreen-an-element

4: https://developer.mozilla.org/en-US/docs/Web/API/Element/req...

5: https://html.spec.whatwg.org/multipage/interactive-elements....

6: https://open-ui.org/components/popup.research.explainer/


Same. Even reached out to the post author and was hoping they might amend it: https://mobile.twitter.com/benfrain/status/15618030119151902...

Sounds like an attribute does the actual promoting.


I'm still trying to grasp the real use of this.. IMO Looks like a bad solution for a problem that wasn't really that big


It's a big problem. In fact I wish a better layer stack API instead of having a special top-layer for dialog.

Problematic UI use cases:

- z-index is a hint, the real layering depends on the positioning of the parent element. The usual trick is to insert an element at the bottom of the DOM, and then use z-index.

- If you create a Dropdown or a popup UI (eg. a date picker), the accessibility of focus handling is hard. Your component needs to appear in a top-layer but by inserting it in a div at the bottom, you loose the tab order that goes from the trigger button to the popup. (there is an aria attribute to associate the control, but at least VoiceOver ignores it, and the browser doesn't respect the tab-order).

- The dialog element not only solves the positioning on top, it also solves the focus-trap that is needed for a keyboard navigable (accesible) UI.

- It's possible to use dialog for a non-modal popup. However, the specs doesn't say much about layering. (in fact a quick dialog test in Chrome/Firefox/Safari... they don't follow a predictable layer positioning).

The thing is, if you need to create a dialog, tooltip, dropdown, or popup today... you need a lot of hacks.


Yes, this doesn't seem like a proper solution.

I can change my modals to top layer, okay. What happens to my dropdowns that can be used both inside the modals and under the modals then?


> The thing is, if you need to create a dialog, tooltip, dropdown, or popup today... you need a lot of hacks.

This top layer isn't a solution either. It's still a hack


I agree. I was answering to the parent comment of: “I'm still trying to grasp the real use of this”.

This top-layer feature only solves the element at the bottom + positioning + z-index hack.

I wish to have a sort of programmatic stack API. But, the constraint of using HTML makes these things messy. The stack is implicit by nesting dialogs, and dialogs can be modeles, but is not a proper API for pop ups. (the article points to a pop up proposal, but my expectations are low)


Small businesses build their websites by setting up on a platform like Shopify or Squarespace. They use a template and fill in the content. They add functionality to the site, like an email opt-in, a "free shipping if you order over $50" bar at the top of the page, a "contact us" button floating at the bottom, a bunch of social media icons floating on the side... via plug-ins/apps/scripts. They don't ever touch code. All those plug-ins/apps/scripts that provide this functionality to non-technical website owners as a service have no idea what the webpage DOM will look like, how it's coded, what other scripts you're loading on the page. They end up fighting to be on top with z-indexes, and that's how you end up with the website's main navigation being on top of instead of behind a modal dialog like a popup contact form, when the site owner wants it to be behind. This "top layer" means the stuff that isn't part of the page and should always be above the page can really be on top.


Sounds like all that stuff which is now fighting over z-index, "implemented" by people with no clue at all, will be fighting over the top layer soon, when the people with no clue at all start throwing it together...


The problem is not these things fighting with each other, but fighting with the webpage design. It's fine if a contact form pops up over an email opt-in form, if the contact form is the more recent thing someone tried to open. It's not fine if the contact form appears behind the website's navigation menu because the website template designer gave the menu too high of a z-index value. Separating these third party overlays from the webpage is the improvement this offers.


Obviously a clever act of resistance within the Chrome team, providing a fantastic crap-blocking tool to which crap will be registered willingly.

"outside of the document flow": that can't be clearer. It's almost imprudent.


How is this triggered? showModal() on an element? Or is it using this: https://developer.mozilla.org/en-US/docs/Web/API/Element/req...

Oh it's a feature of the <dialog> element I guess


Yey! Now I can dismiss more notifications and adverts to subscribe to newsletters on every site I visit. Race to z-index:10001 has begun.


”z-index: 10000” is a solution employed by people who have no idea what a stacking context is, and, consequently, do not know that one can define their own ”top layer” and have z-indexes inside that work completely separate from the rest of the document.

Just set ”position: relative” on an element and it will start a new stacking context, and stack it within the underlying context. It’s like having a card in a card stack be another stack of cards.


I don't blame them when the rules for what creates a stacking context look like this: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Positio...


2 minutes after release- where’s the top-top layer option.


This amp goes to 11 (https://youtu.be/KOO5S4vxi0o)


But why? And is this a new thing? Or an existing thing gaining visibility in devtools?


Someone at Google had to justify its 6 figure salary. Plus s/he probably made a point about how this will ensure modal ads coming on top of everything else.


You joke but I've read this is literally how Google's internal politics work.


It's any $BigCo. The work isn't for the community, it's to impress your manager, with fanfare, and get your name on something and that raise/promotion.

A truly FOSS Chromium team, or a revitalized Firefox team would be better for managing rendering engines and specs. Maybe just taking the big guys out of the specs would be a good start.


LOL, but I wasn't joking.


yeah.. why?


Vue 3’s <Teleport> component pretty much solves this, as any component can inject a part of its template to anywhere else in the DOM (edit: even outside of the app’s root element). Very nice feature.


>Vue 3’s <Teleport> component pretty much solves this,

It's so funny to me how transparently contrarian the entire Vue community is.

No no, they're totally not React Portals which have existed for 5 years... they're Vue Teleports!


I’ve never used React. Was just posting a (potentially) helpful tip. What were you saying again about being contrarian?


Unfortunately, you can't practically use this today because it has only very recently been added to Safari (March 2022). I guess something to look forward to in two to three years.


why only one top layer? why not just "layers"? Unpoly has solved this quite elegantly: https://unpoly.com/up.layer


Anyone ranting about this feature, has ever implemented an aria compliant website?


z-index: 10000? Amateurs. Hubspot web chat button leaves it in the dust with its z-index: 2147483647. Try to top that.


Obligatory nitpick: max z-index is obviously not 10_000 but 2_147_483_647. (2^31-1) [1][2]

[1] http://web.archive.org/web/20160604042509/http://www.puidoka... [2] https://codepen.io/myf/pen/QWmRZEJ?editors=0011 (2147483647)


This is a joke, right?


Z-index is a relic of the imperative styles of the past. Why are we building on top of it, further entrenching us into imperative territory? We should be replacing z-index with something more compatible with modern functional frameworks like React




Join us for AI Startup School this June 16-17 in San Francisco!

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

Search: