web-dev-qa-db-fra.com

(CSS) Faire défiler une image de fond plus lentement que tout le reste

voici mon code CSS pour le corps:

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

Ce que je veux faire est de faire en sorte que l'image défile plus lentement que tout le reste de la page pour créer un simple effet de parallaxe. J'ai regardé en ligne et tous les exemples que j'ai vus sont beaucoup plus compliqués que ce que je veux.

31
BananaPineapple

Je suis tombé par hasard sur cette recherche de plus de flexibilité dans ma vitesse de parallaxe que j'ai créée avec du CSS pur et je veux juste souligner que tous ces gens ont tort et que c'est possible avec du CSS pur Il est également possible de mieux contrôler la hauteur de votre élément.

Vous devrez probablement éditer votre DOM/HTML un peu pour avoir des éléments de conteneur, dans votre cas, vous appliquez l’arrière-plan au corps qui vous restreindra beaucoup et qui ne semble pas être une bonne idée.

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

Voici comment vous contrôlez la hauteur avec les longueurs en pourcentage de Viewport basées sur la taille de l'écran:

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;
  }

La vitesse de la couche est contrôlée par une combinaison des valeurs de la perspective et de la translation Z. Les éléments avec des valeurs Z négatives défileront plus lentement que ceux avec une valeur positive. Plus la valeur est 0, plus l'effet de parallaxe est prononcé (c'est-à-dire translateZ (-10px) défilera plus lentement que translateZ (-1px)).

Voici une démo que j'ai trouvée avec une recherche sur Google parce que je sais qu'il y a beaucoup de non-croyants, ne dites jamais impossible:

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

63
Neo

vous pouvez utiliser quelque chose de simple comme ici: html:

Mouvement

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;

    });
  };

})();

Voici jsfiddle

5
Piotr Ciszewski

Si vous voulez appliquer une image d’arrière-plan très haute, utilisez ce 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 + "%";
        });
})();
3

Je sais que c'est très tard, mais je me suis demandé si cela ne fonctionnerait pas plus facilement que les codes ci-dessus et j'ai investi 15 minutes de ma vie.
Voici mon code:

document.getElementById("body").onscroll = function myFunction() {  
    var scrolltotop = document.scrollingElement.scrollTop;
    var target = document.getElementById("main1");
    var xvalue = "center";
    var factor = 0.5;
    var yvalue = scrolltotop * factor;
    target.style.backgroundPosition = xvalue + " " + yvalue + "px";
  }
#main1 {
    background-image: url(https://images.unsplash.com/photo-1506104489822-562ca25152fe?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9);
    background-position: top center;
    background-attachment:scroll;
    background-size: cover;
    height: 80vh;
    width: 100%;
}
#placeholdersoyoucanscroll{
    height:100vh
}
<body id="body">
      <main>
        <div id="main1">
        </div>
        <div id="placeholdersoyoucanscroll">
        </div>
    </main>
</body>
1
Tim T.

Je me rends compte que c'est une vieille question, cependant, je suis récemment tombé sur ce problème moi-même et j'ai passé beaucoup de temps à essayer de trouver le meilleur code qui fonctionne. Tout ce que j'ai trouvé était soit trop compliqué, soit ne fonctionnait pas sans beaucoup de retard, en particulier dans Chrome. Comme l'ont souligné d'autres personnes, le problème ne peut pas être résolu avec du CSS pur, mais j'ai créé ma propre directive simple AngularJS pour résoudre le problème:

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
    });
  };
}]);

Il peut être utilisé dans le code HTML comme ceci:

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

Si vous voulez voir un exemple de ce à quoi cela ressemble, vous pouvez visiter cette page .

1
tjespe

Convenez que css n'est pas possible uniquement, car vous devez calculer le rapport de hauteur de l'image et du document. J'aime aussi cet effet, c'est pourquoi j'ai créé une fonction simple qui ne fait que ça. Voici la fonction et son appel à l'événement de défilement:

$(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';
}

Vous pouvez le trouver ici avec un exemple et une explication visuelle de ce qui se passe réellement avec l'image et le document:

défilement d'image d'arrière-plan lisse

1
Vuk Djapic