Using Sass to Manage Layers with z-index

On a recent project, I started to feel a bit overwhelmed with managing numerous layers with z-index. The thing about z-index is that all of the layers have to be in order, so I end up with multiple z-index declarations in multiple files all over the place. It’s also hard to keep track of the numbers; bump one up and you have to go bump all the others up as well. It gets a bit tedious, especially when you have numerous layers. This can all be fixed with a little bit of Sass, and here’s how to do it!

$layers: (
    'navigation', // z-index: 0
    'logo', // z-index: 2
    'login-popup', // z-index: 3
    'overlay', // z-index: 4

@function layer-index($layer) {
    // This just returns the named layer's 
    // location in the list, which becomes it's z-index.
    @return index($layers, $layer); 

@mixin z-index($layer, $position:relative) {
    position: $position; // relative by default
     // Set the z-index to the named layer's index in the list.
    z-index: layer-index($layer);

.navigation {
    // Use this to name your layers and position them.
    @include z-index(navigation, absolute); 

.logo {
    @include z-index(logo); // Relative by default

.login-popup {
    @include z-index(login-popup, absolute); 

.overlay {
    @include z-index(overlay, absolute);

Just use @include z-index(your-name-goes-here, absolute); to name your layers, and specify its position. Then, add the name to the list of layers in $layers at specific positions in the list (top most layers go towards the bottom). The order of the $layers list is what does the trick. If we wanted the logo to show over the overlay, for instance, we would just move 'logo', right below 'overlay', to get the effect.

All you have to do now is make sure all your elements with z-index use the @include z-index() mixin to name the layer and add it to a position in the $layers list.

An Example

Here we have two menus on a mobile layout. On a mobile layout they are going to overlap a bit, especially if they use both menus at the same time. Right now, the secondary navigation is not accessible; we need to bump that layer up.

Two menus where the second one is inaccessible because of z-index
What we’re starting off with–an inaccessible secondary navigation.


Let me show you what we need to do get those two layers squared away with ease:

Naming the secondary navigation layer.
Name the tools navigation menu.
Naming the Main Navigation
Name the main navigation.
Adding the Layers
Add the named layers to the list.
Switching the layers using Livereload
Here’s some live reload action on how easy it is to change our layers now.

Now your days of complicated layer management is over. No numbers to keep track of–just layers you can order easily!


5 thoughts on “Using Sass to Manage Layers with z-index

  1. Very cool! Keeping track of the various z-indexes can be a pain, and sometimes a time Hoover! This keeps it mighty tight, and refining or adding to the layers is easy and idiot proof (not a ref to me!).

    Definitely a must add to my “Felix bag of tricks” !!

    Thank you for sharing.

  2. I kinda have a different opinion about this one.

    First, I’d rather decouple the z-index ordering from positioning.

    Second, I’d just have a sass-map with manual numbering to sort the z-index. Anyway, the day you have to manage more than 10+ z-indices on a single visual page is that day you really start thinking about your markup and styles.

    Something in the lines of;

    $z-index: (
    default : 1,
    popup: 51,
    modal : 999

    and use it with “z-index: z-index(default);”

    pretty lean and simple. You can also re-order the z-index map anything you want or add/edit the numbers based on your requirements.

  3. Of course, get a map function to make that work.

    @function z-index($value) {
    @if map-has-key($z-index, $value) {
    @return map-get($z-index, $value);

    @warn “Unknown `#{$value}` in $z-index.”;
    @return null;

Have a comment?

Your email address will not be published. Required fields are marked *

accessibilityadminaggregationanchorarrow-rightattach-iconbackupsblogbookmarksbuddypresscachingcalendarcaret-downcartunifiedcouponcrediblecredit-cardcustommigrationdesigndevecomfriendsgallerygoodgroupsgrowthhostingideasinternationalizationiphoneloyaltymailmaphealthmessagingArtboard 1migrationsmultiple-sourcesmultisitenewsnotificationsperformancephonepluginprofilesresearcharrowscalablescrapingsecuresecureseosharearrowarrowsourcestreamsupporttwitchunifiedupdatesvaultwebsitewordpress