Monday February 8, 2021 By David Quintanilla
Managing CSS Z-Index In Large Projects — Smashing Magazine

About The Creator

Steven Frieson is a entrance finish developer who loves to resolve issues for individuals, whether or not they’re web site customers or fellow builders. He’s eager about many …
More about

Wrangling z-index values is a troublesome process for a lot of builders. Right here is an easy-to-implement mini-framework based mostly on current conventions that brings readability and confidence to working with z-index.

There are a number of articles that specify z-index (here’s a good one), because it continues to journey up builders of all expertise ranges. I don’t suppose that the variety of articles is an indication that none of them do job at explaining it, however that there are a number of builders on the market and simply because one developer learn and understood the article doesn’t essentially imply that everybody on their group learn and understands it now. Whereas taking the time to higher perceive how z-index (or any piece of expertise) works will certainly set you as much as work with it higher, we are able to additionally take one other method: make it simpler to work with z-index.

We use abstractions and conventions to cover away the tough and error-prone components, which in flip makes it simpler for everybody who must do the identical process. I had the chance to try to make z-index simpler to work with for my group whereas engaged on a redesign of our firm’s web site. The system I designed allowed my group to implement your entire UI whereas by no means having to query what a sure z-index worth was used for, what quantity to make use of when including a brand new z-index declaration, or the way to repair stacking bugs that crept into the system.

Widespread Resolution

The most typical system I’ve seen for managing z-index values — apart from no system — is setting a number of general-use values, every separated by an arbitrary quantity. This resolution undoubtedly tames z-index points, however as I’ve labored on groups that use this method there nonetheless appears to be confusion about the way to use it correctly. Right here is an instance from the Bootstrap documentation.

$zindex-dropdown:       1000;
$zindex-sticky:         1020;
$zindex-fixed:          1030;
$zindex-modal-backdrop: 1040;
$zindex-modal:          1050;
$zindex-popover:        1060;
$zindex-tooltip:        1070;

Bootstrap defines z-index values in Sass variables like $zindex-dropdown, $zindex-sticky, and $zindex-fixed. These names appear fairly straight ahead, however when a developer goes to decide on a price for a function they’re engaged on, there may very well be confusion as to which worth is most applicable for his or her use. They find yourself asking, “Is what I’m implementing a ‘dropdown’ or a ‘popover’?” which might simply be debated and will not have a transparent reply.

A second subject I see with this resolution is that the precise values for the variables may appear complicated or result in insecurity. This resolution leaves area in between every worth to offer builders area so as to add their very own values in between if vital. Bootstrap defines seven values separated by increments of 10, beginning at 1000 and ending at 1070.

Many questions might come to thoughts when studying this:

“Why begin at 1000?

“Is there something lower than 1000?”

“The place is 1010? Is it a bug? Is one thing else utilizing it?”

“Why was 10 chosen? What if I would like greater than 9 values to go in between?”

Although I’ve by no means really wanted these “what if” questions answered, they will add insecurity and confusion to a system that already appears magical and misunderstood. Can we take away all of those issues, permitting the developer to simply and precisely select the z-index worth they want?

A New Resolution

Since engaged on a redesign gave my group a contemporary begin, this was one frequent subject we needed to see if we might keep away from. To align with our normal coding requirements, my targets for managing z-index was to keep away from magic numbers and to make it simpler for each group member to confidently contribute. The second aim of constructing it simpler for others is imprecise, so I centered on attempting to resolve these frequent points:

  • Folks typically select arbitrarily giant z-index values;
  • z-index bug fixes typically end in a brand new z-index bug;
  • The connection between z-index values is troublesome to hint.

Let’s have a look at options for every of those points that I used to be in a position to apply, leaning on conventions and utilizing current applied sciences.

Giving Z-Index Values Semantics

One motive individuals typically select arbitrarily giant z-index values is as a result of they don’t know the z-index worth of the merchandise above which they’re attempting to position a brand new merchandise. As soon as they discover an arbitrarily excessive worth that works, they depart it as an alternative of discovering an optimum worth. In a while, when somebody finds this worth they don’t know why it’s what it’s, and even the unique creator might have forgotten.

z-index: 9999;

The answer for fixing “magic numbers” like that is by utilizing a named fixed as an alternative. Whereas naming the worth alone doesn’t give us way more worth than the category identify does, after we put our z-index constants collectively, their relationship begins to change into specific.

To take away the magic numbers, I first began defining all of our z-index values in a JavaScript file. I used a JavaScript file since our utility was utilizing a CSS-in-JS resolution, although this and the concepts on this article could be applied with styling preprocessors like Sass variables in addition to in CSS utilizing customized properties.

export const backdrop = 0;
export const openButton = 1;
export const dropdown = 2;

With z-index constants, the CSS worth has little extra which means, and the precise worth is obscured away.

  z-index: ${backdrop};

