Pure CSS 3D product shots from a 2D graphic

Sometimes it’s useful to embrace your laziness!

As SitePoint’s in-house book cover designer, I have two main tasks:

  1. To produce the single-piece wrap-around cover design for our Print-on-Demand process (Indesign work)
  2. To make a faux-3d image of what that book will look like in the real-world for product pages.

As you might guess, that second part is fairly repetitive Photoshop ‘grunt work’. Distort each 2d face onto the shapes of a 3d book image.

And if we want a slightly different view of the book for a different part of the product page, I’m pretty much resigned to creating a new graphic from scratch.

What if we could farm that second task out to pure CSS? Could we get a better, more flexible result?

##Spoiler alert: You can!

3d_Lighting_Effects_in_CSS.png

Here’s a CodePen of my solution.

LINK

I’ll leave the nitty-gritty technical stuff to a separate post but I thought I’d cover some of the obvious questions here.

###Why do it?

Does ‘It’s more fun than Photoshop’ count?

The flat-color versions of these covers compress beautifully as PNG, so we can afford to send a single, reasonably high-resolution file. That’s one HTTP request that we can reference in 2, 3 or 4 different views and scales.

If you think about it, we stopped using FONT tags because we didn’t want a transitory presentation decisions to be locked into the content. This has a similar feeling to me.

The original framing decision for a product shot could be very much linked to the shape of the original layout it inhabited. This approach can un-couple us from permanent layout decisions.

###How does it work?

I’m trying to keep the HTML lightweight but sensible.

Two DIVs display the front and back cover respectively as background-images. Background-position ensures we’re seeing the right parts.

The other edges and spine are all pseudo elements (:before and :after). A wrapper DIV groups them. The outer DIV is the ‘3d stage’ we work in.


In production the idea is to chain CSS classes to the ‘stage’ to compose the shot – .cam-high, .cam-low, .clockwise45, .anticlockwise15, .large, etc.

You’re really animating it?

Animation is a side-benefit rather than the goal here.

I’m animating the demo mainly to make it clear that you’re not looking at a flat JPG. In production we may animate (or transition) the book on hover.

The goal was to replace static, hand-made JPG images with something easier and more versatile.

###But it doesn’t look flat now

In my first attempts I nailed the 3d transforms but the color was far too flat to fool the eye. Real-world books catch light and shadow.

Luckily we can do a reasonable job mimicking this behaviour with CSS linear gradients. My gradient transitions from transparent, to smokey white to smoky black to transparent.

grad.png

It’s effectively a transparent version of this gradient.

Using multiple backgrounds I’m layering an over-scaled gradient across each of the shiny surfaces to create uneven lighting.

It’s surprisingly effective to animate the position of the gradient as we rotate the model. It’s subtle but it adds a lot without much overhead.

###Downsides?

There aren’t too many. Small rounding errors in the CSS can leave razor thin gaps along some joining edges. Slightly adjusting the angle can often be enough to fix it.

I’m not ruling out a fix – perhaps an inner box-shadow in gray? – but I haven’t got it yet

Older browsers won’t understand the 3d CSS properties. This means they’ll render the cover flat – no disaster there. Ideally we’d turn off those pseudo elements.

###Other applications?

Obviously it’s going to be difficult to do this with effectively with, say, t-shirts and tennis shoes.

Nevertheless anything from software to CDs to DVDs to breakfast cereal or any other boxed product could benefit for this approach.

So what do you think?

Originally published in the SitePoint Design Newsletter

13 Likes

Jesus Christ, that’s some beautiful code. Great work @alexmwalker . It’s be great to be able to click and rotate it but as far as this goes, you’ve done a fantastic job.

1 Like

Aw, thanks @RyanReese :slight_smile:

Yes, letting the user turn it in either direction would be a nice touch.

It is actually very nice.

I’m thinking running the animation all the time could be distracting so it would be even better if you could run it once or that the user could run it when he wished.

But, of course, that can’t be done with CSS only.

Still, food for thought there… a nicely done!

1 Like

I’m currently using radio buttons and :checked combined with sibling selectors to let the user turn the animation on and off with pure CSS.

Not sure if it’s the ideal way to do things, but it’s certainly possible. :wink:

2 Likes

At work I’m kind of limited to what I can load and see so I’ll need to get home and look into this further. Never thought that it could be possible. Then I liked the article even more.

Thanks. You always write interesting and creative articles that makes you look at things from a different angle.

Almost like @PaulOB’s quizzes and CSS tests… but without the evil side :stuck_out_tongue:

Although I have to say that @kevinyank does like to post tricky questions too (I’m thinking about his latest article 3 Things (Almost) No One Knows About CSS - #59 by GeoBake)

1 Like

Great job Alex (as usual) :smile:

I especially love the subtle gradient animation which brings the whole thing to life.

4 Likes

There are tons of hacks from perspective to backface visibility so you should be able to get this looking really good. You could look at using pseudo elements and negative margin to fill the gaps.

Stunning demo, Alex. I also hate using Photoshop, InDesign etc. these days, as they feel so limited in some respects in comparison to front-end technologies.

1 Like

I’m already using all my pseudo elements on my construction DIVs. Could I use on from the grouping DIV? Maybe.

At one stage I did have a -1px adjustment on the spine position in my Sass.

It actually worked, but I just couldn’t stomach it in my code. I’ll find a better way. :wink:

1 Like

I have no doubts, keep us all posted.

I moved a post to a new topic: Help needed to create a pop-up menu

Its amazing man! a step by step guide is aprreciated.

1 Like

Just wanted to to echo what was has already been said. great effect and very elegant code!

Wow, it’s amazing code
Great and fantastic job alexwalker :grinning:

really really nice. Is there any way to do this with objects that aren’t rectangular? I’m guessing not?

Alex did some sort of cylinder-shaped one a bit ago. Can’t find the link for it.

Many complex 3D models are in fact made up from multiple quad polygons, though not necessarily rectangular or planar, they may be trapezoid or any kind of quadrilateral. These could maybe be masked with alpha in images to appear as non rectangular quads. So in theory (that I’m just making up) more complex shapes could be created. Though I fear the css involved may make your head explode.

I’d like to see that. Was it using multiple elongated rectangles to make the curve?

could you could use a lot (really a lot) of elements with border-radius: 50% to make a sphere?

edit: apparently yes: http://codepen.io/peterwestendorp/pen/wGECk

2 Likes

'Tis a master thing…