February 19, 2015 | 94 Feedbacks

Parallax Hero Image

A full-width figure element, with floating images distributed in a 3D space.
Browser support
  • ie
  • Chrome
  • Firefox
  • Safari
  • Opera

What you can achieve through CSS 3D Transforms is limitless. With power comes responsibility, though. There will be cases when you’ll take full advantage of CSS 3D capabilities. In most projects, though, you can just spice things up a little.

Today’s nugget is an effect which is getting quite popular and relies on 3D Transforms. In a nutshell, we distributed some images on the z-axis, then we used the mouse as a (fake) 3D camera so that perspective changes while you move the mouse cursor. What we really do is rotating the images in the 3D space according to the mouse position.

Since this effect relies on mouse movement, on mobile devices it won’t be visible.

You can see this cool effect in action on websites like Squarespace and HelloMonday.

Image credits: and

Creating the structure

The main HTML structure is a <figure> element containing our hero image (we used 3 different <img>s) and wrapped in a .cd-background-wrapper element.

The images used should have the same dimensions.

Adding style

To create the hero image we put the <img> elements one on top of the others: the first one has a static position, while the others are in absolute position; a different translateZ value is assigned to each of them.

The idea behind the parallax effect: when user moves his mouse over the hero image, the .cd-floating-background element is rotated (along the X and Y axises)  according to the mouse position. Since the <img> elements  have different translateZ values, a different rotation is perceived for each of them.


To properly achieve this effect, we have to make sure that our <img>s are properly positioned in a 3D-space: first, we assign a perspective value to the .cd-background-wrapper, which creates a 3D-space shared by its children; then we assign a transform-style: preserve-3d to the .cd-floating-background so that its children are positioned in a 3D space rather than flattened (as default). TranslateZ does the rest!

About IE: IE9 doesn’t support CSS3 3D Transforms while IE10+ doesn’t support the transform-style: preserve-3d property. So the parallax effect won’t be visible in IE and you’ll see a standard image.

Events handling

We bind the initBackground() function to the image load event: this function changes the position property value of the <figure> element from relative to absolute (the  ‘is-absolute’ class is used). At that point, we need to assign a proper height to the .cd-background-wrapper element (since its child is in absolute position, its default height is 0) and proper dimensions to the .cd-floating-background (it has to be bigger than its wrapper – this way rotation won’t reveal empty borders).

We evaluate the image aspect ratio and the viewport width and assign to the .cd-background-wrapper a height equal to viewportWidth/heroAspectRatio. The .cd-floating-background height and width are proportional to the .cd-background-wrapper ones and its left and top parameters are set so that the image is centered inside its parent.

We then bind the mousemove event to the .cd-background-wrapper: the mouse position is evaluated using event.pageX and event.pageY and a corresponding rotateX and rotateY value is assigned to .cd-floating-background.

Note: Modernizr doesn’t detect preserve-3d support yet. So, in order to target browsers that don’t, we used the getPerspective function which assigns a preserve-3d/no-preserve-3d class to the <html> according to browser support (Modernizr – issue 762).


Jul 15, 2016
  • Fixed bug when image top is not zero
May 25, 2015
  • Fixed bug on Chrome 43.0.2357.65
Feb 20, 2015
  • Firefox bug fixed - image rendering issue
Feb 19, 2015
  • Resource released by CodyHouse

Claudia Romano

