On this article, I’ll present you methods to use fashionable CSS tips to create fancy CSS ribbon shapes with minimal code. As an additional bonus, our ribbons can have hover animations!
CSS ribbons are in every single place, and you will discover a ton of articles about them, however the ones we’ll create listed below are a bit particular. We’re going to depend on a single ingredient to create every of the shapes, and CSS variables to simply management them. We aren’t going to depend on fastened dimensions or magic numbers. The shapes will match their content material so that you don’t have to fret concerning the textual content inside.
I’ve made a group of CSS ribbon shapes with a whole lot of cool examples, and on this article, we’re going to review two varieties of them, pictured under.
I’ll be calling the left one the “folded ribbon” and the fitting one the “rotated ribbon”.
Making a CSS Folded Ribbon Form
Step one in creating our folded CSS ribbon is to outline the variables of our form.
.ribbon {
--r: 20px;
--s: 20px;
--c: #d81a14;
}
Two variables will management the form, and one variable will management the colour.
Utilizing clip-path to create a CSS ribbon
Now let’s transfer to the code. We’re primarily going to depend on clip-path
. The picture under illustrates the polygon form we’re going to make use of.
We add some padding to keep away from slicing the textual content, then we apply the clip-path
:
.ribbon {
--r: 20px;
--s: 20px;
--c: #d81a14;
line-height: 1.6;
padding-inline: 1.2lh calc(var(--r) + .2lh);
background: var(--c);
clip-path: polygon(1lh 0,100% 0,calc(100% - var(--r)) 50%,100% 100%,100% 100%, 0 100%,0 100%);
}
Utilizing the CSS lh unit
It’s possible you’ll be questioning what’s happening with the lh
unit. It’s a brand new unit that corresponds to the line-height
worth. Since we’re utilizing one line of textual content, the line-height
setting is what controls the peak, so 1lh
is equal to the peak of the ingredient, which is tremendous helpful. (You may learn extra concerning the lh
unit in An Overview of CSS Sizing Models.)
In clip-path
, I want to chop the form of an isosceles triangle, and to do that I must know the peak of the ingredient. 1lh
is the same as that top.
Making a CSS fold with clip-path
Now, to create the folded half, we’re nonetheless going to make use of clip-path
and replace the earlier polygon. The cool factor about clip-path
is that it could lower “outdoors” the boundaries of the ingredient. It could sound shocking or perhaps ineffective, on condition that now we have nothing outdoors, but it surely means we are able to embody issues like box-shadow, define, pseudo-elements, and so forth.
In our case, we’ll depend on box-shadow
. The picture under illustrates the trick.
Word how I’m updating the clip-path
to incorporate 4 new factors, three of that are outdoors the ingredient. For the reason that half we’re slicing is outdoors, it’s not seen, but when we add an enormous box-shadow
we make if seen. I’ve used a blue coloration as an example the thought above, however within the code we’ll use the identical coloration because the background:
.ribbon {
--r: 20px;
--s: 20px;
--c: #d81a14;
line-height: 1.6;
padding-inline: 1.2lh calc(var(--r) + .2lh);
background: var(--c);
clip-path: polygon(1lh 0,100% 0,calc(100% - var(--r)) 50%,100% 100%,1lh 100%,1lh calc(100% + var(--s)),.5lh calc(100% + var(--s) + var(--r)),0 calc(100% + var(--s)),0 100%);
box-shadow: 0 0 0 999px var(--c);
}
Lastly, we add a contact of shadow impact by introducing a gradient and one other box-shadow and we’re achieved. Our CSS ribbon form is ideal!
Working with polygons to invert our CSS ribbon
You’re in all probability questioning methods to create the second ribbon (the inexperienced one). We do the identical factor however with a distinct polygon. We take the primary polygon and we invert it.
A polygon will be written like so:
clip-path: polygon(X1 Y1, X2 Y2, ..., Xn Yn)
To get the alternative form, you modify all Xi
by 100% - Xi
. So simple as that! Earlier than checking my code, attempt to do it alone utilizing the polygon of the primary ribbon.
Tips on how to animate our CSS ribbon
Within the demo above, hover the shapes to note a pleasant animation. To realize it, we have to replace the polygon on hover by offsetting some factors. I received’t re-write the entire polygon on hover, however I’ll outline a CSS variable that may management the offset.
If you happen to deal with the animation, you’ll discover that now we have three factors transferring to the left and three factors transferring down and to the left as effectively.
We replace the Xi
of the factors transferring to left with Xi + d
and we replace the Yi
of the factors transferring doing with Yi + d
. Then we merely replace the variable d
to manage the motion:
.ribbon {
--d: 0px;
clip-path: polygon(calc(1lh + var(--d)) 0,100% 0,calc(100% - var(--r)) 50%,100% 100%,calc(1lh + var(--d)) 100%,calc(1lh + var(--d)) calc(100% + var(--s) + var(--d)),calc(.5lh + var(--d)) calc(100% + var(--s) + var(--r) + var(--d)),var(--d) calc(100% + var(--s) + var(--d)),var(--d) 100%);
}
.ribbon:hover {
--d: .2lh;
}
If you happen to see such a polygon for the primary time, you might get confused, because it appears to be like a bit scary. However in actuality, it’s not that advanced. We began with a easy polygon and we slowly added extra factors and extra calculations till we reached this advanced one.
Making a Rotated CSS Ribbon Form
Let’s sort out the second form. For this one, we’ll use the brand new trigonometric capabilities together with CSS variables and calc()
just like the earlier one. To know the logic behind this form, let’s rotate it and hold the textual content in a straight line.
I’m including a little bit of transparency to see the components behind the primary ingredient. I’ll be utilizing pseudo-elements to create them. I’ve additionally added the blue define as an example the realm of the ingredient. This form shall be managed with two variables:
.ribbon {
--r: 30px;
--a: 15deg;
}
The r
is doing the identical job as with the earlier form. The a
will management the rotation of the primary ingredient and a whole lot of different issues.
Let’s begin with the primary ingredient. We will see from the determine that we have to lower it from all sides, so you might logically consider using clip-path
, however not this time. We’ll depend on a gradient coloration, the place the half we have to lower can have a clear coloration:
.ribbon {
--r: 30px;
--a: 15deg;
background:
linear-gradient(calc(90deg + var(--a)),
#0000 calc(1lh*sin(var(--a))),
var(--c) 0 calc(100% - 1lh*sin(var(--a))),
#0000 0
);
}
Working with geometry in CSS
Right here comes the geometry.
The a
is the angle variable we outlined. Contemplating this, the gradient must have an angle equal to 90deg + a
, and the clear coloration ought to begin at 0
and cease at d
. Doing a little math, d
is the same as 1lh*sin(a)
. If we apply the identical logic on the opposite facet, we get the next code:
background:
linear-gradient(calc(90deg + var(--a)),
#0000 0% calc(1lh*sin(var(--a))),
var(--c) calc(1lh*sin(var(--a))) calc(100% - 1lh*sin(var(--a))),
#0000 calc(100% - 1lh*sin(var(--a))) 100%
);
We do some optimization by eradicating the 0%
and 100%
(they’re implicit), and when now we have two consecutive coloration stops which are equal, we are able to substitute the second with 0
:
background:
linear-gradient(calc(90deg + var(--a)),
#0000 calc(1lh*sin(var(--a))),
var(--c) 0 calc(100% - 1lh*sin(var(--a))),
#0000 0
);
We’re achieved with the primary ingredient, so let’s transfer to the pseudo-elements. Right here as effectively, we want some geometry tips to establish the scale.
We will simply discover the peak H from the earlier determine we used to establish the gradient configuration. It’s equal to 1lh/cos(a)
. For the width W, it’s equal to (100% - x)*cos(a)
, the place 100%
is the width of the primary ingredient and x
is that small half the place now we have the transparency. It’s equal to 1lh*tan(a)
.
Each pseudo-elements have the identical measurement, so our code is as follows:
.ribbon:earlier than,
.ribbon:after {
content material: "";
place: absolute;
top: calc(1lh/cos(var(--a)));
width: calc(100%*cos(var(--a)) - 1lh*sin(var(--a)));
}
If you happen to’re not comfy with the maths and also you’re a bit misplaced with the method, it’s superb. You don’t must precisely perceive them. The purpose is to have the ability to modify the form utilizing CSS variables. The formulation are right here to make issues simpler and keep away from us coping with hard-coded values and magic numbers.
After the dimension, we should always accurately place every pseudo-element, rotate it, and use clip-path
for the cutout half:
.ribbon:earlier than,
.ribbon:after {
content material: "";
place: absolute;
remodel: translate3d(0,0,-1px);
rotate: var(--a);
top: calc(1lh/cos(var(--a)));
width: calc(100%*cos(var(--a)) - 1lh*sin(var(--a)));
background: color-mix(in srgb,var(--c),#000 40%);
}
h1:earlier than {
proper: 0;
prime: 0;
transform-origin: prime proper;
clip-path: polygon(0 0,100% 0,100% 100%,0 100%,var(--r) 50%);
}
h1:after {
left: 0;
backside: 0;
transform-origin: backside left;
clip-path: polygon(0 0,100% 0,calc(100% - var(--r)) 50%,100% 100%,0 100%);
}
The code needs to be self-explanatory and the clip-path
worth needs to be straightforward to know. We used extra advanced polygons with the primary form.
Word the usage of color-mix()
, which permits me to create a darkish model of the primary coloration. I’m additionally utilizing a 3D translate with a unfavourable worth on the z-axis to deliver the pseudo-elements behind the primary ingredient. You may assume that that is the job of z-index
, but it surely received’t work because of some stacking context points that I’ve detailed on this Stack Overflow thread.
Now, if we rotate the ingredient in the wrong way, we get our CSS ribbon form.
As with the earlier instance, I’ll allow you to dissect the code of the inexperienced ribbon and see what modifications I made to get the alternative form.
Conclusion
It was a enjoyable train, don’t you assume? We explored some fashionable CSS options like CSS variables, calc()
, and trigonometric capabilities, and we mixed them to create fancy ribbon shapes.
If you need extra, go try my full assortment of ribbon shapes. Attempt to construct a few of them alone earlier than checking the code. It is going to be a very good train to apply what you’ve realized right here.