Skip to content

chrislloyd/nested-index-set

Repository files navigation

Nested Index Set

Remove CSS z-index magic numbers with nested index sets.

Installation

npm install @chrislloyd/nested-index-set --registry=https://npm.pkg.github.com

Reference:

Usage

NestedIndexSet is a better model for CSS z-index. Instead of just having a large list of magic numbers, NestedIndexSet lets you capture relationships between your elements. Nested index sets are are easy to change without breaking unrelated parts of your site - you can guarentee that the menu always shows above a modal, even if the modal changes.

A basic example is figuring out a z-index for a Modal. Using a fixed number (i.e. 999) doesn't capture the intent that it should sit above other element's on the page. For example:

import NestedIndexSet from '@chrislloyd/nested-index-set';

// The min/max values are the (approximate) values of CSS' integer types.
const page = NestedIndexSet.fromRange(-2147483648, 2147483647); // index=0

export const z = page.above(); // index=1073741824
export function Modal() {
    return <div style={{ zIndex: z.index }} />;
}

If the Modal is changed to be below a Menu, we'd simply update that reference:

const menu = page.above();
export const z = menu.below();

All indexes that depend on z are guarenteed to still work as intended.

Integration

NestedIndexSet can be used in brown-field sites where you may already have fixed z-index and want to incrementallly capture the relationship between them. For example:

// previously:
// --menu-z-index: 998;
// --menu-z-index: 999;
const menu = new NestedIndexSet(0, 998, 999); // index=999
const modal = new NestedIndexSet(998, 999, 2147483647); // index=9999

If you start off by expressing the values in this way, you can then incrementally update your site to use a more expressive setup like in the previous example. menu.max and modal.index being the same value is a good hint that those indexes are defined in terms of one another.

Static vs. Dynamic

There's nothing about NestedIndexSet that requires static usage (i.e. values computed in module scope rather than at runtime) however that is it's primary usage. By specifying indexes in module scope, it makes the indexes more portable to more environments (server rendering, codegen etc.). It's more akin to traditional CSS.

Background

NestedIndexSets are inspired by Nested Sets from relational databases. By capturing the bounds of an index, it lets us specify z-index values as a tree rather than global magic variables.

               below                             above

| ----------------------------- page ----------------------------- |
                                  | ------------ menu ------------ | 
                                  | --- modal --- |

There are other ways of capturing these relationships but they either:

  • Don't guarentee uniqueness (i.e. two elements can occupy the same index)
  • Aren't available statically

Reference:

Development

Open in GitHub Codespaces

Contributing

I (@chrislloyd) have minimal time to dedicate to open source contributors. This package is provided "as is" and is primarily intended for my own benefit. PRs are welcome, however.

Reference:

About

Remove CSS z-index magic numbers with nested index sets

Resources

Stars

Watchers

Forks