This additionally makes the unique worth straightforward to search out, revealing the associated constants, however there’s a additional enchancment that may be made. We all know by how z-index works that these values are associated to one another, so we are able to change our constants to make that extra obvious.

export const backdrop = 0;
export const openButton = backdrop + 1;
export const dropdown = openButton + 1;

Utilizing easy arithmetic, we are able to use the earlier constants to make the following fixed. Taking this concept one step additional to additional eradicate ambiguity, I added some utility constants to make these definitions learn extra like a sentence.

const base = 0;
const above = 1;

export const backdrop = base;
export const openButton = above + backdrop;
export const dropdown = above + openButton;

Now when somebody sees a line like z-index: ${dropdown}; they will look discover the dropdown’s definition and skim, “The dropdown is above the open button.”

This makes future upkeep of the constants simpler. Each time you’ve a brand new worth so as to add, you could be assured that you’re including it to the correct place.

export const backdrop = base;
export const openButton = above + backdrop;
export const dropdown = above + openButton;
export const closeButton = above + dropdown; // new

Deleting values is simple too, however you must keep in mind to replace every other values which might be depending on it. Utilizing JavaScript, the linter highlighted this for me.

Stacking bug tickets typically present up that say one thing like, “the dropdown is overlapping with the button when it needs to be beneath.” When coming throughout these, the repair is so simple as swapping the connection pointers within the definitions.

export const backdrop = base;
export const dropdown = above + backdrop;
export const openButton = above + dropdown;
export const closeButton = above + dropdown; // ???

Now that we’ve swapped the z-index order, we discover one other potential bug earlier than we even examine the browser. The shut button may now battle with the open button. Now you can have the required conversations to resolve bugs earlier than anybody sees an issue in manufacturing.

One further piece I discovered to be useful in uncommon conditions was a utility for putting objects under others. To keep away from mixing above and under, I made the rule that under ought to solely be used for destructive values.

const base = 0;
const above = 1;
const under = -1;

export const backdrop = under + dropdown;
export const dropdown = under + button;
export const button = base;

In this system, every z-index value is only as high as it needs to be, and since it’s dynamically chosen, you aren’t concerned with what the value actually is.

You may also delete and add values understanding with confidence the way it will have an effect on the opposite stacked components.

As soon as our utility ended up with a dozen or so z-index constants, although it began to change into a little bit bit complicated having a protracted flat checklist.

Organizing By Stacking Context

When fascinated by stacking context and the way the values of every stacking context are unbiased of others, it appeared like different front-end options for efficient scoping. I drew similarities to different JavaScript modules, parts, atomic design, and BEM. They’re all attempting to resolve comparable issues of how we are able to independently scope issues, protecting them from affecting different areas.

Taking inspiration from BEM, I made a naming conference for our constants to higher manage the values and produce extra order to the flat checklist of constants. The format I ended up utilizing had a template like this: z<Context><Factor>.

The z portion is a prefix denoting the truth that the worth is supposed for use in z-index declarations, contemplating we had different constants outlined in our JavaScript recordsdata like colour variables.

The<Context> portion is changed with the identify stacking context the fixed belongs to. That is much like the “block” in BEM and in apply nearly all the time shares the identical identify because the element being styled. The primary exception is the foundation HTML stacking context that’s used for web page area stacking.

The ultimate portion of the format, <Factor> is for the identify of the precise merchandise to be positioned within the stacking context and is most much like “component” in BEM.

Right here is a full instance of what this naming conference might appear like when added to what we’ve talked about beforehand. For an interactive model, you possibly can mess around with the identical instance in a CodePen:

