Launching Calypso

Today we announced a new dashboard we’ve been working on for some time at Automattic. We’ve codenamed it Calypso, and it’s written entirely in JavaScript and powered by the API. It’s being used by millions of people as the new, and it’s completely open source.

Calypso has been more than eighteen months in the making, and I’m proud of everyone who has played a part in bringing it to life. We’ve worked together through all the ups and downs that come along with a fundamental change to the way we work.

On a personal level, building Calypso has been an incredible experience as project lead. I’ve learnt a ton. Working out how we communicate effectively, organize cross-team goals, and plan and strategize around this project at Automattic has been (and remains) a wonderful challenge. I still have much more to learn, and I hope to write about a few of the challenges now that we’ve shared the project with you. If you’re interested in the project backstory I’ve written about how Calypso came to be on the developer site.

There are some great posts talking about the launch, I really love Matt’s take on the project and the philosophy behind it all. Here are some others from today:

JavaScript Swipe Cards UX

When using the web we’re all used to the classic scrolling experience, where we scroll a long page until we reach the end or get bored. What if instead we scrolled screen-by-screen like some of the best native reader apps?

I worked on a proof of concept JavaScript card swiping UX that offers a similar level of performance as a native app. Each card can be swiped both up and down, and will respond with precision to dragging and quick swipes. This is using many of the same techniques as the pull down to refresh UX, and again uses hammer.js for the drag events.

Browser native scrolling has been disabled, so you are only swiping between a single full width and height card each time. Since it’s a proof of concept it’s only limited to three cards that you can loop through infinitely. In a real world application of this it could be extended to add true infinite scrolling through cards, handling memory usage by adding and removing card elements from the DOM when off screen.

This UX would lend itself well to a news reader interface (a la Flipboard), or in a scenario where you have a few screens of related content. I think combining this UX with the pull down to refresh UX, you’ll have the base for an interesting web reader that could perform similarly to a native app reader. I intend to experiment and iterate on these techniques further, and see how well they can interact together.

View on GitHub | Try a Demo

JavaScript Pull to Refresh for the Web

Across many native mobile apps you’ll see an interaction that allows you to pull down a list to refresh its contents. This is commonly know as “pull to refresh”, and I set out to try and build a native-like JavaScript equivalent for the web.

There are a few solutions already out there if you try a quick Google search, but many of them don’t feel quite right. They aren’t close enough to the performance and responsiveness of a native app implementation.

In order to get a more native-like level of performance I used some of the same CSS and JavaScript techniques that I wrote about when building the smooth sliding mobile menu. Combine that with the really awesome touch event library called Hammer.js and you’ve got the base for a great pull to refresh implementation.

There’s no crazy nested markup for this to work, it’s a very simple setup. It supports native scrolling, and it will work across all modern browsers on both the desktop and on mobile devices.

If you’re interested in using it in your next project, I’ve included all of the implementation details in the Github project readme. If you want to give it a spin, check out the demo implementation in your favourite browser or mobile device.

View on GitHub | Try a Demo

Building a Smooth Sliding Mobile Menu

It’s possible to create user interface animations in the browser that are as buttery smooth as native app animations. There are a few important techniques that you’ll need to know in order to achieve that level of performance.

This site is built to be responsive, meaning when you size down your browser window or visit on a mobile device the design adjusts to fit.

The biggest change is the top navigation menu, when the width of the viewport becomes narrow enough it will collapse into what is now commonly called a “burger button”. I guess it resembles a burger from the side? In any case, tapping that button will slide in a menu specifically designed for mobile devices. Give it a try, I’ll wait.

You might notice that the performance of the menu transition is smooth and silky, and the burger button responds instantly to your finger tap. On modern devices it’s almost indistinguishable from the performance you’d expect in native apps.

In this post I’m going to run through all the implementation techniques you’ll need to know in order to get that level of animation performance on your own websites or web apps. Let’s get into it!

1. Build out the HTML

The first step is to build out the HTML that we’ll need for the page and the menu. You’ll need two containers, one for everything on your page, and one for the menu. I’m using UL and DIV elements here, but you can use whatever makes the most semantic sense on your page. I’ve also added a link that will eventually act as the way to toggle the menu open and closed.

My New Site


The order of the menu and the page elements doesn’t matter, although semantically the menu makes the most sense at the top of your page.

2. Style the Menu with CSS

We’ll need some basic styles in order for the menu to appear on the top right hand side of the screen and remain a specific width regardless of the screen size. Feel free to adjust these styles so the menu looks exactly how you’d like.

I’ve chosen to give the menu a width of 240px for a couple of reasons, it feels like a good width for a vertical menu, and it will fit across a wide range of devices while still leaving part of the page visible. Add the following CSS to your page:

While you are styling the menu you may want to remove the display: none and reverse the z-index settings so it will sit on top of the page. Once you’re happy with the design make sure you set them back so the page covers the menu entirely and it’s hidden until requested.

3. Avoiding the Browser Reflow

Now, at this point you might be thinking we can sprinkle some jQuery .slideIn() and .slideOut() magic on the menu and be done with it. Although that would work reasonably well on desktop browsers, it will perform poorly on mobile devices.

Using jQuery’s built in animation functions will animate the menu in a way that causes something called browser reflow. This is where the browser has to re-calculate and render the position of elements on your page each time something changes. If you’re animating your menu that’s a lot of frames and a lot of re-calculation, causing the animation to be sluggish on less powerful mobile devices.

There’s a way we can animate elements in the DOM and avoid causing reflow, it’s using a CSS property called transform.

