Évolutions : accessibilité, offset, dépendance à jQuery.scrollTo
Quelques réflexions en vrac sur des évolutions possibles. edit : c'est pas en vrac en fait, tout est lié :)
Dépendance à jQuery.scrollTo
Spip fournit déjà un script pour défiler en douceur vers un élément, il est utilisé pour les rechargements ajax notamment : https://git.spip.net/spip/spip/src/branch/master/prive/javascript/ajaxCallback.js#L193
Il s'utilise de cette façon :
// Pour une ancre
$(window.location.hash).positionner();
// Pour un élément
$('#mon-element').positionner();
On pourrait se reposer dessus au lieu d'utiliser la lib jQuery.scrollTo : moins de javascript à charger.
Gestion des offset
Un autre avantage, c'est qu'à partir de Spip 4 on peut définir facilement un offset pour les cas où il y aun élément fixe en haut de la page, typiquement les headers.
Il suffit de déclarer une variable jQuery.spip.positionner_marge
.
Cela fonctionnerait donc à la fois pour l'ajax et les ancres.
Accessibilité
Les utilisateur⋅trices ayant des handicaps visuels peuvent choisir de réduire les animations du navigateur. Dans ce cas là, en javascript ça n'en tient pas compte, ça force l'animation pour tout le monde : pas super pour l'accessibilité.
Mais de nos jours, on peut faire un défilement doux purement en CSS tout en tenant compte du réglage pour limiter les animations, le support est de 80% pour l'instant.
/* Défilement doux vers les ancres */
html {
scroll-behavior: smooth;
}
/* Accessibilité : respecter le choix des personnes ayant choisi de réduire les animations */
@media (prefers-reduced-motion: reduce) {
html {
scroll-behavior: auto;
}
}
Et peut-être qu'il serait possible de gérer l'offset purement en CSS également en générant un bout de CSS en js. De cette façon on ne déclare l'offset qu'à un seul endroit, et ça fonctionne partout : rechargements ajax et ancres douces en CSS.
/**
* Ajouter un pseudo élément égal à l'offset aux cibles des ancres internes
* afin qu'elles ne soient pas masquées par les éléments en position fixe en haut de la page.
* @see https://stackoverflow.com/a/28824157
*/
:target::before {
content: "";
display: block;
height: /* ici la valeur de jQuery.spip.positionner_marge */
margin: /* ici la valeur inverse de jQuery.spip.positionner_marge */
}
Ça pourrait être un mélange des 2 : la solution en JS pour les vieux navigateurs, la solution purement CSS accessible pour les récents.