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.

From our sponsor: Supercharge your marketing across design, automations, analytics, and more, using our marketing smarts.

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.



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?

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

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

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

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.


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:

        display: none 
    } .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);


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.$next.removeClass('content-hidden next')
       .css({ "transform": "translate3d(0, -"+ translationValue +"px, 0)" });


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

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

  }, 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.

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. Sweet article Brian!

    One question though. What would i need to change if i didn’t want the pages to loop once it reached the end of my articles?
    Any help would be much appreciated 🙂

  2. Wow! awesome, great way to let the viewer see what’s next and smooth transition! I’m going to have to give this a try.

  3. I visited Medium’s website a day ago and was interesting how this page transition works…. Thank you for explanation and great article! 🙂 Just in time!

  4. Nice one Brian

    Can it be used also to go back to the top of the page quicker than via scolling ?

  5. Safari version 6.0.5 (8536.30.1), when you click on the next article at the bottom of the page, new article opens and scrolls down and does not stay on the top of the page. how to fix it? thank for the sharing, very very good work!

  6. Very cool mechanic, but there seems to be some serious lag involved where if you click ‘back’ too quickly there is no action (chrome 30, win7). the view stays the same. If you wait a while before going back it seems to go fine

  7. Great tutorial. Do you have a javascript books to recommend? Completely of the topic here, But i was wondering how you created that swipe animated gif?

  8. Great, exactly what I needed !
    However, I don’t think that ajax’ing the content of the main article is a good thing because people who do not have javascript enabled wouldn’t be able to see any content.

    • So many people have disabled javascript… It shouldn’t be an issue, however if it really is a concern to you: use regular <a href rel=”nofollow”> to the next page. Fetch the click action with javascript for people who have javascript enabled and serve it with ajax. People who have it disabled just go to a new page. Hope that makes sense.

  9. Hi, I have downloaded the file but it doesn’t work at all. Is there something that I suppose to change?

  10. this is great work. Can we disable looping. Also can we put static text after that like contact form or something in the index file itself?

  11. I downloaded and dosnt work at all, the images dont load and it says file:///data/post_1.json?_=1384654457169 failed to load resource in the console log.

  12. Anybody figured out how to implement a second picture? If you look at “Medium” you’ll see pictures in the middle of the article. I already tried to put am tag in the ajax data, but this will crash the site. I hope you can help me out 🙂