Skip to content Skip to sidebar Skip to footer

How Do I Create A Parallax Effect Without Using A Background-image?

I am trying to create a parallax effect without using background-image with background-attachment: fixed, as background-attachment: fixed doesn't work on iOS so well. Here's what I

Solution 1:

Unfortunately, I do not know of any sure fire way using pure CSS. The reason for it is because there is no way to get the current scroll position (which we could be using in a calc()). Also, when positioning an element using fixed, it does not care about its parent anymore and it becomes impossible to enforce an overflow:hidden.

There are two ways of creating a paralax effect without using background, is to either make use of JavaScript, I've given you a full working example. It is minimal, might make the browser work way too much for nothing, but it works. You'll certainly want to optimize it to only apply on elements that are visible if you have a lot.

$(document).ready(function() {
  var onScroll = function() {
    var scrollTop = $(this).scrollTop();
    $('.paralax-image').each(function(index, elem) {
      var $elem = $(elem);
      $elem.find('img').css('top', scrollTop - $elem.offset().top);
    });
  };
  onScroll.apply(window);
  $(window).on('scroll', onScroll);
});
.content {
  height: 500px;
}

.paralax-image {
  overflow: hidden;
  height: 200px;
  position: relative;
}

.paralax-imageimg {
  position: absolute;
  height: 100vh;
  min-width:100%;
}
<scriptsrc="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script><divclass="content"><h2>Lorem Ipsum</h2><divclass="paralax-image"><imgsrc="https://via.placeholder.com/400x200"></div></div>

Now for the full CSS part... It is a bit complexe to implement and cannot be done for every kind of layout. The trick would be to have your image(s) using a position:fixed rule. But instead of unsuccessfully relying on overflow:hidden, you would have them at the lowest z-index, have all your elements with a background and create "holes" where you want to display the image. This will create a lot of problems when adding backgrounds, you'd have to make multiple different elements to make sure you have always a possibility to display the paralax image. I've tried to demonstrate how this could be achieved, without creating a too complexe example. This technique will only work for 1 image. If you want it to work with multiple images, you'd have to use javascript to switch visibility accordingly, and only 1 paralax effect visible at a time.

/* Can't use margins no more... */h1 {
  margin: 0;
  padding: 0.67em0;
}

p {
  margin: 0;
  padding: 1em00;
}

body {
  margin: 0;
}

.container>* {
  background-color: white;
}

.paralaxed {
  z-index: -2;
  height: 100vh;
  position: fixed;
  top: 0;
}

.paralax-image {
  background: transparent;
  height: 200px;
}
<divclass="container"><imgclass="paralaxed"src="https://via.placeholder.com/400x200"><h1>My Title here</h1><divclass="paralax-image"></div><p>
    lorem ipsum...
  </p><p>
    lorem ipsum...
  </p><p>
    lorem ipsum...
  </p><p>
    lorem ipsum...
  </p><p>
    lorem ipsum...
  </p></div>

Solution 2:

You actually can make pure CSS parallax effects without the need for background-image or background-attachment. Keith Clark has a great write up & tutorial on it. I'm going to borrow his code for the sake of the example:

HTML

<divclass="parallax"><divclass="parallax__layer parallax__layer--back">
    ...
  </div><divclass="parallax__layer parallax__layer--base">
    ...
  </div></div>

CSS

.parallax {
  perspective: 1px;
  height: 100vh;
  overflow-x: hidden;
  overflow-y: auto;
}
.parallax__layer {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
}
.parallax__layer--base {
  transform: translateZ(0);
}
.parallax__layer--back {
  transform: translateZ(-1px) scale(2);
}

It's actually quite a simple solution, but it might take a second to grasp how it's all happening. The big thing that's going on here is the transform: translateZ(-1px) scale(2), which moves that <div> back along the z-axis and resizes it back to normal. Setting the z-axis is how the speed of the parallax is controlled. So translateZ(-1px) is slower than translateZ(-2px).

Now that the div has been moved back in the z-axis, it needs to be resized back to its normal size. To do that, you simply add scale to the transform property. The scale must be calculated using 1 + (translateZ * -1) / perspective. So transform: translateZ(-10px) should be transform: translateZ(-2px) scale(3) assuming you keep the perspective set to 1px.

Then the perspective is changed to 1px for the .parallax container which will set the <div> perspective to the center. Adding overflow-y: auto allows content to scroll normally, but descendant elements will be rendered to the fixed perspective.

Since this just uses <div>'s and CSS, you should be able to solve your problem without JS. You can easily just place your images within the divs. This is a simple demo that shows just a single <div> parallax effect. If you look at the source code, you'll see no JavaScript except the part for Google Analytics. Here's a demo with a ton of different sections.

I recommend you read this tutorial, as the code should do everything you want. Plus it works flawlessly on iOS, Safari, Chrome, & FF. I've used it a number of times, and I can't recommend the method enough. Needless to say I borrowed much of my answer from that tutorial, so props to Keith Clark for the great write up.

Solution 3:

For whatever reason this seems to have worked best for me:

https://github.com/deggenschwiler/jquery_parallax

Requires jQuery in header of page:

<html><head><style>.parallax {
        height: 400px;
        width: 100%;
        background-image: url("SOMEBGIMAGE.jpg");
        background-position-y: 0%;
        background-repeat: no-repeat;
        background-size: cover;
      }
    </style><scriptsrc="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script><script>
    $(window).scroll(function() {
          var y = 0;
          var scroll = $(window).scrollTop();
          var win = $(window).height()
          var height = $(".parallax").height();
          var offset = $(".parallax").offset().top;
          y = ((100 * scroll)/(height + win)) + ((100 * (win - offset))/(height + win));
          if (y > 100){y = 100;}
          elseif (y < 0){y = 0;}
          var out = String(y) + "%";
          $(".parallax").css("background-position-y", out);
    });
    </script></head><body><divclass="parallax"></div></body></html>

Solution 4:

Pure CSS-Workaround: Set the container-padding to the height of the parallax (eg. 100vh), then postion fixed/absolute the child (parallax area) in it. Play around with z-index to achieve a parallax scrolling effect. Worked for me :)

Post a Comment for "How Do I Create A Parallax Effect Without Using A Background-image?"