See the Pen [Managing CSS Z-Index in Large Projects Demo](https://codepen.io/smashingmag/pen/xxEvepz) by Steven Frieson.

See the Pen Managing CSS Z-Index in Large Projects Demo by Steven Frieson.

For different language variations, check out this repository.

// Utils
const base = 0;
const above = 1; // use this for all values above the bottom
const under = -1; // and this for all values under the bottom

// Web page Structure
export const zLayoutNavigation = above + base;
export const zLayoutFooter = above + base;
export const zLayoutModal = above + zLayoutNavigation;
export const zLayoutPopUpAd = above + zLayoutModal;

// NavMenu
export const zNavMenuBackdrop = under + base;
export const zNavMenuPopover = above + base;
export const zNavMenuToggle = above + zNavMenuPopover;

Now that our constants are organized by their stacking context, we are able to rapidly see which values are associated and the place a brand new worth or repair ought to go.

Taking It Additional

That’s basically the specification of how this could work. Contemplating this resolution was solely designed with one utility in thoughts, there are some additional steps that may very well be taken to make it extra mature and help extra use instances. A few of these concepts are extra particular to the language it’s being applied in however most concepts carry over.

One space that might presumably be improved round what’s being shipped to the browser. Once I applied this, the framework we had been utilizing didn’t give us a lot management over the construct instruments, so the JavaScript file of all of the definitions was bundled with the appliance. This didn’t have a measurable efficiency impression on our utility, however you might have seen that all the values may very well be computed at compile time. An implementation utilizing Sass would find yourself not transport any of the Sass variables to the shopper, however as an alternative, insert the derived z-index worth within the CSS. For JS and CSS options, construct instruments like Webpack and PostCSS, respectively, might assist do the identical.

The way in which the answer advanced as I labored on it, the z-index constants ended up multi functional file. This ended up being an effective way to see all the z-index values throughout the appliance without delay, making it simpler to rapidly look for any doable stacking conflicts. They had been additionally filed away with different styling constants like colours and typography, so it made sense to initially have all of them outlined collectively. Because the file grew although, it began to be internally organized by stacking context as defined above. Because the stacking contexts typically mapped to a element, it began feeling like every set of constants may very well be collocated with their element. This is able to convey all the conventional advantages of collocation, being nearer to the recordsdata they’re utilized in, inflicting much less friction when needing so as to add, edit, and take away constants. We by no means refactored it, however that looks like a viable choice to discover.

One further piece has to do with ergonomics and developer expertise. The constants are all exported as a flat checklist in the mean time. The naming conference took inspiration from BEM, however Sass and JavaScript permit us to make use of different methods to manage our knowledge. Sass maps or JavaScript Objects or Maps might have been used to arrange the values hierarchically. If we had all of the values in a z object, it might have led to shorter import statements. We might have gone additional to have an object per stacking context as effectively resulting in a utilization fashion extra like z.format.navigation. Completely different instruments like TypeScript might guard towards making typos right here, although this is likely to be extra effort than it’s value.

Our Outcomes

The system as spelled out was efficiently applied and deployed to our manufacturing functions. Checking again in on the aims, we undoubtedly removed the magic numbers. So far as developer ease and confidence goes, my group was in a position to simply add new z-index values and repair pre- and post-launch bugs with out concern that the modifications would introduce new bugs. On a number of events, we mounted bugs earlier than they had been filed.

We additionally had been in a position to keep away from the difficulty of coming throughout a random z-index: 9999;. Although the appliance had sticky headers, floating motion buttons, dropdowns, modals, pop up adverts, and extra within the stacking context, the best worth we had was 5. Even then, nobody knew it for the reason that values had been all abstracted away from us in variables.

Solving developer experience issues resulted in a z-index mini-framework, helping people make the correct decision with less effort and move more quickly.

One thing else we seen was that typically we had been assigning a z-index after we didn’t essentially want one. Since stacking contexts could be created by a number of totally different properties, declarations like place: sticky; can act in the same method as setting z-index: 1;. In these instances, we continued so as to add a continuing and declaration anyway. Preserving them allowed for higher consistency within the system as an alternative of permitting there to be particular instances, which might degrade confidence about whether or not every little thing was working appropriately or not. Preserving the fixed checklist full aided in understanding the system and set us up higher for rearranging the values when vital.

What It Doesn’t Remedy

Like all framework, there are components that it doesn’t not do job at fixing for you. Naming issues remains to be arduous, and this framework barely exacerbates the issue by requiring that you just identify all your z-index values. Even nonetheless, we discovered that the gained readability overcame the chore of getting to call all of them.

This technique additionally doesn’t essentially assist you determine which stacking context a bug is in. Coming throughout a z-index bug the place you don’t know the place the brand new stacking context is created or the place the z-index worth is about shouldn’t be solved by this framework, however upon getting discovered the difficulty, the trail to creating the right repair is evident.

Utilizing It In Your App

The concepts shared right here needs to be actionable in most functions relying in your styling resolution and browser help. Migrating to make use of this method shouldn’t be very dangerous since stacking contexts are already scoped individually; you possibly can migrate one context because it already exists at a time. Altering to make use of these conventions forces you to explain extra clearly what you have already got in your app, shining a lightweight on what may presently look like a darkish, scary nook.

In case your z-index values are in a state the place you might be not sure about most or all of them, then the finest option to convert to this method will in all probability be to start out by creating a continuing for every worth in a single checklist in a single file. Because the stacking contexts change into extra clear, you can begin grouping them and renaming them (if vital) to adapt to the naming conference.

My group was not working with any exterior CSS libraries or frameworks that included z-index values, however that might presumably add some issue to adopting this method. Hopefully, the utilities are configurable sufficient to cope with most makes use of and to even incorporate the third-party values into the system.

Lastly, all the examples right here have been written as a single file of z-index values, however you would collocate these values with the element to make an excellent stronger connection between the 2. Utilizing a file naming conference will make it simpler to search out all the values all through the appliance.

Attempt It Out Your self

In case you are having bother wrangling z-index values in your website and find yourself attempting out these ideas, I might love to listen to about your expertise. This mini-framework was developed over only a few months and has solely been utilized in one manufacturing codebase, so there are actually unexplored use instances and opinions that may very well be added or tweaked.

Smashing Editorial
(vf, yk, il)

Source link