View Transitions

7-17-2023

Midway through a view transition

I've recently rewritten my entire site, breaking it up from long scrolling pages into smaller pages that use View Transitions. View Transitions are an experimental way to make an MPA (Multi Page App) feel like a SPA (Single Page App). If you're just interested in trying them out without reading further, make sure you have a chromium version higher than 115 and then enable the below flags. Otherwise, read on!

chrome://flags#view-transition

chrome://flags#view-transition-on-navigation

Background

For a long time I'd have told you that I prefer back end to front end work, but I don't think that's entirely true. I really enjoy playing with html and css; I just dislike arbitrary, bloated, kitchen sink frameworks. When free of EE design of websites, I really enjoy tinkering, and I love finding a website that feels really well designed. For this reason, I've really enjoyed occasionally poking around Tyler Gaw's website, and subscribing to his blog, which lead me to first learning about View Transitions.

His post explains View Transitions, provides a neat interactive demo, and links to another excellent blog post (that I also subscribed to through RSS). I think Tyler does some really neat, zany things with his experiments, and I could see the industry swinging back from SPA centric design to more MPAs. Inspired, and feeling like both my main site and my blog were getting too long as single pages, I decided to split my website into chunks and use view transitions to make those chunks still feel cohesive. My goal was to make my website easier to navigate, even more interactive, still fast, and still free of javascript.

To accomplish this, I decided to go the long way and address some other cleanup I wanted to do at the same time. First, I updated my blog generator app. (My main website and my blog are separate repos and projects). Originally it took a series of markdown files and stitched them together to create a single page with all articles, and even a css powered TOC (Table of Contents) popup. I gave it a new flag that would remove the TOC popup and instead make a 'main page' that acted as a year delineated full page TOC. (Inspired again by Tyler's blog, I also increased my font size, though not to as bold a size as his). Then, I started working on the main site.

For a long time, I've been using a custom 'html extender' app that let me use simple for loops and if statement directives in html, combined with json 'data files'. My app would parse my plain html pages, and then essentially do string substitution to spit out modified html, replacing my custom tags with the created html. This was all done at compile time and gave me clean, plain html for my static site.

In many of my recent hobby projects, I've been using the Kotlin DSL (Domain Specific Language) for generating html, whether backend or in javascript, and at both compile time and runtime. It's at essentially the same level of abstraction as html and feels to me very 1:1 in how it works. In the end it feels to me like simply less verbose html, while also giving me the power to do functional things: I love being able to extract out functions, make things dynamic, and loop over data. I decided to rewrite my whole website using the DSL, and it really only took a day to do the bulk of it because I could essentially copy paste from html to dsl. Once the site was rewritten, I essentially was able to move function calls around and do a small amount of wrapping to break the website into the chunks that I wanted.

Now that I had rewritten my site and broken it into multiple pages, I was ready to start playing with transitions between pages. My main goal was to create a cohesive, physical feeling "canvas". I was inspired by file trees, panning between multiple desktops, and panning a large image around to explore it (like holding a Where's Waldo book close to your face and moving it around to see all the details). My idea was that the main page of the site was "left most" on the canvas, and clicking into a sub page would always pan the site as if you were swiping it to the right. Then when you pressed the back button, you would swipe back the other direction. My hope was to make things match the clean feel I'm going for with the site, while making it feel interactive and more physical.

Challenges

Realizing my vision while using zero javascript proved trickier than I expected, and I hit a number of snags. First, the transitions were trickier to reason about than I had expected. Since I was doing page specific transitions, I realized that each new page controls the transition of both the new page coming in, as well as the old page going out. This logically makes sense but was something I had to continually hold in my head as I reasoned about changes. A number of the other challenges were made trickier by my consistently editing the wrong page or transition and then not understanding why things weren't happening as expected.

The second challenge I faced was general "jumpiness" and vertical stretch between pages. This was really thorny because it didn't seem consistent (often because of the first challenge). Much of this magically resolved itself by using a chrome version of 115 or above. Since I was on chrome 114 on my main browser, I also downloaded a beta browser, and switched back and forth for testing. The second half of this challenge was that while if you just animate the root element things are more straightforward, named elements try to morph into the same-named element on the other page. I was not able to find out how to disable that behavior (and treat it more as a replace than a morph) and that caused havoc combined with the last challenge.

The hardest challenge I faced was fairly simple in concept, hacky in execution, and thorny combined with the other challenges. When I navigate to the blog list from the main page, I want things to swipe left. However, when I navigate back to the blog list from a specific article, I want things to swipe back to the right. This means that the page should animate differently depending on where you came from. Given I am not using javascript, I had to get creative on how to solve this. (Fortunately, the blogs were the only sub-pages that were two deep, and so I only needed to solve this for this specific page).

To solve my issue, I was able to leverage only-child to detect when a named transition only existed on the new page. I made the body of both the blogs list page and each entry page have the view transition name of entry. This let me have one transition if we were coming from the home page (without the blog entry name) and another transition coming from a blog entry page (since both had the same transition name).

[data-page="blogs"]::view-transition-new(entry):only-child {

  animation: slideToLeft var(--view-transition-time);

}



[data-page="blogs"]::view-transition-new(entry) {

  animation: slideToRight var(--view-transition-time);

}

This solution is quite hacky, and may break down as view transitions continue to be iterated on. It also caused me another issue, where the named elements try to morph into each other. (I actually did the opposite of the above solution at first, naming the home page and blog list and not the entries. This was messier css and lead to a more noticeable morph issue). Because the blog list is effectively trying to morph into the blog entry, as well as panning away from it, I get an unwanted side effect. Unlike everywhere else, clicking from the blog list into an entry (and going back) also scrolls you up or down to where you were before or the top of the page. I spent a good deal of time trying to remove that behavior, but I haven't found a way to do so yet. I think it could be considered a feature, but it doesn't match my flat left/right pan vision.

Conclusion

I think I learned a lot playing with these transitions, and I certainly had fun doing so. I'm excited for these flags to someday hopefully be turned on by default, and for visitors to see such a neat little "progressive enhancement". I am tired of seeing SPAs be the default choice even when they don't make sense, and then seeing them do things like url re-writing to act more like MPAs. My hope is that things like view transitions both indicate and will empower a move back towards a world that will chose SPA or MPA depending on what makes sense, instead of blindly choosing the former. It's also fun to see that while some parts of the internet are hyping crypto or ai or whatever is next, others are steadily iterating and evolving in even things as small as how we move from one web page to another. I'm excited to see how websites will use this to evolve.