- let r = 9;
svg(aria-hidden='true' width='0' height='0')
filter#blob(color-interpolation-filters='sRGB'
y='-100%' height='300%')
// extract highlight out of red channel and paint it blue
feColorMatrix(values=`0 0 0 0 .12
0 0 0 0 .53
0 0 0 0 .9
1 0 0 0 0`)
// blur the highlight - this does two things:
// 1. makes edge pixels semitranparent
// 2. rounds corners
feGaussianBlur(stdDeviation=r)
// slighly shrink it horizontally
// so we'd have a bit of a gap between the highlights
// if every single nav item was highlighted
feMorphology(radius='4 0')
// push alpha of most semitransparent pixels to either 0 or 1
// save for a few pixels with alphas close to .5
// this ives us a blob with smooth edges
feComponentTransfer(result='baseblob')
feFuncA(type='table' tableValues=[-r, r + 1].join(' '))
// extract text & paint it differently based on
// whether it's hovered (on the green channel)
// or not (on the blue channel)
feColorMatrix(in='SourceGraphic'
values=`0 .12 .27 0 0
0 .53 .32 0 0
0 .89 .39 0 0
0 1 1 0 0` result='basetext')
// intersect this text with the blob obtained before
feComposite(in='baseblob' operator='in')
// paint this intersection white
feColorMatrix(values=`0 0 0 0 1
0 0 0 0 1
0 0 0 0 1
0 0 0 1 0`)
// put the blob underneath it
feBlend(in2='baseblob')
// and the initial text underneath all else
feBlend(in2='basetext')
nav(style='--k: 0')
a(href='#' style='--i: 0' data-ico='🏠') home
a(href='#' style='--i: 1' data-ico='📖') about
a(href='#' style='--i: 2' data-ico='🗨️') contact
a(href='#' style='--i: 3' data-ico='🌟') store
View Compiled
@import url('https://fonts.googleapis.com/css2?family=Inter&display=swap');
@property --k {
syntax: '<number>';
initial-value: 0;
inherits: true
}
html, body { display: grid }
html { min-height: 100% }
body { background: #040404 }
svg[aria-hidden='true'] { position: fixed }
nav, a { display: flex }
nav {
place-self: center;
filter: url(#blob);
transition: --k .35s cubic-bezier(.32, 1, .68, 1)
}
a {
--sgn: clamp(-1, var(--i) - var(--k), 1);
--bit: round(.5*(1 + var(--sgn)));
--out: max(-1*var(--sgn), var(--sgn));
--sel: calc(1 - var(--out));
--col: #00f;
gap: .375rem;
position: relative;
padding: 0 1.25rem;
background: #000;
color: var(--col);
font: 1.125em/ 2.25 inter, sans-serif;
text-decoration: none;
text-transform: capitalize;
isolation: isolate;
&::before {
background: var(--col) text;
color: #0000;
content: attr(data-ico)
}
&::after {
--r: calc(var(--out)*var(--bit)*100%);
--l: calc(var(--out)*(1 - var(--bit))*100%);
position: absolute;
inset: 1px 0;
background: #f00;
mix-blend-mode: lighten;
clip-path: inset(0 var(--r) 0 var(--l));
content: ''
}
&:hover, &:focus { --col: #0f0 }
&:focus { outline: none }
@supports (scale: Abs(-5)) { --out: abs(var(--sgn)) }
}
View Compiled
addEventListener('click', e => {
let _t = e.target;
if(_t.href) {
_t.parentNode.style.setProperty('--k', +_t.style.getPropertyValue('--i'))
}
})
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.