Designing empty states
What to show before there is anything to show.
An accent bar grows along the bottom edge from the left and leaves to the right when you move away. Swapping transform-origin between the two states gives it that direction.
Also known as: card bottom border animation, accent bar on hover, underline card hover.
What to show before there is anything to show.
<article class="hfx-card-bottom-bar"> <span class="hfx-card-bottom-bar-eyebrow">Guide</span> <h3>Designing empty states</h3> <p>What to show before there is anything to show.</p> </article>
.hfx-card-bottom-bar {
--c: var(--hfx-color, #3b82f6);
font-size: var(--hfx-size, 16px);
width: 15em;
border-radius: 0.75em;
overflow: hidden;
background: #fff;
border: 1px solid color-mix(in srgb, #000 10%, transparent);
color: #1f2937;
font-family: system-ui, sans-serif;
position: relative;
box-sizing: border-box;
width: 14em;
padding: 1.1em 1.2em 1.25em;
transition: background-color 0.35s ease;}
.hfx-card-bottom-bar:hover { background: color-mix(in srgb, var(--c) 5%, #fff); }
.hfx-card-bottom-bar::after {
content: "";
position: absolute;
inset: auto 0 0;
height: 0.22em;
background: var(--c);
transform: scaleX(0);
transform-origin: 100% 50%;
transition: transform 0.45s cubic-bezier(0.65, 0, 0.35, 1);
}
.hfx-card-bottom-bar:hover::after {
transform: scaleX(1);
transform-origin: 0 50%;
}
.hfx-card-bottom-bar-eyebrow {
font-size: 0.62em;
font-weight: 700;
letter-spacing: 0.12em;
text-transform: uppercase;
color: var(--c);
}
.hfx-card-bottom-bar h3 {
margin: 0.35em 0 0.3em;
font-size: 1em;
font-weight: 600;
transition: color 0.3s ease;
}
.hfx-card-bottom-bar:hover h3 { color: var(--c); }
.hfx-card-bottom-bar p {
margin: 0;
font-size: 0.8em;
line-height: 1.45;
color: #6b7280;
}
@media (prefers-reduced-motion: reduce) {
.hfx-card-bottom-bar, .hfx-card-bottom-bar *, .hfx-card-bottom-bar::before, .hfx-card-bottom-bar::after, .hfx-card-bottom-bar *::before, .hfx-card-bottom-bar *::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
}The same effect using Tailwind utility classes. No custom CSS or config needed.
<article class="group relative w-56 overflow-hidden rounded-xl border bg-white p-5 transition-colors duration-300 hover:bg-blue-50/50"> <span class="text-[10px] font-bold uppercase tracking-widest text-blue-500">Guide</span> <h3 class="mt-1 font-semibold transition-colors group-hover:text-blue-500">Designing empty states</h3> <p class="mt-1 text-sm text-gray-500">What to show before there is anything to show.</p> <span class="absolute inset-x-0 bottom-0 h-1 origin-right scale-x-0 bg-blue-500 transition-transform duration-500 group-hover:origin-left group-hover:scale-x-100"></span> </article>
--hfx-color on the element or a parent.
Currently previewing #3b82f6.--hfx-size. Every other dimension is in
em, so the whole thing scales together. Currently previewing 16px.transition or animation
shorthand. Staggered delays are relative, so they keep their rhythm.