(CSS) Make a background image scroll slower than e

2019-01-16 16:25发布

问题:

here is is my CSS code for the body:

body {
  padding: 0;
  margin: 0;
  background-image: url("../images/background.jpg");
  background-repeat: no-repeat;
  background-color: grey; 
  background-size: 100%;
}

What I want to do is make it so that the image scrolls slower than everything else on the page to make a simple parallax effect. I've looked online and all of the examples I've seen are much more complicated than what I want.

回答1:

I stumbled upon this looking for more flexibility in my parallax speed that I have created with pure CSS and I just want to point out that all these people are wrong and it is possible with pure CSS It is also possible to control the height of your element better.

You will probably have to edit your DOM/HTML a bit to have some container elements, in your case you are applying the background to the body which will restrict you a lot and doesn't seem like a good idea.

http://keithclark.co.uk/articles/pure-css-parallax-websites/

Here is how you control the height with Viewport-percentage lenghts based on screen size:

https://stanhub.com/how-to-make-div-element-100-height-of-browser-window-using-css-only/

  .forefront-element {
    -webkit-transform: translateZ(999px) scale(.7);
    transform: translateZ(999px) scale(.7);
    z-index: 1;
  }

  .base-element {
    -webkit-transform: translateZ(0);
    transform: translateZ(0);
    z-index: 4;
  }

  .background-element {
    -webkit-transform: translateZ(-999px) scale(2);
    transform: translateZ(-999px) scale(2);
    z-index: 3;
  }

Layer speed is controlled by a combination of the perspective and the Z translation values. Elements with negative Z values will scroll slower than those with a positive value. The further the value is from 0 the more pronounced the parallax effect (i.e. translateZ(-10px) will scroll slower than translateZ(-1px)).

Here is a demo I found with a google search because I know there are a lot of non-believers out there, never say impossible:

http://keithclark.co.uk/articles/pure-css-parallax-websites/demo3/



回答2:

you can use something simple like here: html:

Motion

css:

body {

  min-height:4000px;
  background-image: url("http://www.socialgalleryplugin.com/wp-content/uploads/2012/12/social-gallery-example-source-unknown-025.jpg");
}

h1 {margin-top:300px;}

js:

(function(){

  var parallax = document.querySelectorAll("body"),
      speed = 0.5;

  window.onscroll = function(){
    [].slice.call(parallax).forEach(function(el,i){

      var windowYOffset = window.pageYOffset,
          elBackgrounPos = "50% " + (windowYOffset * speed) + "px";

      el.style.backgroundPosition = elBackgrounPos;

    });
  };

})();

Here is jsfiddle



回答3:

Agree that it isn't possible just with css, because you have to compute image and document height ratio. I also like this effect, that's why created simple function that does just that. Here is function and its call on scroll event:

$(window).on('scroll', function() {
	smoothBackgroundScroll("relative/image/url");
});

function smoothBackgroundScroll(imgsrc) {
	function loadImageHeight(url, width) {
		var img = new Image();
		img.src = url;
		if (width) {
			img.width = width;
		}
		return img.height;
	}

	var dh, wh, ih, st, posy, backh, backw;
	if (!this._smoothBackgroundScroll) {
		var bcksize = $(document.body).css('background-size');
		var bmatch = /(\w+)\s*(\w+)/.exec(bcksize);
		if (!bmatch || bmatch.length < 3) {
			backh = loadImageHeight(imgsrc)
		} else {
			backh = parseInt(bmatch[2]);
			if (isNaN(backh)) {
				backw = parseInt(bmatch[1]);
				backh = loadImageHeight(imgsrc, parseInt(backw));
			}
		}
		this._smoothBackgroundScroll = {
			dh: $(document).height()
			, wh: $(window).height()
			, ih: backh
		}
	}
	dh = this._smoothBackgroundScroll.dh;
	wh = this._smoothBackgroundScroll.wh
	ih = this._smoothBackgroundScroll.ih;
	st = $(document).scrollTop();
	posy = (dh - ih) * st / (dh - wh);
	document.body.style.backgroundPosition = 'center ' + posy + 'px';
}

You can find it here along with example and visual explanation what's really going on with image and document:

Smooth background image scrolling



回答4:

If you want to apply a high background image, use this JS:

(function () {
        var body = document.body,
                e = document.documentElement,
                scrollPercent;
        $(window).unbind("scroll").scroll(function () {
            scrollPercent = 100 * $(window).scrollTop() / ($(document).height() - $(window).height());
            body.style.backgroundPosition = "0px " + scrollPercent + "%";
        });
})();


回答5:

I realize that this is an old question, however, I recently stumbled upon this problem myself and spent a lot of time trying to find the best working code. Everything I found was either too complicated or didn't work without lagging a lot, especially in Chrome. As pointed out by others, the problem cannot be solved by pure CSS, but I made my own simple AngularJS directive to solve the problem:

app.directive("paraBack", ['$window', function ($window) {
  return function(scope, element, attrs) {
    element.css("background-image", "url("+attrs.paraBack+")"); // Apply the background image with CSS
    element.css("background-attachment", "fixed"); // Disable background scrolling

    var max = Infinity;

    var image = new Image(); // Create a JavaScript image so that the code below can be run when the background is loaded
    image.src = attrs.paraBack;
    image.onload = function () {
      max = image.height - window.innerHeight; // Stop scrolling after the bottom of the picture is reached
      var xOffset = -(image.width/2-window.innerWidth/2);
      element.css("background-position-x", xOffset+'px'); // Horizontally align the background
    }

    var scrollHandler = function () {
      var offset = Math.floor(this.pageYOffset*0.1); // Set background to scroll at 10% of scrolling speed
      if (offset<max) {
        element.css('background-position-y', '-'+offset+'px'); // If not the bottom of the image is reached, move the background (scroll)
      }
    };

    angular.element($window).on('scroll', scrollHandler); // Set the defined scrollHandler function to be ran when user scroll

    scope.$on('$destroy', function () {
      angular.element($window).off('scroll', scrollHandler); // Unbind the function when the scope is destroyed
    });
  };
}]);

It can be used in the html like this:

<body para-back="url/to/image">

If you want to see an example of what it looks like, you can visit this page.



回答6:

Best way is to do it with jQuery. There are a lot of sites about this, for example:

  • jQuery to give impression of background scrolling slower
  • http://code.tutsplus.com/tutorials/a-simple-parallax-scrolling-technique--net-27641
  • http://callmenick.com/2014/09/08/advanced-parallax-scrolling-effect/