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, anddepth
references the width to apply length on the z-axis.
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—