Ancres et déplacement progressif de l’ascenseur

Lis moi avec webReader

Une fois n’est pas coutume, voici un petit script jQuery.

NB : Stéphane soulève un problème d’accessibilité dans les commentaires, ne passez pas outre.

Il permet lors de l’activation d’une ancre de déplacer progressivement l’ascenseur de la page en fonction. J’aime personnellement beaucoup cet effet car je trouve qu’il rend plus compréhensible l’utilisation des ancres.

var scrolling = function(){
    var speed     = 1000;
    jQuery('a[href^="#"]').bind('click',function(){
        var id = jQuery(this).attr('href');
        if(id == '#')
            goTo('body');
        else
            goTo(id);
        return(false);
    });
    function goTo(ancre){jQuery('html,body').animate({scrollTop:jQuery(ancre).offset().top},speed,'swing',function(){
            if(ancre != 'body')
                window.location.hash = ancre;
            else
                window.location.hash = '#';
            jQuery(ancre).attr('tabindex','-1');
            jQuery(ancre).focus();
            jQuery(ancre).removeAttr('tabindex');
        });
    }
};

Point par point, cela donne :

var scrolling = function(){

Déclaration de la fonction, qui sera à déclencher au chargement de la page.

    var speed     = 1000;

On choisi une vitesse pour l’effet. Ce paramètre peut être modifié à loisir.

    jQuery('a[href^="#"]').bind('click',function(){

On intercepte le click sur les liens qui renvoient vers des ancres…

        var id = jQuery(this).attr('href');
        if(id == '#')
            goTo('body');
        else
            goTo(id);
        return(false);

Et on déclenche la fonction d’animation en fonction de la destination (haut de page ou ancre). On annule ensuite le comportement par défaut du lien.

    function goTo(ancre){jQuery('html,body').animate({scrollTop:jQuery(ancre).offset().top},speed,'swing',function(){

L’astuce repose sur l’utilisation de la fonction animate, qui pour le coup simplifie bien le code.

            if(ancre != 'body')
                window.location.hash = ancre;
            else
                window.location.hash = '#';

En callback, on prend soin de changer le hash dans la barre d’adresse pour ne pas différer du comportement normal.

            jQuery(ancre).attr('tabindex','-1');
            jQuery(ancre).focus();
            jQuery(ancre).removeAttr('tabindex');
        });
    }
};

On place enfin un tabindex négatif sur l’ancre, afin de pouvoir ensuite forcer le focus dessus. Ainsi, logiquement, même les lecteurs d’écrans devraient s’y retrouver.

On termine enfin par un peu de ménage.

N’hésitez pas à critiquer le tout ! La démo est disponible ici.


17 commentaires ↓

#1 Pascal le 10.05.09 à 12:31

Je trouve l’idée intéressante, tu as un exemple visible ?

#2 Goulven le 10.05.09 à 12:55

On peut voir une tite démo ?

Je suis curieux notamment de savoir si ça n’empêche pas le navigateur d’enregistrer le clic et de permettre de revenir en arrière dans la page (comme je l’avais vu sur certains sites).

(Au passage, il manque un background-repeat:no-repeat; sur la liste MarkItUp).

#3 tetue le 10.05.09 à 13:57

Si je ne me trompe pas, c’est le principe d’un de mes plugins SPIP préférés, « Ancres douces » que l’on peut apprécier sur les blogs du Monde diplo : afficher un billet commenté, puis sur les ancres de la page qui permettent de sauter aux commentaires, puis d’un commentaire à l’autre, etc.

Comme toi, j’aime beaucoup cet effet, parce qu’il explicite les liens dans la page.

#4 Shemu le 10.05.09 à 17:12

Il me semble qu’il existe un petit plugin « ScrollTo » qui ajoute cet effet de défilement doux en faisant un add-on de la fonction javascript de base « window.scrollTo ».

#5 Vincent le 10.05.09 à 18:34

Voici l’exemple qui va bien rapidement codé.

  • Goulven : OVH a eu quelques soucis cette après-midi, c’est sans doute ça.

  • tetue : du coup, tu charges quelques kilos supplémentaires avec les plugins jQuery d’Ariel Flesler, non ? Ils permettent bien plus de choses mais pour le coup, je n’en avais pas besoin.

  • Shemu : c’est justement le plugin cité plus haut il me semble.

#6 Stéphane Deschamps le 10.06.09 à 17:20

Bien.

Je sape le moral de tout le monde ?

Comme je le disais sur spip-contrib :

Le plugin « ancres douces » me pose des soucis.

Quand on clique sur un lien vers une note de bas de page sur un site normal et qu’on retourne en arrière dans son navigateur avec le clavier (alt+gauche ou retour arrière sous Windows, je n’ai pas de mac sous la main mais je crois me rappeler qu’on a le même type de combinaison), on remonte dans la page à l’endroit qu’on vient de quitter. Tout ça obéit à la mécanique classique du navigateur : le #ancre est considéré comme l’emplacement suivant de l’historique.

Avec « ancres douces », on dirait qu’il part du principe que je n’ai pas quitté l’endroit que je suis en train de lire (un return false en JS). Donc un back me fait partir… à la page précédente. (même s’il remplace à partir du # dans l’URL, en réalité je suppose que c’est juste une astuce dans l’objet URL courant, mais ça ne « déplace » pas réellement le navigateur d’un coup vers l’avant dans son historique —cette dernière remarque est une educated guess, comme on dit quand on veut frimer).

Arglü.

Ce n’est pas stratégique mais pour les niais comme moi qui font tout au clavier, c’est très déstabilisant/inconfortable.

Et c’est le même problème ici… désolé, hein. Je n’ai pas de solution, mais il m’est impossible d’entériner ce genre de système tant que je n’aurai pas de solution à prposer.

#7 Vincent le 10.06.09 à 18:47

Je ne comprend pas Stef, j’ai justement un comportement normal au niveau de l’historique moi.

Tu as testé avec un navigateur particulier ?

Je viens de le faire avec Firefox, Safari et Opera sous mac. Idem sous Firefox et IE PC.

#8 Anonyme le 10.12.09 à 13:43

Tu ne voudrais pas reproduire ton article sur jquery.info ?

#9 Stéphane Deschamps le 10.13.09 à 15:36

@Vincent : tu as un Mac ou un Windows sous la main ?

Firefox/Win : je clique sur « bas », ça scrolle gentiment.

Je fais back et je reste comme un gros niais en bas de page… et je suis triste… ;)

#10 Vincent le 10.13.09 à 15:42

Ok Stéphane, compris !

Le souci devrait pouvoir se corriger facilement en ajoutant une « ancre vide » au chargement de la page non ?

Je vais essayer ça.

#11 Vincent le 10.13.09 à 15:56

Bon… ça ne marche pas. Je suis triste aussi tiens.

:(

#12 Stéphane Deschamps le 10.13.09 à 19:58

Voilà. Tu vois mieux mon problème, maintenant ? Pour l’instant, pour moi, c’est insoluble.

#13 Vincent le 10.13.09 à 20:17

C’est problématique oui.

Néanmoins le confort apporté (notamment pour les utilisateurs néophytes) est certain. Et le cas d’utilisation que tu pointes du doigt est relativement peu fréquent.

J’avoue que je suis mitigé…

Tu conseilles de mettre à la poubelle dans tous les cas toi ?

#14 Bruno le 10.15.09 à 7:57

Je cherchais justement un effet similaire sur des pages faisant déjà appel à la bibliothèque jquery. ce script est vraiment très bien ;-) Pour contourner le problème évoqué par Stéphane (ne pas casser l’historique de navigation), il suffit de remplacer return (false) par void(0)

#15 Vincent le 10.15.09 à 9:44

On dirait bien que ça marche : merci Bruno !

#16 Stéphane Deschamps le 10.27.09 à 18:30

Bravo Bruno ! Génial !

(je vais vite le redire sur spip-contrib) :)

#17 Zacos le 03.29.10 à 11:08

Bonjour, etd’abord bravo, cet effet est exactement ce que je cherchais. A un bémol près, que je vous soumets  : avant que le script ne fasse « glisser » la page, l’ancre html a le temps de fonctionner. Du coup, avant l’effet de glissement, on a le temps de voir l’endroit cible pendant une fraction de seconde. Pour détailler ce qui se passe, au moment du clic, la page saute instantanément à la position de l’ancre, puis revient instantanément au point de départ pour retourner (en glissant harmonieusement, cette fois) vers la position de l’ancre. Lorsque la page ne contient que du texte, l’oeil ne s’en rend pas compte, mais lorsqu’il y a des images en décor de page, c’est flagrant, on a le sentiment d’un bug. Les programmeurs émérites que vous êtes auraient-ils une solution (je ne suis qu’un modeste graphiste ignorant de javascript, avec seulement quelques bases en AS3) ?


Laisser un commentaire

Mise en forme : vous pouvez utiliser la syntaxe Markdown. Vous verrez, c’est chouette !
Modération à priori : les commentaires n’apparaissent pas immédiatement en ligne.