From our sponsor: Meco is a distraction-free space for reading and discovering newsletters, separate from the inbox.
After exploring some hover animations for links using CSS only, I also wanted to make some button animation using some interesting CSS techniques like animating a clip path or applying a mix-blend-mode.
The following button uses a mix of a fancy border radius and a clip path animation. Note that I’m using SVG path data for the clip path and animating to another path seems to work already, so this is such a cool thing and allows for so many great effects!
.button {
pointer-events: auto;
cursor: pointer;
background: #e7e7e7;
border: none;
padding: 1.5rem 3rem;
margin: 0;
font-family: inherit;
font-size: inherit;
position: relative;
display: inline-block;
}
.button::before,
.button::after {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.button--janus {
font-family: freight-display-pro, serif;
font-weight: 900;
width: 175px;
height: 120px;
color: #fff;
background: none;
}
.button--janus::before {
content: '';
background: #e6e6e6;
-webkit-clip-path: path("M154.5,88.5 C131,113.5 62.5,110 30,89.5 C-2.5,69 -3.5,42 4.5,25.5 C12.5,9 33.5,-6 85,3.5 C136.5,13 178,63.5 154.5,88.5 Z");
clip-path: path("M154.5,88.5 C131,113.5 62.5,110 30,89.5 C-2.5,69 -3.5,42 4.5,25.5 C12.5,9 33.5,-6 85,3.5 C136.5,13 178,63.5 154.5,88.5 Z");
transition: clip-path 0.5s cubic-bezier(0.585, 2.5, 0.645, 0.55), -webkit-clip-path 0.5s cubic-bezier(0.585, 2.5, 0.645, 0.55), background 0.5s ease;
}
.button--janus:hover::before {
background: #000;
-webkit-clip-path: path("M143,77 C117,96 74,100.5 45.5,91.5 C17,82.5 -10.5,57 5.5,31.5 C21.5,6 79,-5.5 130.5,4 C182,13.5 169,58 143,77 Z");
clip-path: path("M143,77 C117,96 74,100.5 45.5,91.5 C17,82.5 -10.5,57 5.5,31.5 C21.5,6 79,-5.5 130.5,4 C182,13.5 169,58 143,77 Z");
}
.button--janus::after {
content: '';
height: 86%;
width: 97%;
top: 5%;
border-radius: 58% 42% 55% 45% / 56% 45% 55% 44%;
border: 1px solid #000;
transform: rotate(-20deg);
z-index: -1;
transition: transform 0.5s cubic-bezier(0.585, 2.5, 0.645, 0.55);
}
.button--janus:hover::after {
transform: translate3d(0,-5px,0);
}
.button--janus span {
display: block;
transition: transform 0.3s ease;
mix-blend-mode: difference;
}
.button--janus:hover span {
transform: translate3d(0,-10px,0);
}
There are some initial button styles for all our buttons (you can simplify that if you’re just using one of them, of course). So on hover, we morph from one path to another using a bouncy timing function.
The other shape uses a fun border radius that makes it look like a blob. This button is a great example for how different techniques can create a similar look. For me, that’s the beauty of CSS — there are just so many different possibilities and never just one way to do things.
In this example, I wanted to have a border around the shape, and with a clip path that’s not possible. So, I used some goofy border radius values to create the look.
These great tools helped me do this:
- Fancy Border Radius by 9Elements for the border radius
- Clippy by Bennett Feely for creating clip paths
One word of caution when using a clip path directly on a button element: if you have some kind of focus styles around the button, they will be cut off. So it’s probably better if you use clipping on another (pseudo) element.
Another button style that I was itching to experiment with, was that rotating badge-like thing that can be seen on many sites these days. Here I used some text on a circle path in SVG with the help of the great article by Amelia Bellamy-Royds, Perfecting Paths for <textPath>.
Check out the result:
I really hope these buttons bring you some joy! Let me know if you have any questions or if you want to show me what you do with these by sending me a tweet @crnacura or @codrops!