Reveal effect with clip-path
- Published • 1 min
In the navbar I’ve added a small indicator next to Posts link. I wanted to draw attention that there is a new blog post. On hover I wanted to show more information: new label (badge).
Initially I wrote it this way:
.navbar-link[data-has-new-article] {
--foreground-color: var(--color-white);
--background-color: var(--color-red-300);
position: relative;
}
.navbar-link[data-has-new-article]::after {
transition-property: width, height, border-radius, text-indent, color;
transition-duration: 150ms;
transition-timing-function: ease-in;
content: "new";
position: absolute;
display: inline-flex;
align-items: center;
width: 0.5em;
height: 0.5em;
padding: 0;
font-family: var(--body);
font-size: 0.7rem;
color: oklch(from var(--background-color) l c h / 0);
border-radius: calc(infinity * 1px);
background-color: var(--background-color);
text-indent: -50%;
}
.navbar-link[data-has-new-article]:hover::after {
content: "new";
width: 3ch;
height: auto;
padding: 0.125em 0.5em;
color: var(--foreground-color);
border-radius: 0.25rem;
transform: translateY(-0.5em);
text-indent: 0;
}
It worked, did the job, no single token was burnt. I thought then, if I have the desired state (full label), why not use masking to switch between dot indicator state and the label? Well, it worked even better. See for yourself:
.navbar-link[data-has-new-article]::after {
transition-property: clip-path;
transition-duration: 150ms;
transition-timing-function: ease-in;
clip-path: circle(0.25em at 0.25em); /* 👈 only dot is visible */
content: "new";
position: absolute;
top: -0.25em;
display: inline-block;
padding: 0.125em 0.5em;
font-family: var(--body);
font-size: 0.7rem;
color: var(--foreground-color);
border-radius: 0.25rem;
background-color: var(--background-color);
}
.navbar-link[data-has-new-article]:hover::after {
clip-path: circle(3em at 0.25em); /* 👈 full state is visible */
}
Until you hover over the link, what indicator is, is actually a top-left corner of the label.
After the change .navbar-link[data-has-new-article]:hover::after contains just one rule! It’s easier to maintain, too.
I recorded how it looked like before and after the change.