In this article, we will explore a few tricks that allow you to add a touch of 3D to your text content. We won't use complex code and a ton of HTML, only a few lines of CSS and you can have the following result:
Creating a 3D box
Let’s start with the following HTML code
<span>A Title</span>
and here is the CSS to transform that single line of text into a 3D box:
span {
--d: .3em; /* control the depth */
padding-block: .1em calc(.1em + var(--d));
padding-inline:.2em calc(.2em + var(--d));
background:
conic-gradient(at right var(--d) bottom var(--d),
#0004 37.5%,#0008 0 75%,#0000 0)
#d81a14; /* the main color */
clip-path: polygon(0 0,calc(100% - var(--d)) 0,100% var(--d),100% 100%,var(--d) 100%, 0 calc(100% - var(--d)));
}
I am using a span
to illustrate that the trick works with inline level elements but it can also be used with block level elements such as block
and inline-block
elements. In the end, we always have one 3D box with our text content.
Now let’s dissect the code. The first thing we are doing is defining the variable --d
that will control the 3D effect. You can adjust the value to understand its effect. Then we define the padding
.
Without the 3D effect our padding should be:
padding-block: .1em;
padding-inline: .2em;
But we need extra space on the right and bottom side
padding-block: .1em calc(.1em + var(--d)); /* top & bottom */
padding-inline:.2em calc(.2em + var(--d)); /* left & right */
.1em
and .2em
are arbitrary values so feel free to use whatever you want.
The next step is to add the gradient coloration
We first apply a solid color as background-color and above it, we use a conic-gradient with three colors. A transparent one and two semi-transparent black to create the different shades of our 3D box.
background:
conic-gradient(at right var(--d) bottom var(--d),
#0004 37.5%,#0008 0 75%,#0000 0)
#d81a14; /* the main color */
We can use only the conic-gradient and define the final colors there but it requires us to manipulate three colors instead of only one.
The last step is to apply clip-path
to cut to corners and get the final shape.
clip-path:
polygon(
0 0, /* 1 */
calc(100% - var(--d)) 0, /* 2 */
100% var(--d), /* 3 */
100% 100%, /* 4 */
var(--d) 100%, /* 5 */
0 calc(100% - var(--d)) /* 6 */
);
That’s all. With only a few lines of CSS, you get a cool 3D effect. You can easily adjust the code to get a different variation.
I let you dissect the code as a small exercise to understand the changes I have made.
Multi-line 3D effect
Let’s move to the interesting part. The previous effect works only with a single inline sentence or a block-level element but what we want is to support multi-line. We won’t wrap each line in a div
or span
but we will keep our code simple:
<span>A title <br> with many lines<br> of text</span>
I am using <br>
to introduce line breaks but they can also occur naturally when the text doesn’t fit into one line.
If we apply the previous CSS we get the following:
It’s clearly broken but we can fix it with a few adjustments. First of all, clip-path
doesn’t play well with inline elements having many lines so let’s remove it.
span {
--d: .3em; /* control the depth */
line-height: 2; /* control the distance between lines */
padding-block: .1em calc(.1em + var(--d));
padding-inline:.2em calc(.2em + var(--d));
background:
conic-gradient(at right var(--d) bottom var(--d),
#0004 37.5%,#0008 0 75%,#0000 0)
#d81a14; /* the main color */
}
I am introducing the line-height
property to control the height of one line or, seen differently, the distance between lines.
A little better but still not there. It’s important to notice the effect of the background and how it splits between the lines, the same for the padding. We can control this effect using box-decoration-break: clone
Each box fragment is rendered independently with the specified border, padding, and margin wrapping each fragment. The
border-radius
,border-image
, andbox-shadow
are applied to each fragment independently. The background is also drawn independently for each fragment, ref
We are getting closer. We are only missing the cut part that we did with clip-path previously. We are going to use mask for this. It relies on gradients so it will also get “cloned” for each line like the previous decorations:
mask:
linear-gradient(45deg,
#0000 calc( var(--d)*cos(45deg)),
#000 0 calc(100% - var(--d)*cos(45deg)),
#0000 0);
Our effect is now perfect. Here is the full demo with two variations
You can use whatever content you want and as many lines as you want. All you have to do is adjust a few values to control the color, the 3D depth, and the distance between the lines.
Let’s try another kind of 3D effect where the boxes stretch to the end of the line. This time we will work with block-level elements.
The logic of this effect is different and it’s all about repeating gradients following the y-axis and we will use the height of one line for this. Luckily the new lh
is what we need here since 1lh
is equal to one line of text (more precisely the height of the line box)
Let’s start by defining the parameters:
h2 {
--d: .3em; /* control the depth */
--s: .2em; /* control the space between boxes */
line-height: 2; /* control the height of the boxes */
}
Then we apply a background configuration similar to the previous effect:
background:
conic-gradient(at left var(--d) bottom var(--d),
#0000 25%,#0008 0 62.5%,#0004 0) 0 0/100% 1lh
#2699DC
Note how the height of the gradient is equal to 1lh
to make it repeat each line of text.
The next step is to apply a mask to create the space between the lines and at the same time cut the corner to create the 3D effect. Here is a figure to illustrate the gradient configuration of the mask:
A first gradient will cut the red part and a second one will cut the green part.
mask:
conic-gradient(from 90deg at var(--d) var(--s),
#000 37.5%,#0000 0) 0 0 /51% 1lh repeat-y,
conic-gradient(from 45deg at calc(100% - var(--d)) calc(100% - var(--s)),
#0000 62.5%,#000 0) 100% var(--s)/51% 1lh repeat-y
We are almost good, we can already see our 3D effect across multiple lines:
But if you look closely, you can notice that the text is not perfectly aligned inside the box. It’s closer to the bottom than the top. We need to offset the whole gradient configuration (background and mask). I will skip the math part and will give you the value of the offset which is (d - s)/2
and the full code will be:
h2 {
--d: .3em; /* control the depth */
--s: .2em; /* control the space between boxes */
line-height: 2; /* control the height of the boxes */
padding-inline: calc(var(--d) + .2em) .2em;
background:
conic-gradient(at var(--d) calc(100% - var(--d)),
#0000 25%,#0008 0 62.5%,#0004 0) 0 calc((var(--d) - var(--s))/2)/100% 1lh
#2699dc; /* the main color */
mask:
conic-gradient(from 90deg at var(--d) var(--s),
#000 37.5%,#0000 0) 0 calc((var(--d) - var(--s))/2)/51% 1lh repeat-y,
conic-gradient(from 45deg at calc(100% - var(--d)) calc(100% - var(--s)),
#0000 62.5%,#000 0) 100% calc((var(--d) + var(--s))/2)/51% 1lh repeat-y;
}
The text is now centered within the boxes but the offset created another issue. The box of the last line is cut and we have a strange line at the top.
To fix the first issue we add a padding-bottom
and for the second one, we use clip-path
to hide the line at the top.
padding-bottom: calc(var(--d)/2);
clip-path: inset(calc(var(--d)/2) 0 0);
Now our effect is perfect. Here is the full demo again
Another 3D effect
let’s try a last one but this time we are going to put letters/numbers inside 3D boxes
As you can see in the code, we are not wrapping each letter inside a container. We are using the same technique as the previous effect but this time following the x-axis. Instead of “each line”, it’s “each letter” and for this, I will rely on the ch
unit (instead of the lh
). All the letters need to take up the same amount of space so only monospace fonts are suitable for this effect.
I won’t dig into the code because this will be your homework! Try to follow the same steps as I did previously and you will see that I am using almost the same tricks
Frequently Asked Questions
Are website builders easy to use?
One of the easiest ways to build a website is with a website builder. Using a website builder doesn't require any programming and coding skills.
Is a website on WordPress safe?
Websites on WordPress are safe, however to avoid hacking keep your website up to date.
Why should I create a website?
There are many reasons why you should create a website if you’re an artist. You can use it to create a place where people can learn about you, talk about your art, or show off your work.
Can you migrate my existing website over?
Yes, and without issue. Regardless of how many websites you’re managing, we’ll bring all of them under the Verpex wing free of charge. Just send us the details of your websites when you’ve signed up to get started.
Temani Afif is an expert web developer, a content creator, and a CSS addict. He is the mastermind behind CSS Loaders, CSS Generators, CSS Tip and a lot of CSS stuff.
View all posts by Temani Afif