Creating Scrolling Parallax Effects with CSS

By  on  
While this solution is elegant on desktop computers, it does not function on mobile devices. To create a mobile-compatible pure CSS parallax scrolling effect, please visit this post by Keith Clark.

I generally dislike ESPN because they're the McDonalds of sports news but they recently did a piece on Luis Suarez that was eye-catching.  The content itself was great but their use of parallax and imagery was outstanding.  They've employed this technique in a few of their features now and I've been so impressed that I implored my readers to write about how it's done.  The following is a post principally written by Stefan Judis with detail added by myself.  Enjoy!

Introduction

For quite a long time now websites with the so called "parallax" effect have been really popular. In case you have not heard of this effect, it basically includes different layers of images that are moving in different directions or with different speed. This leads to a nice optical effect and keeps the attention of the visitor.

In web design, the most common way to achieve this is by simply adding a jQuery plugin to a website. Doing this unfortunately has a few disadvantages. These plugins mostly attach an event handler to the scroll event of the window object. This leads to tons of events being handled via JavaScript (handling the scroll event can easily cause performance issues and should be considered carefully). To move the mentioned layers, background positions of images get calculated and set to the depending elements, which then additionally causes a lot of DOM manipulations.

In short: parallax done with JavaScript can decrease the scrolling performance of a website quite quickly.

background-position: fixed to the Rescue

What only a few people may know, is that this effect can be achieved via CSS, too. Check out the example below:

See the Pen Parallax with background-attachment : fixed by Stefan Judis (@stefanjudis) on CodePen.

To get this parallax effect, background images have to be placed on different elements. These elements additionally need to have defined background-attachment: fixed. By defining background-attachment the behavior and positioning of any background image can be changed.

The initial value of the property is scroll, which basically means that the image position is fixed to its element. There is nothing fancy about that and we all know this behavior. The user scrolls on a website and elements are moving up and down and so do the background images.

It gets interesting by setting the background-attachment to fixed. fixed defines that the background image position is not fixed to the depending element but rather fixed to the viewport. This means that the image will stay visually on the same position no matter how much scrolling will be done. This leads to the nice visual parallax effect.

Let's have a quick check on the actual implementation:

<!-- Four containers for setting the background images -->
<div class="parallax">
  <div class="bg__foo">foo</div>
  <div class="bg__bar">bar</div>
  <div class="bg__baz">baz</div>
  <div class="bg__bazz">bazz</div>
</div>
// setting base styles to image containers
[class*="bg__"] {
  height: 50vh;

  text-indent: -9999px;

  /* fix background */
  background-attachment: fixed;

  /* center it */
  background-position: center center;

  /* Scale it nicely to the element */
  background-size: cover;

  /* just make it look a bit better ;) */
  &:nth-child(2n) {
    box-shadow: inset 0 0 1em #111;
  }
}

.bg__foo {
  background-image: url(
    https://s3-us-west-2.amazonaws.com/s.cdpn.io/30354/parallax1.jpg
  );
}

.bg__bar {
  background-image: url(
    https://s3-us-west-2.amazonaws.com/s.cdpn.io/30354/parallax2.jpg
  );
}

.bg__baz {
  background-image: url(
    https://s3-us-west-2.amazonaws.com/s.cdpn.io/30354/parallax3.jpg
  );
}

.bg__bazz {
  height: 100vh;

  background-image: url(
    https://s3-us-west-2.amazonaws.com/s.cdpn.io/30354/parallax1.jpg
  );
}

A quick check regarding browser support on MDN shows almost global compatibility. It is already supported in IE9 and Android 2.1.

Sum up

I personally prefer CSS solutions to JavaScript solutions and this is a perfect example for my preference. There is no logic and no additional DOM manipulation needed, which makes the whole solution pretty nice. But there is still one thing to remember when dealing with parallax effects.

Even with this CSS solution there is a lot of stuff to do for the browser. background-attachment: fixed will lead to much more painting that needs to be done by the browser, which can affect the scrolling performance and maybe drop your FPS (remember the 60FPS goal?). So keeping an eye on the FPS meter e.g. in Chrome when doing these kind of things is always a good idea.

Stefan Judis

About Stefan Judis

Stefan is a frontend developer from Berlin. He maintains the projects grunt-phantomas and grunt-photobox. Improving performance, automating everything, visualizing datasets and drinking good coffee are the things he is doing most of the time.

Recent Features

  • By
    Facebook Open Graph META Tags

    It's no secret that Facebook has become a major traffic driver for all types of websites.  Nowadays even large corporations steer consumers toward their Facebook pages instead of the corporate websites directly.  And of course there are Facebook "Like" and "Recommend" widgets on every website.  One...

  • By
    JavaScript Promise API

    While synchronous code is easier to follow and debug, async is generally better for performance and flexibility. Why "hold up the show" when you can trigger numerous requests at once and then handle them when each is ready?  Promises are becoming a big part of the JavaScript world...

Incredible Demos

  • By
    Duplicate the jQuery Homepage Tooltips Using Dojo

    The jQuery homepage has a pretty suave tooltip-like effect as seen below: Here's how to accomplish this same effect using Dojo. The XHTML The above HTML was taken directly from the jQuery homepage -- no changes. The CSS The above CSS has been slightly modified to match the CSS rules already...

  • By
    MooTools Window Object Dumping

    Ever want to see all of the information stored within the window property of your browser? Here's your chance. The XHTML We need a wrapper DIV that we'll consider a console. The CSS I like making this look like a command-line console. The MooTools JavaScript Depending on what you have loaded...

