A CSS Property for Creating Depth

Web design is still very much a two-dimensional medium. Pretty unsurprising considering that print journalism is among the earliest trades to embrace the web platform, once hailing it as the birth of “Way New Journalism”. Much of what we do on the web is pretty much a substitute for paper, whether it’s reading news, saving documents in folders, creating checklists, making reservations, ordering food off menus, and whatnot. Writing this blog post is just as much a substitute for the journals where I’d documented many pages of memories by hand.

It’s called a web page after all.

There are pleny of ways web design creates the illusion of depth. Box and text shadows in CSS, for one, certainly add some sort of visual separaton between elements and the page surface. SVG can be used to draw three-dimensional shapes on the screen. We have the z-index property for managing elements with stacking contexts. The <canvas> element is capable of some pretty wild 3D-esque stuff by way of WebGL. CSS masks can make it look like something “pops” off the screen. We can even use clever positoning and perspective trickery in CSS to make something “flip” from front to back. Parallax-like scroll shadows, anyone?

In some ways, it’s actually useful to think about CSS in terms if “cubes” instread of “boxes”.

Even with all of these clever tools, features, and tricks at our disposal, I still find it tough to draw a cube in CSS. Instead, I’d probably whip something up in Figma, export it as SVG, put it on the page, and call it a day. But what I really want to do is this:

.cube {
  aspect-ratio: 1;
  depth: 2;
  width: min(200px, 50%);
}

The idea is that we can set a length on the element’s width, apply an aspect ratio to add length to the height, then establish length in the z-direction — near and away. In other words:

  • width sets a length on the x-axis,
  • aspect-ratio references the width to apply length along the y-axis, and
  • depth references the width to apply length on the z-axis.
Cube illustration labeled with CSS properties for width, aspect-ratio, and depth.

I haven’t fully thought this out. Like, what would happen if border-radius: 50% is slapped on there? Would we get a sphere? What about negative values? Should those add depth in a different direction? Does that even make sense, or should we ignore negative values altogether?

What I can imagine is that depth would default to 0 (perfectly flat) and accept any length value, perhaps fr units being the exception. So, if we were to set depth: 3rem that would reference the HTML root font-size to compute a value. Or, hey, go wild with fixed pixels, yeehaw!

A unitless value can be computed by the width or height, whichever is set. Oh wait, both are set? Reference width first, I guess? Maybe that’s an implicit keyword we can override:

.cube {
  depth: 2 height;
  height: 100px
  width: 200px;
}

Even better, using logical directions:

.cube {
  depth: 2 block; /* default: inline */
  height: 100px
  width: 200px;
}

Oh gosh, we probably have to consider how it gets resolved when min-* and max-* properties — including min(), max(), and minmax() functions — are in the mix. I suppose whichever value is “greater” wins? Isn’t that sorta how aspect-ratio works?

I dunno, just spitballing here. Someone please sto—

✏️ Handwritten by Geoff Graham on October 25, 2023

Leave a Reply

Markdown supported