A randomly generated blobby nav created with CSS.
Has smooth anchor scrolling, uses backdrop-filter, and SVG filter. Also, has a pure CSS "off" click by resizing a label
Enjoy!
| - const randomInRange = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min | |
| - const SECTIONS = ['HOME', 'ABOUT', 'CONTACT', 'WORK'] | |
| nav.menu(style=`--hue: ${Math.random() * 360}`) | |
| input(type='checkbox', id='menu-toggle', class='menu__toggle') | |
| label(for='menu-toggle', class='menu__toggle-label') | |
| label(for='menu-toggle', class='menu__toggle-label menu__toggle-label--closer') | |
| svg.menu__icon(preserveAspectRatio='xMinYMin', viewBox='0 0 24 24') | |
| path(d='M3,6H21V8H3V6M3,11H21V13H3V11M3,16H21V18H3V16Z') | |
| svg.menu__icon(preserveAspectRatio='xMinYMin', viewBox='0 0 24 24') | |
| path(d='M19,6.41L17.59,5L12,10.59L6.41,5L5,6.41L10.59,12L5,17.59L6.41,19L12,13.41L17.59,19L19,17.59L13.41,12L19,6.41Z') | |
| ul.menu__content | |
| li.menu__item(style=`--x: ${randomInRange(15, 35)}; --y: ${randomInRange(15, 25)};`) | |
| a.menu__link(href="#HOME") HOME | |
| li.menu__item(style=`--x: ${randomInRange(45, 75)}; --y: ${randomInRange(25, 40)};`) | |
| a.menu__link(href="#ABOUT") ABOUT | |
| li.menu__item(style=`--x: ${randomInRange(15, 35)}; --y: ${randomInRange(45, 75)};`) | |
| a.menu__link(href="#CONTACT") CONTACT | |
| li.menu__item(style=`--x: ${randomInRange(65, 75)}; --y: ${randomInRange(50, 75)};`) | |
| a.menu__link(href="#WORK") WORK | |
| main | |
| for SECTION in SECTIONS | |
| section(id=SECTION)= SECTION | |
| svg(style='position: absolute; left: 100%') | |
| defs | |
| filter(id=`goo`) | |
| feGaussianBlur(in='SourceGraphic', stdDeviation='15', result='BLUR') | |
| feColorMatrix(in='BLUR', mode='matrix', values='1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 18 -7', result='GOO') | |
| feBlend(in='SourceGraphic', in2=`goo`) |
| // 404 |
| @import url('https://fonts.googleapis.com/css?family=Alata&display=swap') | |
| * | |
| box-sizing border-box | |
| :root | |
| --speed .85 | |
| --primary hsl(0, 0, 100%) | |
| --size 30 | |
| --ease cubic-bezier(0.175, 0.885, 0.32, 1.275) | |
| body | |
| background #fafafa | |
| font-family 'Alata', sans-serif | |
| min-height 100vh | |
| overflow-x hidden | |
| padding 0 | |
| main | |
| height 100vh | |
| overflow-y scroll | |
| scroll-behavior smooth | |
| scroll-snap-type y mandatory | |
| section | |
| align-items center | |
| display flex | |
| font-size 3rem | |
| height 100vh | |
| justify-content center | |
| scroll-snap-align center | |
| width 100vw | |
| .menu | |
| position fixed | |
| &__toggle | |
| opacity 0 | |
| position absolute | |
| &:checked | |
| & ~ .menu__content .menu__item | |
| --active-x var(--x) | |
| --active-y var(--y) | |
| --scale 1 | |
| & ~ .menu__toggle-label:not(.menu__toggle-label--closer) | |
| --clip circle(1000% at 0% 0%) | |
| height 100vh | |
| width 100vw | |
| backdrop-filter blur(10px) | |
| & ~ .menu__toggle-label .menu__icon | |
| &:nth-of-type(1) | |
| --scale 0 | |
| &:nth-of-type(2) | |
| --scale 1 | |
| &__toggle-label | |
| cursor pointer | |
| height calc(var(--size, 20) * 0.5vmin) | |
| width calc(var(--size, 20) * 0.5vmin) | |
| display block | |
| --clip circle(100% at 0% 0%) | |
| -webkit-clip-path var(--clip) | |
| clip-path var(--clip) | |
| position absolute | |
| top 0 | |
| left 0 | |
| transition backdrop-filter calc(var(--speed, 1) * 1s) var(--ease), clip-path 0s, -webkit-clip-path 0s | |
| &--closer | |
| z-index 3 | |
| --scale 0 | |
| &__icon | |
| --scale 1 | |
| height calc(var(--size, 20) * 0.25vmin) | |
| width calc(var(--size, 20) * 0.25vmin) | |
| position absolute | |
| top 50% | |
| left 50% | |
| transform translate(-70%, -70%) scale(var(--scale, 1)) | |
| &:nth-of-type(2) | |
| --scale 0 | |
| fill var(--primary) | |
| transition all calc(var(--speed, 1) * 1s) var(--ease) | |
| &__content | |
| background 'hsl(%s, 50%, 50%)' % var(--hue, 0) | |
| margin 0 | |
| display block | |
| list-style-type none | |
| z-index -1 | |
| filter url("#goo") | |
| position absolute | |
| top 0 | |
| height 0 | |
| width 0 | |
| left 0 | |
| z-index 2 | |
| &:after | |
| background 'hsl(%s, 50%, 50%)' % var(--hue, 0) | |
| content '' | |
| border-radius 50% | |
| transform translate(-50%, -50%) | |
| position absolute | |
| height calc(var(--size, 20) * 1vmin) | |
| width calc(var(--size, 20) * 1vmin) | |
| top 0 | |
| left 0 | |
| &__item | |
| background 'hsl(%s, 50%, 50%)' % var(--hue, 0) | |
| border-radius 50% | |
| cursor pointer | |
| display flex | |
| list-style-type none | |
| font-size 1rem | |
| height calc(var(--size, 20) * 1vmin) | |
| left calc(var(--active-x, 0) * 1vw) | |
| overflow hidden | |
| place-items center | |
| position absolute | |
| text-align center | |
| top calc(var(--active-y, 0) * 1vh) | |
| transform translate(-50%, -50%) scale(var(--scale, 0.75)) | |
| transition all calc(var(--speed, 1) * 1s) calc(var(--delay, 0) * 1s) var(--ease) | |
| width calc(var(--size, 20) * 1vmin) | |
| @media(min-width 768px) | |
| font-size 3rem | |
| &:nth-of-type(1) | |
| --delay .1 | |
| --x 35 | |
| --y 35 | |
| &:nth-of-type(2) | |
| --delay .2 | |
| --x 65 | |
| --y 35 | |
| &:nth-of-type(3) | |
| --delay .3 | |
| --x 35 | |
| --y 65 | |
| &:nth-of-type(4) | |
| --delay .4 | |
| --x 65 | |
| --y 65 | |
| &__link | |
| align-items center | |
| color white | |
| cursor pointer | |
| text-decoration none | |
| font-weight bold | |
| text-align center | |
| display flex | |
| justify-content center | |
| height 100% | |
| width 100% | |
| &:hover | |
| text-decoration underline |