3d Text technique

3D CSS Text with 3D Transforms

A new method for creating incredibly realistic 3D Text using only CSS

noahblon
3 min readOct 12, 2013

--

Several years ago, @mdo released a demo which used stacked text shadows to create a 3D effect on text. The use of CSS3 to create such realistic and cool looking 3D blew my mind.

Now, CSS actually has the ability to create real 3D effects. In this article, I’ll write about a new way to create 3D text powered by 3D transforms that looks incredibly realistic. You can see a screenshot of the effect in the headline image of this post and check out a functioning demo of the technique on Codepen.

Setting the scene

First, lets set up the markup. We’ll setup our scene and inside the scene, several layers.

<div class=’scene’> 
<div class=’layer’></div>
<div class=’layer’></div>
<div class=’layer’></div>
<div class=’layer’></div>
<div class=’layer’></div>
<div class=’layer’></div>
<div class=’layer’></div>
<div class=’layer’></div>
<div class=’layer’></div>
<div class=’layer’></div>
</div>

Each layer will contain a copy of our text. When transformed in z-space, the layers will stack on top of each other. With a small enough transform, the text in the layers will appear to be a unified whole, and three dimensional.

Now for the styling needed to make this work:

html, body { height: 100%; width: 100%;}.scene {
height: 100%;
width: 100%;
perspective: 800px;
transform-style: preserve-3d; }
.layer {
width: 100%;
height: 100%;
position: absolute; }

Notice how the layers are the full size of the viewport and positioned absolutely. We now have a whole bunch of layers stacked on top of each other that equal the size of the scene. This is a critical trick for how this effect works.

.layer::after {
content: ‘Text \A separated with \A line-breaks’;
white-space: pre;
text-align: center;
display: flex;
align-items: center;
justify-content: center; }

Now we’ll set up our child elements which contain our stacking text. I’m using pseudo-generated content because it keeps my markup a little cleaner and is a bit more fun to pull off, but you could use text inside an element with the layer as a parent instead. Notice that the white-space property is set to pre-formatted. This allows you to insert line breaks into your generated content with \A (carriage return), a very handy trick I’ve used a ton.

I’ve also used flexbox to center the text horizontally and vertically in the viewport.

.layer:nth-child(1):after {
transform: translateZ(-4px);}
.layer:nth-child(2):after {
transform: translateZ(-8px);}
.layer:nth-child(3):after {
transform: translateZ(-12px);}
/* So on and so forth */

Finally we’ll stack our layers by translating them on the z-axis. Each layer will be a distance behind the previous, selected by their index (nth-child). A Sass loop is helpful to create this block of code, but as an example I’ll show you the first few layers in vanilla CSS. You will need need to translate each layer you choose to include.

Basically, thats the nuts and bolts of the setup. Now its just visual styling. For my demo, I’ve added text shadows to layers which give it an illusion of lighting on the text itself. On the last layer, I’ve added a bunch of text shadows giving the actual illusion that the 3d object is casting a shadow. I’ve made the first layer a slightly lighter color than subsequent layers to make the distinction between the face and sides of the object more distinct.

.layer::after {
color: #222;
text-shadow: -1px -1px 1px rgba(255, 255, 255, 0.1), 1px 1px 2px rgba(0, 0, 0, 0.5);}
.layer:first-child:after {
color: #212121;}
.layer:last-child:after {
text-shadow:
1px 1px 1px black,
5px 5px 5px rgba(0, 0, 0, 0.6),
10px 10px 10px rgba(0, 0, 0, 0.5),
20px 20px 40px rgba(0, 0, 0, 0.3),
30px 30px 50px rgba(0, 0, 0, 0.3),
40px 40px 100px rgba(0, 0, 0, 0.3);}

However you can play with the styling achieve other neat effects. I’ve played with opacity, background-clipping, and gradient masks to achieve some really neat results. You can also try animating the thing, for example animating the perspective, the perspective origin or the layers position in z-space.

Look out for a future post where I’ll show you some other tricks using this technique.

--

--