Skip to content

By Cody Olsen

Published

Turns out, it was just CSS all along.

At Sanity we love spinners, perhaps too much. To be fair, when you make real-time content applications that are very API intensive, you often need UX affordances to tell folks that stuff is indeed happening.

We even commemorate failed spinners, like the beloved “Mister Spinny” that made their way into our company Slack:

When I joined Sanity, the love for spinners is one of the reasons I felt right at home. I was even briefly a spinfluencer on Instagram a decade ago:

In the time of writing post, half the Studio team are away in Brooklyn for Everything NYC, and so there were more room for banter in the daily standup.

We talked about how my teammate Ash prefers to use Safari as his daily driver, and it launched me into a rant about how I stopped using it after I failed to solve the wobbly spinner that only happens in WebKit browsers:

You'll get dizzy if you look at these for too long

This is not a “me” probem, nor is it new or uncommon. Here’s a sample with folks struggling with the same thing:

The usual suggested fixes were raised as we dove into the rabbit hole together, like setting will-change: transform to put the spinner on the GPU etc etc, to no avail (of course, if these fixes worked I would have PR-ed a fix long ago and still use Safari):

During our conversation, we dug deeper and I started to think aloud about how the root of the issue is in how Safari handles sub-pixels when rendering SVGs with rotate() in CSS.

For the render to be stable, you need dimensions that are even so that they neatly divide by 2. A hard problem to solve since spinners in our products need to follow our icon convention of having height and width set to 1em in order to look right next to whatever text it’s placed with. That leaves hard coded pixel values off the table.

Ash pointed out “Oh that’s interesting, I wonder if the new CSS round() function could solve that“.

I guess I skipped my weekly CSS homework, because that function is new to me, so I gave it a shot:

All the attempts, ending with the one that worked

It bloody worked!

Look up "bliss" in the dictionary and you will probably see this

Look at this hand-made PR that no agent touched in the year of 2026, a rare sight!

const size = 'round(1em, 2px)'
export const spinnerIcon = style({
  animation: `${rotate} 500ms linear infinite`,
  // Prevents a wobbly spinner on Safari
  height: size,
  width: size,
})

Fable 5.1 couldn’t hack it, Astra 6 gave up, Muse Spark 1.3 got lost in the weeds.

I guess that…

Sometimes the best way to solve a problem is for clever humans to hash it out.

And that’s coming from someone who burned 2.6B tokens last Thursday, so it’s making me a little nostalgic:

Diagrams showing agent and model use for Cody Olsen

Ash knew this because he keeps up with the technology we’re asking our agents to use. So this a good example that it can pay off to keep up with “the boring parts” of the platform, and for standups to have room for banter in them.

Turns out…

Of course, a week after drafting this post, Apple came out with their operating system updates and the wobbliness is fixed in the newer versions of Safari on MacOS 27 (still wobbly on iOS 27) . I guess they (finally) read up on CSS too 😇.

Acknowledgements

Thanks to Ash Stevens for the idea for the solutions, and to Knut Melvær for getting this post out. And to the Safari team at Apple for making us feel clever for a week.


Published:


Cody Olsen

Cody Olsen

Principal Software Engineer

Sanity


Discussion

This post is being discussed on Bluesky. Reply there and your comment shows up here.

Loading discussion…

More from Engineering

cd ..