Medium-Style Page Transition

An article on how to achieve Medium’s next page transition effect—an effect that can be seen by clicking anywhere on the “Read Next” footer at the bottom of the page. This effect is characterized by the lower article easing upward as the current article fades up and out.
MediumStylePageTransition

From our sponsor: Grow sales by using the smart tools in our all-in-one Marketing Platform. Try it for free.

Medium, a blogging platform which has gained popularity over the past several months, has one of the smoothest, most polished user interfaces on the web. As you click and touch the interface, you’ll notice that great attention has been paid to transitions, white space, color, fonts, imagery, and iconography.

In this article, I will outline how to achieve Medium’s page transition effect—an effect that can be seen by clicking anywhere on the “Read Next” footer at the bottom of the page. This effect is characterized by the lower article easing upward as the current article fades up and out. See the animation below for an illustration of this effect.

article-animation

HTML

In this demo, the page first loads with barebones HTML, which we’ll use as a template that will be filled in later with Ajax’d-in data. Below is what our <body> looks like on initial page load. One main <article> tag. Pretty simple, eh?

    
<body>
  <article class='page hidden'>
    <div class='big-image'></div>
    <div class='content'></div>
  </article>
</body>

Once the content is Ajax’d-in, the <body> looks something like so:

  
<body>
  <article class='page current'><!--other HTML --></article>
  <article class='page next '><!--other HTML --></article>
<body>

The page currently being viewed has a class of current, and the next article has a class of next. The next article only has its large image being shown at the bottom of the page, which, when clicked on, brings it into focus.

CSS

The styles in this demo which control the article transitions are both applied dynamically via jQuery’s css() method, as well as by applying classes to the <article> elements using jQuery’s addClass() method.

Here’s a rundown of the pertinent classes used:

     
    article.page.hidden { 
        display: none 
    }

    article.page.content-hidden .content { 
        display: none 
    }

    article.fade-up-out {
        opacity: 0;
        transform: scale(0.8) translate3d(0, -10%, 0);
        transition: all 450ms cubic-bezier(0.165, 0.840, 0.440, 1.000);
    }

    article.easing-upward {
        transition: all 450ms cubic-bezier(0.165, 0.840, 0.440, 1.000);
    }

Javascript

Before getting into the Javascript code, I want to first outline the algorithm used to transition the “next” article upward, and transition the “current” article up and away.

User clicks on big image of next article:

  1. Disable scrolling on the page
  2. Fade current article to opacity of 0, a scale of 0.8, and move it upward by 10%.
  3. Show the next article’s content, give it smooth transitions, then move it upward to the top of the window
  4. After 500ms:
    1. Remove the current article from the DOM
    2. Remove smooth transitions from next article
    3. Scroll to top of page programmatically.
    4. Make next article the current article
    5. Enable scroll on the page
    6. Make Ajax request for next article’s content

The Code

  
  ArticleAnimator.animatePage = function(callback){
  var self              = this;
  var translationValue  = this.$next.get(0).getBoundingClientRect().top;
  this.canScroll        = false;

  this.$current.addClass('fade-up-out');

  this.$next.removeClass('content-hidden next')
       .addClass('easing-upward')
       .css({ "transform": "translate3d(0, -"+ translationValue +"px, 0)" });

  setTimeout(function(){
      scrollTop();
      self.$next.removeClass('easing-upward')
          self.$current.remove();

      self.$next.css({ "transform": "" });
          self.$current = self.$next.addClass('current');

      self.canScroll = true;
      self.currentPostIndex = self.nextPostIndex( self.currentPostIndex );

      callback();
  }, self.animationDuration + 300 );
}

Throughout the CSS & Javascript code, you’ll notice that, in order to achieve fluid animations, I am using transform: translate3d(x,y,z) to move my DOM elements. By doing this, we “hardware accelerate” the DOM elements movement. This method is preferred over animating an element using top/left or transform: translate(x,y,z), which are not hardware accelerated by default.

Side notes

As outlined earlier, the page is populated by making Ajax requests to static json files. Page state is managed using the PushState API and location.hash.

Photos in the demo were used courtesy of Unsplash. The page font is set in PT Serif and the headings in Source Sans.

Tagged with:

Brian Gonzalez

Brian is a web developer and designer based in Los Angeles. He's one of the web’s biggest proponents, and enjoys using the web to build things that bring life to products and the people that use them.

http://briangonzalez.org/

Stay up to date with the latest web design and development news and relevant updates from Codrops.

CSS Reference

Learn about all important CSS properties from the basics with our extensive and easy-to-read CSS Reference.

It doesn't matter if you are a beginner or intermediate, start learning CSS now.

Feedback 90

Comments are closed.
  1. Great Just loved it!! i was searching for this trick but i didn’t found the best one but now i think i found it thank’s very much!!

  2. This is by far one of the best page transition I have ever seen. Simple and saves me the from the dreaded infinite scrolling.

  3. If I download the code, it does not load any content, I tried it on WAMP and on my website as well, but it does not work…

    What do I need to setup to get the AJAX loading?

  4. DESIGNfromWITHIN,

    Since the page uses ajax, it’s best to serve the “index.html” with a true http server, and not from file. I like to use a Ruby gem called serve to achieve this.

    Simply gem install serve, then type serve from with the project’s root, and you’ll be able to access the page at localhost:4000. Hope this helps!

  5. very interesting transition
    Work well on Mozilla / Safari / IE
    but doesn’t work on Google Chrome

  6. It’s really frustrating to find the scrollbar missing in the demo page, it’s unaccessible for me as my mouse does not have a scrolling wheel – any possibility of fixing it?

    • The scroll bar is there but it’s only 1px wide on chrome. Not all of us use a Macbook with gestures or even a mouse with a scroll wheel. Very unusable.

      Clicking and using the down arrow is not an acceptable solution as it’s not natural behavior for most people.

  7. Awesome.
    Just a question, how did you do the gif animation above?
    Maybe a tutorial on that.
    =)

  8. What about a “Back” button or “Last Article”? It seems like should work just tagging the link on a #NUMBER.

    Right?

    By the way, it’s pretty awesome!