A stylish faux-3D effect in pure CSS.

Boxes & Notches

Prism is built on two complementary structures: boxes, which extrude out of the page, and notches, which sink into the page. Box shadows are special – look at the corners!

Oh, wait... your browser doesn't support the fancy shadows. Bummer.

prism-box-lg
prism-box-sm
prism-notch-sm
prism-notch-lg
prism-blank

Depth tracking

The virtual “depth” of nested boxes and notches is tracked up to a customizable recursion limit.

Nested prism-box-sm elements
Nested prism-notch-sm elements

Interactivity

Built-in -active-, -focus-, and -hover- variants of classes can dynamically change the depth of elements. Still no JavaScript in sight!

Demo form (click around!)

(Check the “Selector quirks” section below for important caveats.)

Usage

Getting started

Download / fork from GitHub

Prism is a Sass project. Compile or include prism.scss as you would any other Sass file. If you need help, the Sass guide is a great resource.

Apply the class prism-base to the outermost container (e.g. your <body> tag) to begin using Prism.

Customization

The file _prism-config.scss contains everything you would want to customize:

$prism_ Description (default)
base_suffix change the name of the prism-base container (base)
base_index the starting depth (5)
max_nesting maximum nested elements for depth tracking (2)
transition_duration transition duration for depth changes (0.2s)
shadow_offset_lg length of large shadows (4px)
shadow_offset_sm length of small shadows (2px)
bg_list list of 9 background colors, from lowest to highest depth
sh_list list of 9 shadow colors
tx_list list of 9 text colors

Reference

Every available class fits one of the following forms:

  • prism-{type}-{size}
  • prism-{selector}-{type}-{size}
  • prism-blank
  • prism-{selector}-blank

Substitute the curly-braced words as needed:

  • {type}: box or notch
  • {size}: sm or lg
  • {selector}: active, focus, or hover

Technical details

Box shadows

The fancy box shadows are implemented using a CSS clip-path polygon on an :after pseudo-selector. If this feature isn't available, it falls back to a standard flat box-shadow.

The pseudo-selector shadow requires the parent element to have its own positioning context, so all Prism elements have position: relative; applied to them.

There are two consequences of the pseudo-selector usage, both of which can be solved with <div> wrappers:

  • You cannot use the :after selector on a Prism box for your own purposes.
  • Prism boxes must be containers – notably, <input> and <img> are not containers.

Notches, on the other hand, just use an inset box-shadow, and so can be applied to any element.

Depth limitations

The virtual “depth” starts at a value of 5 by default. Boxes increase this value and notches decrease it, by either 1 or 2 steps depending on whether it's small (-sm) or large (-lg). The depth determines the background, shadow, and text colors (see the Customization section).

The depth is clamped between 1 and 9, inclusive. Attempting to go beyond this range will lead to unsightly stacking and shadow colors, but for most practical usage, these limits should never cause any issues.

Depth-tracking is implemented through a recursive Sass mixin. Increasing the max nesting leads to an exponential size increase of the output .CSS file, which is why it has a fairly conservative default value.

Selector quirks

Selector variants (e.g. prism-hover-…) can't contain nested Prism elements. This is purely by design – allowing them to do so increases the output filesize by an unreasonable ratio, for little practical gain.

Selector transitions from box to notch are not supported – the box and notch shadows will both be visible when in notch form. This could be solved by giving notches a “blank” clip-path shadow, but the transition would still have issues: the box shadow would remain visible for too long, and the notch shadow would appear too soon. So, again, this quirk is by design.

The reverse case (notch to box) does not suffer from the same double-shadow issue, but the shadows are still both visible for too long mid-transition, so this use case is discouraged.