Published on August 11, 2017.
I was working on behalf of Minimill, building a site for Albert Wenger's latest book, World After Capital. It was a simple static site: a handful of HTML pages with some shared CSS. I had finished the basic implementation, but I felt something was missing. It needed motion. The design used a small set of components across each of the pages. A blue (and sometimes white) background, a striking yellow book cover, and a consistent navigation bar in the upper right.
The home, author, talks, and FAQ pages of worldaftercapital.org.
I wanted to create animations between each page, each component morphing into different forms as the user navigates through the site. However, this presented a problem. Typically, in order to animate across page transitions on the web, you need a single page app, where all of the content and structure of the site is loaded at once and each page transition just hides (and shows) different parts of the page. My problem was, I already had a multi-page static website, and I didn't want to rewrite the entire thing to add these page transitions. As a result, I was going to have to account for a browser refresh between each page.
How it works
In order for
pangea.js to work, the web designer must first take every pair of pages, imagine a common visual state between them, and code each one in CSS. After instatiating the library on each page,
pangea.js handles the rest. When you click a link, the following happens:
- The library inspects the link's
hrefproperty, to figure out where you're trying to go.
- If the destination is a known page with a shared state, add a class to the body, triggering CSS that animates the page to the shared visual state.
- Once in the shared state, the page refresh is triggered by modifying
- On every new page, trigger entrance animations from the shared visual state to the new page.
The effect is pretty smooth:
The result is one fluid animation between pages and a hidden page refresh. (You can find the refresh by watching Chrome's URL label in the lower left corner.) By animating to and from a simple shared state and leveraging the browser's asset caching, the browser's page change often takes less than 100ms, the lower limit for human-perceptable delay.
Using the library
The first step for using
pangea.js is writing markup. In order for the library to know when a page animation is complete, simply mark an element on the page with an ID. Here, I use
Next, for each page, add styles that react to various classes being added to the
<body>. In order to achieve smooth animations, this will require one entrance animation per page from the shared state, and one exit animation to the shared state for each page the source page links to.
Finally, instantiate the
pangea.js library. On each page, register each destination page that should be tracked, the body class to trigger the animation, and the last element to animate.
As you may notice, the syntax is somewhat verbose; this is an intentional trade-off. Because there is no shared communication between pages on this type of flat HTML site, each pair of pages must be manually registered and styled. This results in a tiny package size of just 1.4KB minified and gzipped.
pangea.js logo, courtesy of Jeff Hilnbrand.
One of the tricky things about using
pangea.js is achieving the sub-100ms subsequent page load times. It was easy on worldaftercapital.org because the site was relatively lightweight. I was worried that it wouldn't scale to heavier static sites. So, when we decided to redesign Minimill's portfolio site, we made transitions a centerpiece:
Minimill's site is much heavier than World After Capital's. However, the browser does a lot of heavy lifting, creating a seamless animation between each page. In the case of the project sub-pages, they even share an image (the open laptop) which sees no flicker.
pangea.js, we essentially disable the entire library on mobile, and the site behaves as you'd expect. No animations, just regular links between HTML.
There are certainly cases where
pangea.js isn't perfect, but for flat, static websites that place a priority on performance and mobile experience, I think it's an elegant solution.
Like all of Minimill's tooling,
pangea.js is open source. Please check out the documented source, and submit an issue or pull request if you think it could work even better. Thanks in advance!