Blog

CSS Experimental

Debugging in public

October 3, 2025 by Cyd Stumpel Reading time: 2 minutes

During prototyping my ideas for next year’s ‘new year, new portfolio’ I came upon an interesting limitation in keyframes in combination with custom properties (CSS variables).

I was prototyping an idea to translate navigation tabs to the right on scroll and to let them reappear on hover.

I didn’t really like the user experience to be honest, so it will probably not make the final cut in next year’s portfolio, but the experiment is interesting regardless.

Link to:

The issue

I created keyframes that translate items to the right based on scroll position, in those same keyframes I was changing a custom property from 0 to 1 to use in a hover selector to animate them to the original position.

@property --scroll-progress {
	syntax: "<number>";
	inherits: true;
	initial-value: 0;
}

.cards {
  &:hover {
		.card {
			translate: calc(-10vw * var(--index) * var(--scroll-progress));
		}
	}

	.card {
		--scroll-progress: 0;
		animation-timeline: scroll();
		animation-name: move-right-2;
		animation-range: var(--header-scroll-range);
		animation-timing-function: var(--default-ease);
		animation-fill-mode: both;
		z-index: var(--index);
	}
}

@keyframes move-right {
	from {
		transform: translateX(0);
		--scroll-progress: 0;
	}
	to {
		transform: translateX(calc(10vw * var(--index)));
		--scroll-progress: 1;
	}
}
CSS

NB I opted for a css variable to get the index of the element here, because sibling index is not well supported enough, yet.

But what actually happened on hover was that the items jumped straight to the end point, despite the transition I had added.

I tried multiple things, like checking if the transition would work if I used a non variable value like 0.5 in the translate in stead of the custom property (this did work), changing the syntax property to other values and much more.

I turned to Bluesky for help and Nathan Knowler suggested the correct fix; to in stead of setting the keyframes to change the --scroll-progress variable on the same item as the transform keyframes, set it on a different element, using the same scroll range. The fix is updated in my codepen.

Link to:

It works, we’re done, right?

False! Because that got me thinking; why??? And I don’t have the answer yet, so please let me know if you do.

I did try a couple more things in codepen, so I know a couple of things it’s not:

  • The reason it didn’t work isn’t related to multiple items having the same keyframes and updating the custom property, because setting the keyframes on a direct parent of any of the items did work.
  • The issue is not with scroll driven animations; it’s all keyframes that have this limitation (see the last example in my codepen).
  • Setting the @property syntax declaration to other syntaxes had no effect.
  • Setting the scroll translation as a CSS variable as well had no effect on the hover effect not working.

Cyd Stumpel

Cyd is a Freelance Creative Developer and teacher from Amsterdam. She teaches at the Amsterdam University of Applied Sciences and occastionally speaks at conferences and meetups.

Last updated: October 3, 2025

4 Webmentions

Join the conversation on Bluesky Bluesky

Reposts 1

Jordan Marcon Bluesky Bluesky

Jordan Marcon

View source

Webmentions are a way to connect with other people who have shared your work.