CSS-lab · Knoppen
Pijl-knop met schuivende cirkel
Een pill-knop met een ronde pijl rechts die bij hover uitgroeit tot de hele knop vult, terwijl het label van kleur wisselt.
- Gemiddeld
- Pure CSS
- MIT-licentie
::beforewidth transitionisolationcubic-bezierinline SVG
<div class="pk-wrap">
<a href="#" class="pk-btn">
<span class="pk-label">Plan een kennismaking</span>
<span class="pk-arrow" aria-hidden="true">
<svg viewBox="0 0 24 24" focusable="false"><path d="M5 12h14M13 6l6 6-6 6" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/></svg>
</span>
</a>
<a href="#" class="pk-btn pk-btn--violet">
<span class="pk-label">Bekijk cases</span>
<span class="pk-arrow" aria-hidden="true">
<svg viewBox="0 0 24 24" focusable="false"><path d="M5 12h14M13 6l6 6-6 6" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/></svg>
</span>
</a>
</div>/* Pijl-knop met schuivende cirkel - prefix .pk- */
.pk-wrap {
display: flex;
flex-wrap: wrap;
justify-content: center;
gap: 20px;
}
.pk-btn {
--accent: #C6FF3D;
--ink: #0C0C0D;
--paper: #F9F8F6;
--dot: 46px;
--pad: 6px;
--speed: 0.55s;
--ease: cubic-bezier(0.7, 0, 0.2, 1);
position: relative;
isolation: isolate;
display: inline-flex;
align-items: center;
min-height: calc(var(--dot) + var(--pad) * 2);
padding: 0 calc(var(--dot) + var(--pad) * 2 + 14px) 0 28px;
font: 600 1.02rem/1 system-ui, sans-serif;
color: var(--paper);
text-decoration: none;
border: 1.5px solid rgba(249, 248, 246, 0.3);
border-radius: 999px;
overflow: hidden;
transition:
color var(--speed) var(--ease),
border-color var(--speed) var(--ease);
}
.pk-btn--violet {
--accent: #9B5CFF;
}
/* De cirkel: groeit vanaf rechts naar de volle breedte */
.pk-btn::before {
content: "";
position: absolute;
z-index: -1;
top: var(--pad);
right: var(--pad);
bottom: var(--pad);
width: var(--dot);
border-radius: 999px;
background: var(--accent);
transition: width var(--speed) var(--ease);
}
/* Pijl ligt altijd boven op de cirkel */
.pk-arrow {
position: absolute;
top: 50%;
right: var(--pad);
display: grid;
place-items: center;
width: var(--dot);
height: var(--dot);
color: var(--ink);
transform: translateY(-50%);
}
.pk-arrow svg {
width: 20px;
height: 20px;
transition: transform var(--speed) var(--ease);
}
/* Hover en focus: vullen, kleur wisselen, pijl draaien */
.pk-btn:hover,
.pk-btn:focus-visible {
color: var(--ink);
border-color: var(--accent);
}
.pk-btn:hover::before,
.pk-btn:focus-visible::before {
width: calc(100% - var(--pad) * 2);
}
.pk-btn:hover .pk-arrow svg,
.pk-btn:focus-visible .pk-arrow svg {
transform: rotate(-45deg);
}
.pk-btn:focus-visible {
outline: 2px solid var(--accent);
outline-offset: 4px;
}
@media (prefers-reduced-motion: reduce) {
.pk-btn,
.pk-btn::before,
.pk-arrow svg {
transition: none;
}
}Wat het is en waar je het gebruikt
Deze pill-knop begint ingetogen: een dunne rand, lichte tekst en rechts een gekleurde cirkel met een pijl. Beweeg je eroverheen, dan groeit die cirkel naar links uit tot hij de hele knop vult. Het label wisselt tegelijk van licht naar donker en de pijl draait een kwartslag omhoog. De knop voelt daardoor alsof hij naar je toe komt.
Het patroon past goed bij secundaire en primaire acties in donkere interfaces: een kennismaking plannen, een case bekijken of door naar een volgende stap. In de demo staan twee varianten naast elkaar, in acid lime en in sunset violet.
Zo werkt het
- De gekleurde vulling is het pseudo-element
.pk-btn::before. Het staat metposition: absoluterechts in de knop en heeft standaard de breedte van de cirkel (var(--dot)). - Bij
:hoveren:focus-visiblewordt de breedtecalc(100% - var(--pad) * 2). Omdat het element aan de rechterkant vastzit, groeit het naar links. Dankzijborder-radius: 999pxblijft het een pil tijdens de hele beweging. isolation: isolateop de knop zorgt dat dez-index: -1van de vulling binnen de knop blijft en niet achter de pagina verdwijnt. Het label ligt er dus altijd boven.- De pijl is een inline SVG met
stroke="currentColor"in een eigen laag. Die draait mettransform: rotate(-45deg). - Eén gedeelde easing in
--easelaat vulling, kleur en pijl als één beweging aanvoelen.
Aanpassen
De variabelen staan op .pk-btn. --accent is de kleur van cirkel en vulling, --ink de donkere tekstkleur na hover en --paper de lichte tekstkleur in rust. --dot bepaalt de grootte van de cirkel en daarmee de hoogte van de knop. --pad is de ruimte tussen cirkel en rand. Met --speed en --ease stel je het karakter van de beweging in. De modifier .pk-btn--violet laat zien hoe je met één regel een variant maakt.
Toegankelijkheid en browsersupport
Het zijn echte links met zichtbare tekst. De SVG en de cirkel zijn decoratief en hebben aria-hidden="true". Toetsenbordgebruikers krijgen hetzelfde effect via :focus-visible, plus een outline in de accentkleur. Donkere tekst op acid lime of violet en lichte tekst op carbon hebben allemaal voldoende contrast. Met prefers-reduced-motion verandert de staat direct, zonder groei- of draaibeweging. Het animeren van width is minder zuinig dan transform, maar voor één knop is dat geen probleem. Het werkt in alle actuele browsers.
Verder lezen
Meer ideeën voor hover-states vind je in ons artikel over CSS-knoppen en hover-effecten. Wil je zulke interacties op je eigen site? Bekijk onze aanpak voor interactief webdesign.
Meer knoppen
