Scrollblur
En tant que « fou de design », je cherche bien sûr toujours de l'inspiration, et quoi de mieux que de passer de temps en temps sur les sites des grandes agences ; c'est ainsi que j'atterris aussi parfois sur le site de Syzygy. En faisant défiler la page, j'ai bien sûr remarqué que l'image d'en-tête de la page d'accueil devient peu à peu floue à mesure qu'on descend dans la page. Je veux ça aussi ! Plutôt sympa ! Il fallait bien sûr le reproduire, et c'était particulièrement intéressant pour moi car je partais du principe qu'il n'existait pas de propriété CSS pour une « image floue » (et je me suis visiblement trompé). Au lieu d'aller d'abord chercher sur StackOverflow, j'ai donc opté pour une autre méthode, et je présente ici brièvement les deux possibilités. Peut-être que quelqu'un trouvera l'effet aussi impressionnant que moi et pourra s'inspirer de mon code.
Possibilité 1 : le fondu
La première approche consistait simplement à superposer deux images et à faire disparaître l'une des deux au défilement, proportionnellement à la position de défilement. Pour cela, il nous faut l'image en deux versions : une avec effet de flou, une sans. J'ai donc retouché l'image originale dans Photoshop avec le flou gaussien et réglé un flou de 8 px (il faut un peu expérimenter avec ces valeurs selon l'image).
Comme je voulais aussi construire cela comme image héros (pleine largeur, baby) comme chez Syzygy, j'ai défini une div avec 100 % de largeur et position:relative; et mis l'image floue en background-image. Dans cette div vient une autre div à 100 % de largeur et 100 % de hauteur, en position:absolute et avec comme background-image l'« image non floue », de sorte que l'image nette recouvre l'image floue, c'est-à-dire que la div supérieure avec l'image nette cache la div avec l'image floue. Dès que l'on défile, nous faisons disparaître lentement la div « intérieure » (= nette), de sorte que la div « extérieure » (= floue) apparaît. Jusque-là, rien de compliqué. Seul le calcul de la valeur d'opacité pourrait causer quelques maux de tête.
Après un peu d'expérimentation, je suis arrivé à la solution suivante : nous voulons, dès que l'image est entièrement sortie du viewport par défilement, une opacité de 0 pour la div intérieure, afin que la div extérieure avec l'image floue devienne visible. Il nous faut donc d'abord 1 % de la hauteur de l'image pour nous repérer, ce que nous pouvons calculer par
100 / $('#hero-image-inner').height()
Nous multiplions cette valeur par la position de défilement en px (= le nombre de pixels dont nous avons déjà défilé). Nous soustrayons cette valeur de 1, car nous voulons une valeur d'opacité décroissante (opacité 1 signifie visible, opacité 0 invisible). Personnellement, je divise encore la valeur par 50, car je veux déjà obtenir 100 % de flou à 50 %. Sinon, l'image ne serait « non floue » (= la div intérieure a une opacité de 0) que lorsque l'utilisateur aurait défilé assez loin pour ne plus voir l'image. Ce serait idiot, bien sûr. Mais le code en dit plus que mille mots :
Javascript
$(document).on('scroll', function(){
$("#hero-image-inner").css("opacity", 1 - (100 / $('#hero-image-inner').height() * $(document).scrollTop()) / 50);
});
HTML
<div class="hero-image-outer">
<div id="hero-image-inner"></div>
</div>
Possibilité 2 : le filtre CSS
(Ici, une vidéo aurait normalement été intégrée pour montrer la deuxième variante.)
La deuxième possibilité, qui était nouvelle pour moi aussi, règle le filtre CSS « blur » selon la distance déjà parcourue par le défilement. Si vous n'avez pas encore travaillé avec, vous pouvez trouver une introduction aux filtres CSS chez W3Schools. Avec cette variante, nous n'avons pas besoin de Photoshop ni d'un logiciel de retouche d'image, car l'effet est généré directement dans le navigateur. La fonction jQuery se déclenche maintenant à chaque défilement et recalcule le « filtre de flou ». La variable percent est calculée différemment de ci-dessus, car le filtre de flou attend une valeur de 0 à 100 et non de 0 à 1. percent se calcule donc à partir de la hauteur totale de l'image en pixels multipliée par la position de défilement actuelle. Si nous défilons par exemple de 2 px vers le bas, la valeur de flou serait exactement 400 pour une image de 200x200. Ce serait un peu beaucoup, car toute l'image serait alors floue dès le premier pixel. Nous n'avons donc besoin que d'une fraction de la valeur, que nous calculons en utilisant une « valeur partielle » (ici 20), par laquelle nous divisons la valeur calculée. Si vous voulez une animation plus rapide ou plus lente, jouez simplement un peu avec le diviseur 20 : une valeur plus élevée donne une animation plus rapide, une valeur plus basse, en conséquence, une animation plus lente.
HTML
<img src="images/clearimage.png" id="heroimage">
Javascript
$(document).on('scroll', function(){
var percent = (20 / $('#heroimage').height() * $(document).scrollTop());
$("#heroimage").css("filter", "blur(" + percent + "px)");
$("#heroimage").css("filter", "filter:progid:DXImageTransform.Microsoft.Blur(PixelRadius='(" + percent + "')");
});
Ici, très important : le calcul de la valeur d'opacité / de flou, je l'ai trouvé par essais et erreurs. Il se peut que ce ne soit pas la solution la plus performante ni la meilleure. Si quelqu'un peut proposer une solution plus « propre », qu'il ou elle n'hésite pas à me la communiquer dans les commentaires.
TL;DR
- Possibilité 1 : superposer deux images (floue et nette), faire disparaître l'une
- Possibilité 2 : filtre CSS blur
- Calcul du pourcentage : hauteur de l'image * position de défilement