Discussion

  1. Øyvind Nordhagen

    Just a clarification: The technique discussed here is not parallax. Parallax is when you have animation along two or more parallel lines that move at separate speeds. Think classic platform games like Sonic the Hedgehog and how the background sprite moves slower than the foreground to create a 3D effect in 2D.

  2. Tim

    Nice effect and writeup, but its not really parallax:

    http://en.wikipedia.org/wiki/Parallax_scrolling

    There are lots of genuine CSS parallax scrolling examples on the net, e.g: http://prinzhorn.github.io/skrollr/

    • Redge

      Skrollr is a JavaScript library…

  3. Came to say the same as the above. While parallax is the new hotness, some people think it’s just something staying static while other things move on top of it. This is not parallax. This is parallax: http://www.spaceneedle.com/home/

    • WebsiteGuru

      Ok so … Technically it is parallax.
      This is actually how parallax started .. then jquery was implemented to even make it “wicked”

      However the heading of this article should have been “Parallax Background Fixed Position: CSS only”.
      The links you have alluded to are “Full Parallax websites where each element is driven by jquery parallax variable mostly from resources like Github etc.

      A smooth moving parallax background is achieved by adding jquery .. however that has huge effects on Google rank/ analytic crawling if you do not know what you are doing.

      It’s one of the reasons why “full parallax” websites did not last.
      What is more realistic now especially if you want to rank a site good on Google and still add some awesomeness are either jquery Parallax driven backgrounds or complete CSS “static” background-position:fixed/ background-attachment-fixed and background-size: cover” on various div “containers”

      So it is parallax not just as fancy as the traditional parallax which has really died and didn’t survive the world of Google page rank and various mobile browsers etc..

  4. Brad

    Parallax is so overdone. I can’t wait for designers to finally get bored with it.

    • chris

      I look at it this way – like most really cool effects, it’s not technically overdone, it’s more that it’s almost always done really poorly – i.e., to demonstrate that the designer has technical skills, not to truly compliment a good design. In my opinion, the spaceneedle.com site referenced above by Jason is a beautiful site, and shows how parallax should be used.

      This site, on the other hand…ugh…

      http://www.marklawrencedesign.com/MLD_sandbox/MLD_2011/

      Just my opinion, worth every penny it cost, but I think it’s a mistake to dismiss stuff like this just because so many people use it poorly.

  5. Chris

    Has anyone considered using translateZ() to make a parallax effect?

  6. As others have said this is not actually parallax, but it is pretty cool and does mimic the ESPN article pretty well. I found this actual pure css parallax on codepen. And I think it may even answer whether or not anyone has considered using translateZ() for this.

    http://codepen.io/scottkellum/pen/bHEcA

  7. Thanks @david. This is another great idea ;) Love from Türkiye.

  8. Since you’re using a single background image per element, this has been supported since Internet Explorer 4, not 9. Which means it has been supported since 1997 (at least for Internet Explorer). It is also not exactly parallax.

  9. I am glad you pointed this out! No one is talking about this. I don’t think anyone has actually read the new guidelines. You shared great CSS code about scrolling parallax effects that is useful post to all. Thanks Stefan Judis for share great post with us.

  10. Good tip, thanks! The big bold title that say “background-POSITION: fixed to the Rescue” did throw me off for a second there, but it all worked out in the end. ;) Whether or not it’s technically parallax, it’s still the effect I was trying to achieve and I’m pleased it can be done without the use of JS.

  11. Huh. Why didn’t I think of that? That makes perfect sense and is a lot simpler. Cool.

  12. Ann

    it doesn’t work on my android tablet :(

  13. Ellen N.

    Thanks a lot! I needed something like this for my project.

  14. Genius! Thanks very much!

  15. Sorin

    I tried your example but in chrome some images not loading totally and doesn’t look and work well. In other browsers work fine.

  16. Great parallax demo. I like to do some scroll effect to my site, but technically I am not ready yet (have not enough css experience) to integrate it to my site theme.

  17. I’m trying to get a similar thing going with not only an image but with html content too. The masking and revealing effect I’m going for should be similar. Any pointers? Links? Libraries that can do that? (js=ok)

  18. Great article for those who are considering to implement a parallax scrolling web design. This parallax scrolling method is also implemented on a drupal website: http://www.startechup.com

  19. KJ Roxxx

    It doesn’t work on IOS…has anyone else found this issue yet???…

  20. Alex

    You don’t contribute anything to the conversation when you point out little technicalities. Who cares if it’s parallax or not. It’s good work and it’s just what I needed, so thank you, and don’t let them get you down

  21. GreenAsJade

    “Who cares if it is parallax or not”?

    Obviously, people who came to an article entitled “Creating Parallax” looking for a solution to create … parallax. This isn’t a “technicality”. If things don’t move at a different speed, it is not parallax. At all.

Wrap your code in <pre class="{language}"></pre> tags, link to a GitHub gist, JSFiddle fiddle, or CodePen pen to embed!