RSS FeedTwitterMastodonShare IconHeart IconGithub IconArrow IconClock IconGUI Challenges IconHome IconNote IconBlog IconCSS IconJS IconHTML IconMedia IconGit IconSpeaking IconTools Icon
setInterval(() => {
  document.startViewTransition(() => {
  h1.textContent = word[index++]
})}, 500)
My google avatar.

Text Replace Transitions

6 min read

First up, the good stuff, the final demo, as if you skipped to the end.

If that's basically an error message about support, here's a recording of it running in Canary (with this flag enabled 😉.

view-transition's let me, with CSS, describe how to dismiss the old text state and reveal the new text state.

The inspo #

This demo idea came from the game Session Skate. In the opening credits, "SESSION" has each letter rapidly cross fade. It looked pretty coo and I instantly realized I could do this with view-transition's, setInterval(), and .textContent. So I sent myself the email todo, cuz well, it was time to land a sick trick, not work.

That turned into a small prototype. Peep these barebones!

setInterval(() => {
  document.startViewTransition(() => {
    h1.textContent = word[index++]
    if (index >= word.length) index = 0
}, 500)
  1. Every half a second
  2. Take a quick "before" snapshot
  3. Set some new text content

When the work finishes in that view transition callback, the browser interpolates between the changes for you, for free. In our case, there was a "V", now there's an "i". One letter disappeared, one letter appeared. We get a crossfade!

There. We matched the video game.

Customizing the transition; aka spinkling props #

Crossfades are coo (fo real y'all), but what if I want to customize how the text swaps? Perhaps with some Open Props?

No prob 🤘💀

First thing, @import the easings and animations:

@import "";
@import "";

Next, as an optimization, tell the whole page to chill and not transition when a document transition snapshot is requested.

html {
  view-transition-name: none;

Now that we said what we dont want to transition, let's specify what should, the h1!

h1 {
  /* be stable. fix that width. */
  inline-size: 1em;
  /* required for view-transitions  
     now it's not the whole page */
  contain: layout;
  /* yo browser; transition this! */
  view-transition-name: replace-effect;

Remember that view-transition-name, we'll be able to reference its before and after states in the next section.

Now for the best part #

Use some of these props to orchestrate the exit and entry of a character / the DOM snapshots. Let's start with how the old character should exit; let's see, I want it to scale out, like away from me, and fade out at the same time.

@media (prefers-reduced-motion: no-preference) {
  html::view-transition-old(replace-effect) {

Delightful magic.
Now for the element entering; fade it in while sliding it up!

@media (prefers-reduced-motion: no-preference) {
  html::view-transition-new(replace-effect) {
    z-index: 1;
      var(--animation-fade-out) reverse,
the fade-out animation is reversed so opacity doesn't need set to 0.

Mix and match animation props in that Codepen and have some fun 🙂

outro #

Fun Stuff!.

Make a DOM change, describe how to transition the changes. Love it.

Hope this gets picked up by other browsers 🤞 Peep the spec.

Mentions #

Join the conversation on

  • Thomas Broyer
  • Thomas Broyer
  • حمد بنقالي | 🇸🇦X7md
  • Stef Walter
  • Jake Archibald
  • nereo perez
  • Elijah Manor
  • Ryuno-Ki
  • shimon
  • Geoff Rich
  • Віталій Бобров 🇺🇦💗🛡️⚔️
  • David McCormick
  • John Morton
  • Robbie
  • Elly Loel ✨🌱
  • Abubakar Habib
  • John bartz
  • Vegard Andreas Larsen 🇳🇴
  • az_kecil
  • Valdie Setiawan, (Ini Gelar)
  • k l e o v 🐢💙
  • たんしお
  • Felix Ochoa
  • Lucas
  • Gaideh
  • GibyCode
  • Zee Welc
  • André Pinto
  • I Made Budi Surya Darma
  • Sean Birmingham
  • Hanzo.Hasashi
  • Pedro picapiedra
  • Jamal
  • Socheat Sok
  • Yerzhan Utelbayev

@argyleink nice write-up, thanks

David McCormickDavid McCormick

@argyleink Good to see you here on Mastodon!

Thilo MaierThilo Maier

CSS hyphenation support is pretty good — just a -webkit- prefix left for Safari I’d love to see them yank off. Toss it on a parent, let it cascade, and you’ll see text hug the ragged edge a little closer and a little more consistently. You don’t have to use it, it’s a bit of an aesthetic choice.

I was thinking about this because I saw Hyphenopoly.js — a polyfill for hyphenation in JavaScript that’s come out in the last few months. I kinda don’t get it with the browser support being so good, but it does work in Node which might be interesting, and I suppose this would be extensible to written languages where hyphenation isn’t supported yet.

Update from Mathias Nater:

Hyphenopoly.js came out 2018 and its predecessor – Hyphenator.js – around 2008, some time before hyphens:auto; was available.
There are still many languages that are not supported natively in all browsers.

Hyphenopoly.js supports 72 languages and, yep, it is extensible: we’ll just need hyphenation patterns (the same patterns TeX uses) or a huge list of pre-hyphenated words where I can compute the patterns from.

(I was under the impression it had just come out in the last few months!)

There is a ton more to the CSS art of controlling where words break through. One of the most comprehensive reads on the subject is Will Boyd’s Deep Dive into Text Wrapping and Word Breaking.


While we’re on type for a second, I do need you to know that Stabby exists:

More good news (in a sec). You know how the content of a page can shift around when a custom font loads after a fallback font has rendered? This is one of the great tradeoffs of display websites right now. Delay rendering until the custom font is ready means no layout shift (good!), but then you’re… delaying rendering (bad!). To my great surprise, the web has shifted toward not delaying rendering, largely thanks to CSS’ font-display: swap;

It is possible to have your cake and eat it too have non-shifting custom font loading without delayed rendering through CSS trickery. It involves using a font loader so that you know when the custom font loads and can adjust CSS to make sure none/little layout shift happens. The tricks were adjusting things like font-size, letter-spacing, and those classics.

The good news is that that old slightly hacky way of dealing with font fallbacks is out and a new school way of dealing with font fallbacks is in. Here’s Katie Hempenius’ recent article:

This article is a deep dive into font fallbacks and the size-adjust, ascent-override, descent-override, and line-gap-override APIs. These APIs make it possible to use local fonts to create fallback font faces that closely or exactly match the dimensions of a web font. This reduces or eliminates layout shifts caused by font swapping.

Improved font fallbacks

Four new things just for fallbacks! Wow. Say you’re loading a custom font called Poppins, it ends up looking like this:

  font-family: Poppins, "fallback for poppins";

  font-family: "fallback for poppins";
  src: local("Times New Roman");
  ascent-override: 105%;
  descent-override: 35%;
  line-gap-override: 10%;

My brain immediately went uhmmmmm wouldn’t these metrics totally depend on the combination of the custom font and the fallback font? Apparently not though!

Because font metric overrides are calculated using measurements that come from the metadata of the web font (and not the fallback font), they stay the same regardless of which font is used as the fallback font.

That’s really great. So you can basically figure out (or look up) the overrides for your custom font, put them in place, and you’re straight up good to go. That’s a good API.

Welp I didn’t really intend for this whole issue to be about typography stuff, but here we are. You gotta see Adam Argyle’s Text Replace Transitions!

You could code any number of ways. But Adam did it using the new View Transitions API (so you’ll only be able to see the demo in Chrome Canary). It’s such a fun way to play with animating things because the API is so tidy: call document.startViewTransition, change the DOM, let it animate (control with CSS if you want). Hopefully, the CSS properties will be all that is needed entirely from cross-page View Transitions (I think that’s the case, I just haven’t seen it really work well yet).

The post Chris’ Corner: More Like Hypography appeared first on CodePen Blog.

8 total views

Member of a CSS Webring

Try a site in the ring!