Web developer, fan of The Big Bang Theory and good food. Co-founder of CodyHouse and Nucleo. You can follow her on Twitter.

  • Nicolas Paillard

    Does not work on my Firefox. V 35

    • Claudia Romano

      There’s an image rendering problem on Firefox. We’re working to solve that. Thanks!

  • Joey Ng’ethe

    The demo seems to be broken. Inspecting it, there seems to be a 403 on one of the scripts

    • Claudia Romano

      Hi Joey, which browser are you using? Thanks

      • Joey Ng’ethe

        Hey Claudia, i was using Firefox but it works on chrome. Great technique, always a fan of codyhouse. Cheers guys.

  • Jakub Vitek

    it doesnt really work for me either :/

    • Claudia Romano

      Hi Jakub, which browser are you using and what issue are u experiencing? Thanks!

  • Alessandro Tesoro

    This looks so cool! Wish i had an use for it :D

  • Guest

    Thanks a lot! Good job!

  • Sergey Bargan

    when i change resolution, plugin not worked. Example: 1024×768

    • Claudia Romano

      Hey Sergey, since the effect relies on mouse movement, we disabled it on smaller devices ( MQ set to 1170px).

  • pepperstreet

    Would be real fun to use it with “gyroscope sensors” ;) :)
    Just found a javascript solution, possible with browsers/css only!?

  • Dylan George

    It’s a bummer this doesn’t work on mobile like does.

    • Sebastiano Guerriero

      Hey Dylan, on mobile it can’t work since you don’t have a mouse. You’re trying HelloMonday mobile version by resizing the browser window of your pc (still using your mouse to test the effect). If you test it on a mobile device instead, you don’t see the effect, it’s just a static image.

      If you want the parallax on smaller devices, just change the media query of the resource (right now the effect is visible for screen size > 1170px)

      • Jeffrey Bennett

        Simply being on mobile or having a touchscreen really has nothing to do with whether or not a page can using parallax scrolling. Check out to see an example of parallax scrolling on touch-enabled smartphone.

        • Sebastiano Guerriero

          The effect on this resource is enabled by the mouse movement (not the scrolling). You can activate this effect on mobile, but since you don’t have a mouse you won’t see the effect.

          • Andrea Coronese

            But there IS, however, an API to use gyro information on a web app (on iOS since 4.2 if I do not mistake, on Android there should be one as well).

            A simple compatibility layer to translate the informations of this example…

            window.ondevicemotion = function(event) {
            ax = event.accelerationIncludingGravity.x
            ay = event.accelerationIncludingGravity.y
            az = event.accelerationIncludingGravity.z
            rotation = event.rotationRate;
            if (rotation != null) {
            arAlpha = Math.round(rotation.alpha);
            arBeta = Math.round(rotation.beta);
            arGamma = Math.round(rotation.gamma);

            into a “fake” mouse movement data, and triggering same events, could be done in a few lines of code (getting rid of Z axis, since it would be useless here.

            I will give it a shot.

    • Siyanda

      You could get it working on IOS using the phones accelerometer and the “deviceorientation” class

    • Panos Telonis

      doesn’t work with mozilla.. it stops when loader is 100% complete but it doesnt load anything else

    • Andy Gee

      hellomonday doesn’t work on Firefox

      The buffer passed to decodeAudioData contains an unknown content type.
      Error: Error Loading file >> assets/audio/proud_peacock.ogg?v=109

      On Chrome it’s fucking awful

  • c97

    This type of effect is called Ken Burns 3D, not some parallax something.

  • WillyPs

    @c97: The term parallax describes a technique Ken Burns uses to give the
    impression of 3D, but he did not invent the idea, the concept predates
    Ken Burns’ use of it, in fact the term parallax predates digital imagery
    and even the discovery of electricity! Kudos to Claudia for using the
    correct term and not calling it ‘some Ken Burns something’.

    [url=]Parallax – Wikipedia, the free encyclopedia[/url]

    But I thank you for your comment, I was searching for parallax and happened onto this page, as I could not remember the name Ken Burns! ;)

  • BB

    There is an issue with image loading in FF. Images are loaded horizontally only for around 1/10 of the viewport. I will try to explain what I noticed, so maybe somebody will find proper solution for this. I have two monitors connected to my PC – one with screen resolution 1920 x 1080 and other with resolution 1366 x 768. When the tab is moved from first screen to second, the images are loaded properly (without refreshing of the page). Next – If I refresh the page on the smaller monitor, there is issue again, and now if I move the tab from smaller monitor to the larger, the images are loaded properly (again without refreshing of the page). Also, if I only pop out the tab in the same screen but in new window, the issue is gone and page is working correctly without refreshing. Maybe it is something about resizing and media queries. Additionally, when page is opened locally on my machine using wamp, there is no problem at all. But the issue occurs only after files are uploaded on server, and only in Firefox. All other browsers are working without any problems. Hopefully, somebody can find an solution for this and share it. Thank you.

  • Claudia Romano

    @disqus_xhfKSpcAWD:disqus @jakubvitek:disqus @joengethe:disqus @nicolaspaillard:disqus Hey guys just uploaded a new version. That should fix the bug on Firefox (you may need to clear your cache though)

    • Carlos

      If you don’t mind me asking, how did you fix the Firefox Bug?

      • Claudia Romano

        Hi Carlos, I added a background-color to the images – not the most elegant way but it worked ;)

    • Bojan Drango

      It is working properly now. Thank you.

  • ASK47

    Can’t get it to work in any browser on my PC. Sometimes my touch screen messes with Chrome and FF feature detection.

    • Claudia Romano

      Hi! actually we targeted the no-touch devices for the effect to work!

      • ASK47

        Well, that makes me feel sad and neglected. Just because I have a touch screen doesn’t mean I’m not using a mouse and keyboard.

        • Claudia Romano

          A solution could be using CSS media queries instead of touch/no-touch detection, and enable the effect only on bigger screens!


    I cant for the life of me figure out how to change the height of this. I want to use it as a header banner, say about 3 or 400px high?

    • Claudia Romano

      The height is given by the aspect ratio of your images, so you should try to change that. Unfortunately it doesn’t work in IE because it relays on the preserve-3d property. But you can use the .no-preserve-3d class to target these browsers and create a different effect ;)


    also, is there any way to get this working on IE?!

  • fazkamisan

    Hey Claudia good work! I think it’s cool that you actually make time and answers questions from all of us. I’ve learnt a lot from you and Sebastiano.

    Keep it up!

    • Claudia Romano

      Hi! thank you for your comment, really glad to hear that :) We try to do our best! Cheers!

  • Cam

    Terrifyingly creepy! I love it :)

  • Tølga Esen

    Nice Job Claudi :)

  • Anish M Alias

    nice work

  • Alexander Hermann

    I’m not that much into js so I could not do this by my own. But can you/or someone of the mighty folks here ad some possibility to that it grabs div’s or p’s or whatever, that it works with text and graphic elements? Thanks and p.s. I really love your work. You do a wonderful job. Greetings from Germany.

  • Chu Quang Tú

    Very nice work. I love your idea about making Parallax like this. Thanks again.

  • Michael

    Could someone with a better understanding of the mathematics please explain the calculation for the proportions variable in initBackground(). Specifically, why ‘1.1/(Math.sin(Math.PI / 2 – maxRotationY*Math.PI/180))’? I’d really like to know – Thanks!

    • Claudia Romano

      Hi Michael, maxRotationY*Math.PI/180 converts the angle from degree to radian. 1/Math.sin(Math.PI / 2 – maxRotationY*Math.PI/180)) gives you the hypotenuse in a right-angled triangle with a unitary cathetus (maxRotationY*Math.PI/180 being the angle between the cathetus and the hypotenuse). The 1.1 (instead of just 1) is to make sure that no empty borders are visible when you rotate of maxRotation. Hope this helps!

      • Michael

        Hi Claudia. Thank you so much for taking the time to reply and giving such a clear explanation – much appreciated!

  • Sarah Bennet Mills

    Hey Claudia,

    You guys are doing awesome. I really love your idea of making parallax effect. Parallax hero images is a part of our monthly round up of best jQuery plugins. Check it out here:

  • Rodrigo Chaves

    love it!

  • Rodrigo Chaves

    Love it!

  • alexeiramone

    Hmmmmm It doesn’t work for me. Chrome

  • BrokerZero

    Very cool! Is there a simple way to include an overlay with text and a button?

  • nazzar s

    Awesome man

  • orangorangan

    Hi Claudia, beautiful application of parallax effect. How can i trigger upon mouse click instead? Thanks :)

    • Sebastiano Guerriero

      I don’t think you can, the effect makes sense as long as you move the mouse around. Do you have an live example of the effect you want to achieve?

  • xochipilli

    Dear Claudia! Thank you so much for sharing your work – it’s inspirational. One question – is it possible to add easing to the movement? Maybe someone could provide a simple jquery solution? Thanks in advance!

  • Mirko

    Great tutorial as always :) I have one question, not code related!! Is the corner man image available somewhere online as a mockup, or is that your own graphic?


  • Gew

    I cant do background-size:cover; help please

  • Batchprocessing

    Hello. I am trying desperately to adjust the movement to be more pronounced in one of the images. I mostly seem to end up copying the function moveBackground(event) (and naming it otherwise) and trying to target the first-child but it just screws things up for all of the images. I would love to ask for advice. Plus, my math gets all screwy. If you don’t mind sharing thoughts, this would be great. Thank you!

    • Claudia Romano

      Hi, try increasing the translateZ value of the image. That should help!

      • Batchprocessing

        It did! Now, i just have to figure out why the background image keeps getting cut off!

        • Batchprocessing

          What about placing text instead of an image? I just started trying to work on that but figured i would ask, others have, just putting it out there. If i find that solution i will post.

  • Nick Sidiropoulos

    Great work! Congratulations for imagination!

  • Leandro Ruel

    hi claudia, nice example… your name… looks like brazilian. =)

  • SNEG

    Something wrong, don’t work(

  • Matt Kochanowski

    this is soo lovely! I’ve noticed that after embedding it into page vertical movement stopped working. Horizontal is still fine. How I can deal with that issue?

    Looking forward to hearing from you!

    Many Thanks!

    • Yehuda Menahem

      Same happend to me

    • Yehuda Menahem

      The solution is in the javascript file when you set the RotateX. notice –> X (not the Y)
      if you image is position not in the top of the window,
      Now the event.pageY(now it’s the Y :) taking the position of the mouse from top of the window
      You need the position of the mouse from the top of the element:
      instead of

      It will work

      • RMDProduction

        HI, ive tried your code but it dosent word for me :/
        could you explain it “more” ? :)
        Here s my rotateX :
        rotateX = ((event.pageY-$(“cd-background-wrapper”).position().top-halfWindowH)/halfWindowH)*maxRotationX;

  • Pratyaksh Somani

    Flawless…..Simply loved this.

    Hey I am planning some creativity in this…..Can I put some image in that iPhone display and put a navigation link to some page from that in-display image…. Is that possible Claudia Romano??

    • Ricky

      wrap an anchor link around the 2nd image?

  • FantasyDecathlon

    Amazing! Except I tried to put a welcome on top but it completely broke on Safari. Anyone figure out how to place a div on top of this parallax effect and still have it work across all modern browsers?

  • Su san

    Hi many thanks for the tutorial, it work perfect except I found it freeze in firefox, and I check your demo in firefox it not working as well, does anybody have solutions? thanks in advance.

    • Claudia Romano

      Hi, just tested it on Firfox (40.0 on Mac) and it’s working fine? Which version are you using? thanks

      • Su san

        Hi many thanks for your reply, I am on firefox 40.0.3 Mac (most updated version? because it’ll update itself), just tried, it still not moving, weird, but works perfectly on other browser.

      • Su san

        (UPDATE) sorry! it back to works when I reset my firefox, it was a bug in my firefox, many thanks for the tutorial!

  • Joe

    Hi Claudia love this effect,

    I was wondering can you get this demo to react the way it does on this site. The image doesn’t reduce in size when resizing the browser. So its more fixed to the height of the browser

    On your demo when you resize the browser the image gets smaller. Would love to be able to get it so it fits the screen through out all break points.

    Many thanks Joe

  • Robert Woods

    Hi Claudia,

    Thanks for this wonderful tutorial.Our developers at CSSChopper simply loved this information.


  • Mumu Badjeber

    The image size..
    @media screen and (max-width: 320px)
    @media (max-width: 460px)

    Best demo :

  • Enf1eld

    Hi. Can you help me? How i can use your plugin with resolution less 1024px?

  • ramesh

    caught TypeError: Cannot read property ‘insertBefore’ of undefined
    Found such error in my console

  • Ricky

    cant get it to work, images load fine, get no errors from the console. images dont react to mouse at all.

  • deadgarry

    I try add a text above this parallax effect but i can’t do it. I try do it for several method but images be always above the text :( I want to set this effect for background of web page. So how i can do it correctly ? Can you help me pls?

  • lass6957

    Isn’t compatible with Google Chrome anymore, however works with Microsoft Edge..

    • Claudia Romano

      Hi there, I just tested it in Chrome (47.0.2526.106) and it’s working fine. What issue are you experiencing? Thanks

      • lass6957

        Hi Claudia,
        First of all, I’m a BIG fan of your work!

        It’s strange. I’ve tested the demo and downloaded version many times through out the last couple of months. No problems. Yesterday it stopped working for me in Google Chrome. Both the demo version and the downloaded version didn’t respond to the movements of my mouse. It was completely still – Also after multiple restarts of my browser.. I tried in another browser (Microsoft Edge) where everything worked like a charm.

        Today, i just tested it again, and everything is working, so i guess it was some kind of browser error.

        Now, that you are here, is it some how possible to integrate this to a banner (frontpage) in WordPress?

        Thank you for getting back to me this quickly! I really appreciate it.

        – Lasse

  • Pirozhok

    Hi, It looks perfect with images, but can I add some blocks with some text? I want see parralax pictures on background!

  • RanaInteractive

    Hi Claudia, Thanks for the tutorial… is it possible to implement this in a WordPress theme. I tried playing around with it, but haven’t have much luck. It loads all of the images and they scale with the site window. But no effect they load one above the next, from the top to bottom of the page, rather than stacked on top of each other in layers. I can add both custom CSS and JS to this particular theme, but it’s not quite working for me.

  • Marc

    Thank you very mich for this awesome plugin. I am experiencing some issues on Safari with a div with text over the images tho (see link: ). Any chance of getting this fixed?

  • Yehuda Menahem

    This is great!

    Question please:
    after embedding it into page vertical movement stopped working
    Where can I set the place where the movement will begin
    I can see now that it’s the top of the page, but can’t find the place to change it
    (I want to give it always the top of the element in case I don’t want it 100% height and 500px height in the middle of the page suppose)

    Thanks a lot ( :

    • Claudia Romano

      @rmdproduction:disqus @yehudamenahem:disqus thanks for the heads-up! Fixed now ;)

  • Brandyss Nikol Adams

    This doesn’t work in the latest Chrome for me…is there something I am missing?

    • Claudia Romano

      Hi there, just tested it on Chrome 51 (Mac) and it’s working just fine. What issue are you experiencing? And are you testing our demo or a local version? thanks

  • Pascal Pixel

    As an alternative to the method in this article, you can also just change the transform-origin based on the mouse position, meaning you’ll only need a single line of js:

    $(document).mousemove(function(e){ $(‘.perspective’).css({ perspectiveOrigin: Math.floor((e.pageX / $(this).width()) * 100) + ‘% ‘ + Math.floor((e.pageY / $(this).height()) * 100) + ‘%’ }); });

  • Jay Emblem

    How can you make this work in squarespace? i can’t figure it out. Thanks!

  • JohnDrach

    Is there a way to make the background image full screen? It’s kind of hard to use if there is a block of nothing at the bottom. I was trying to adjust but can’t seem to get it to work