.container__wrapper
  .container
    h1.motion(data-splitting='') Meander
View Compiled
*
  box-sizing border-box

body
  min-height 100vh
  display flex
  align-items center
  justify-content center
  background hsl(0, 0%, 15%)

:root
  --coefficient 1.25

.container__wrapper
  height 75vmin
  width 75vmin
  padding 5vmin

.container
  height 100%
  width 100%
  position relative

.motion
  font-weight bold
  font-size 5vmin
  font-family sans-serif
  .char
    offset-path path(var(--path))
    position absolute
    color 'hsl(%s, 80%, 50%)' % calc((360 / var(--char-total)) * var(--char-index))
    top 0
    left 0
    animation travel 10s -8s infinite ease alternate

@keyframes travel
  from
    offset-distance calc((var(--char-index) * var(--coefficient)) * 1%)
  to
    offset-distance calc((100 - ((var(--char-total) - var(--char-index)) * var(--coefficient))) * 1%)
View Compiled
const { Meanderer, Splitting } = window

Splitting()

const path =
  'M-44.2 285.7s322.4 166.3 398.8 55c30.1-43.8-30.5-139.8 78.4-142.9 298-8.5-202.5 280.5-5.3 371.2 320 147.2 31.6-586 328-543.5C957 54.4 571.3 503.2 766.3 491.9c195-11.3-3-207.9 154.2-217.7 338-21.1-239.6 333.4 111.2 341.7 391.9 9.3-193.4-489.2 168.5-604 283.5-90 24.8 372.8 246.5 194.2 189-152.2 228.8-127.4 305.4-8.3 76.3 118.7 59.6 160.4-60.5 188.3-84.6 19.6-559.4-165.6-415 54.4 236.7 360.7 394.6 153.4 521.6 56'
const width = 1798.5
const height = 644.8

const RESPONSIVE_PATH = new Meanderer({
  path,
  width,
  height,
})

const CONTAINER = document.querySelector('.container')

const UPDATE = () => {
  const NEW_PATH = RESPONSIVE_PATH.generatePath(
    CONTAINER.offsetWidth,
    CONTAINER.offsetHeight
  )
  CONTAINER.style.setProperty('--path', `"${NEW_PATH}"`)
}

const OBSERVER = new ResizeObserver(UPDATE)
OBSERVER.observe(CONTAINER)
View Compiled

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://unpkg.com/meanderer@0.0.1/dist/meanderer.min.js
  2. https://unpkg.com/splitting@1.0.0/dist/splitting.min.js