4. CSS Transform and the GPU

Using the transform property will allow us to manipulate any element over three dimensions using the translate3d value. We can move the element on the X, Y and Z axis on the page. So for example to move the #page element 10px to the left, we could use:

Notice that we use a negative value to shift the #page element to the left. You need to think of the elements’ starting position always as 0, 0, 0 regardless of any other positioning applied to the element in your CSS.

It’s also important to include the vendor prefixed -webkit-transform version in your CSS for the best level of support across multiple browsers and versions. This will ensure your menu works on all modern desktop and mobile browsers to at least a few versions back.

CSS also provides the more axis specific transform options translateX() and translateY(), so why are we using translate3d()? The reason is we want to use hardware acceleration to eventually animate the transform. Using translate3d() allows us to access the power of the GPU (Graphics Processing Unit) on the mobile device to render the element and eventual animation. The GPU is designed for this sort of work so it can provide smoother animation than using the CPU alone.

When we apply translate3d() to an element, a GPU rendered copy of the element is created and placed on a separate layer from the rest of the page. This means any manipulation of that element will not cause browser reflow — we are only modifying that layer and not affecting any other elements on the page below. This dramatically improves the performance of animation on mobile devices.

So how can we make use of the CSS transform property to animate our menu? First of all we’ll need to track the state of the menu using JavaScript.

5. Add JavaScript to Track State

Using JavaScript to track the state of the menu will allow us to add CSS classes to the body element of the document. This will allow us to handle all of the animation purely in CSS.

If you take another look at the menu animation on this site you’ll notice that the menu is not actually moving. What is happening is the menu stays in one place — stuck to the top right edge — and the whole page on the layer above slides back to reveal it.

There are four distinct states:

  1. No animation, menu not visible
  2. Page animating to the left, revealing the menu
  3. No animation, menu is visible
  4. Page animating to the right, hiding the menu

We need to assign CSS classes to the body element to represent when we are in one of these four states. To do this you’ll need to add the following JavaScript to your footer (make sure you have jQuery loaded before this, or you can adapt it to raw JavaScript):

Now, with this JavaScript you’ll see the following body classes appear and disappear depending on the menu state:

  1. No animation, menu not visible — No classes on body
  2. Page animating to the left, revealing the menu — animating & left classes on body
  3. No animation, menu is visible — menu-visible class on body
  4. Page animating to the right, hiding the menu — animating & right classes on body

We’ll see why it’s important to know about these four different states and have distinct classes for each in the next step.

6. Let’s Animate!

From here on our all of the animation will be done using CSS transitions. We can now use the CSS classes that the JavaScript added to the body element to determine when to apply CSS transition properties to elements. Add the following CSS to your page right below the previous styles:

I think the first four declarations should hopefully make sense. The first is easy, the #menu element should not be hidden when animating or visible. The second makes sure that the #page element will have a transition applied to it when transformed. That basically means it will animate smoothly over .25 seconds to the transformed position rather than just jumping directly to it.

The next two declarations determine the direction and final position that the #page element should be transformed to. So if it’s .left then it goes 240px to the left, if it’s .right, then 240px to the right from its initial spot (remember it always starts at 0, 0, 0).

The final declaration is a little tougher. When the .animate, .left and .right classes are not present, which is when the menu is either fully visible, or fully hidden, none of the CSS transforms above will apply. That means that there’s no translate3d being set on #page. As soon as the animation classes are removed, and the .menu-visible class is added, #page is going to jump back to its original position at position: absolute; top: 0; right: 0. In order to stop this we need to adjust its position so it does not jump back after opening. We need to adjust it to right: 240px; to keep it open at 240px from the right edge of the page.

You might be thinking — why not just leave the .animating and .left classes on the body to keep the #page in the correct position? It’s true that this would retain the final position of the #page element after the transition. The issue is that it also leaves the element in a state of being rendered by the GPU since the translate3d() value still applies. This is a bad idea, ending up with too many elements being GPU rendered at once will cause mobile browsers to crash.

As a best practice you should only apply translate3d() when absolutely necessary during animation states. Use standard positioning to retain an elements’ final state after animating. This is the main reason we needed to track and apply CSS classes for the four distinct states.

This last CSS declaration will eliminate any flickering of elements while they are in a state of being animated, it only applies to webkit based browsers (most current mobile browsers). Add it below the CSS already added:

7. Make it Responsive (if needed)

You should now have a basic page with a sliding menu. With the code above the menu will always be present and working on any modern device, at any screen size. For it to only show on smaller mobile devices you’ll need to introduce a media query to your CSS. Here’s one that will apply to most tablets and smartphones:

You may want to be more granular with your media queries depending on the size and type of devices you want to support. The above is a fairly blunt approach and will keep the #menu and #toggle-menu elements hidden on bigger screens entirely. You may want to write some alternative styles for #menu on larger screens, or include an entirely separate menu inside of #page for larger screens that will be hidden on mobile devices.

That’s it! You should now have a smooth native-like slide in menu. Here’s a demo of the final version. There are many other great uses for CSS transforms, transitions, and animations, some of which I’ve covered in recent posts: JavaScript Pull to Refresh for the Web, and JavaScript Swipe Cards UX. With the right techniques it’s possible to replicate many of the buttery smooth animations you’d generally expect only in native apps.

I’ve packed up all of the code and put it on Github. You can use it as a base to adapt to your needs. I look forward to seeing some of your implementations, let me know if you can think of any good improvements to the code in the comments.

View on GitHub | Try a Demo