<div class="container">
<h2 data-splitting>I am animating on a path</h2>
</div>
@import url("https://fonts.googleapis.com/css?family=Inconsolata:700");
* {
box-sizing: border-box;
}
body {
min-height: 100vh;
background-color: black;
display: flex;
align-items: center;
justify-content: center;
flex-wrap: wrap;
color: coral;
padding: 2rem;
overflow-x: hidden;
}
.container {
max-width: 100%;
width: 80rem;
}
h2 {
position: relative;
font-family: Inconsolata, monospace;
font-size: 1.8rem;
text-transform: uppercase;
// Dimensions of original path
width: 515px;
height: 168px;
transform: scale(var(--x, 1));
transform-origin: var(--o, center);
margin: 0 auto;
}
.char {
--i: calc(50% / var(--char-total));
offset-path: path('M.4 84.1s127.4 188 267.7 0 247.3 0 247.3 0');
offset-distance: calc(var(--char-index) * 1.2rem);
position: absolute;
animation: move 1500ms infinite alternate forwards var(--delay, 0ms);
}
@keyframes move {
100% {
--i: 2rem;
offset-distance: calc((var(--char-index) * 1.2rem) + 12rem);
}
}
View Compiled
const container = document.querySelector('.container')
const split = Splitting({
whitespace: true
})
const update = () => {
const { el } = split[0]
const originalPathWidth = el.clientWidth
const originalPathHeight = el.clientHeight
const m = container.clientWidth / originalPathWidth
const containerLeft = container.getBoundingClientRect().left
const elLeft = el.getBoundingClientRect().left
// If same width, do nothing
if (m === 1) return
// Scale
el.style.setProperty('--x', m)
// Set transform origin
if (container.clientWidth < originalPathWidth) {
el.style.setProperty('--o', 'left')
} else {
el.style.setProperty('--o', 'center')
}
}
const observer = new ResizeObserver(update)
observer.observe(container)
This Pen doesn't use any external CSS resources.