Étendre les liens en JavaScript (ou en CSS)
L’astuce d’aujourd’hui est un bout de code que j’utilise sur quasiment tous les sites que je réalise. Elle me sert à concilier une bonne pratique de référencement et une bonne pratique d’ergonomie qui restaient jusqu’ici incompatibles.
Dans l’univers du référencement, l’ancre d’un lien doit idéalement être un texte de quelques mots vecteurs de sens. Ce lien doit également être unique au sein du document, pour ne pas diluer le jus de référencement transféré vers la page cible. Par exemple : dans une liste d’article de blog on mettra le lien vers la page sur le titre.
Dans l’univers de l’ergonomie c’est un peu différent. Toujours dans cette liste d’article : l’internaute sait qu’un clic sur le titre l’emmènera sur la page de détail, mais il s’attend aussi à pouvoir cliquer sur l’image de miniature ou sur le texte « lire la suite ». En fait au niveau de la navigation le mieux c’est quand un bloc est cliquable intégralement.
Ces deux approches semblent opposées. Cependant l’optimisation des liens pour le SEO ne concerne que le code source de la page, celui qui sera analysé par les moteurs. L’approche ergonomique s’adresse au DOM ; la page calculée par le navigateur.
Entre les deux il y a – souvent – JavaScript !
Edit : en re-effectuant un test ce matin, après avec discussion avec des confrères, je me rend compte que cette solution n’est pas optimale. Je la laisse pour la postérité et vous invite à utiliser l’astuce uniquement CSS détaillée plus bas dans l’article.
La solution que je propose, c’est de placer les liens sur les textes idéals pour le référencement, puis au chargement de la page, les déplacer sur des éléments parents. Ainsi on conserve le meilleur des deux mondes.
Quel balisage mettre en place pour utiliser cette astuce ?
Afin d’utiliser le petit code JavaScript que je vais vous donner, il est nécessaire d’adapter le markup (le balisage de votre document). Sur les balises <a/>
que nous voudrons étendre, nous allons ajouter un attribut data-expand-link
, et sur les éléments parents que nous souhaiterons transformer en lien nous ajouterons l’attribut data-expand-target
.
Par défaut, il faut aussi choisir ce que deviendra le lien d’origine… le parent deviendra forcément un <a/>
, mais en fonction de l’ergonomie ou des éléments contenants, on peut souhaiter que l’ancien lien devienne un <span/>
, une <div/>
ou un <button/>
par exemple…
Je propose que le lien devienne une balise <div/>
par défaut, mais qu’en ajoutant un attribut data-expand-type="span"
on puisse définir un comportement différent.
Le code de transformation des balises
Pour mettre en place notre astuce, il nous faut créer un fichier JavaScript que nous chargerons par le biais d’un traditionnel wp_enqueue_script
(dans votre thème ou dans une extension) :
Dans ce fichier, on s’assure que le document est complètement chargé et que jQuery est bien présent. Ensuite nous allons écrire les deux fonctions nécessaires :
La première, ligne 2, nous permet de transformer la nature d’une balise, sans modifier ses attributs ni ce qu’elle contient.
La fonction suivante, nommée applyExpandLink()
ligne 16, parcours le contenu à la recherche des liens à étendre. Pour chacun d’eux elle localise le parent qui deviendra le lien, elle lui transfert ses attributs puis change la nature des deux balises.
Si vous utiliser ce script sur un site qui charge des contenus dynamiquement, vous pourrez re-exécuter applyExpandLink()
pour forcer la fonction à reparcourir le document et exécuter les transformations sur les liens fraichement insérés.
Une dernière précision pour finir : le seul élément que ne peut pas contenir un lien, c’est un autre lien ! Soyez donc vigilant à ne pas mettre plusieurs <a/>
dans une même balise ayant l’attribut data-expand-target
. Dans les faits cela ne changerait rien (c’est la magie des spécifications HTML5 qui prévoient les comportements des navigateurs en cas d’erreur ????) mais votre document calculé ne serait plus valide.
Edit : en CSS c’est mieux
Comme je le disait en introduction, c’est une astuce que j’utilise depuis de nombreuses années. À l’époque j’avais fait un test pour être sur que Google n’interprétait pas la modification du DOM en javascript. Suite à la publication de cet article et une discussion sur le slack j’ai décidé de refaire la vérification. Les résultat est vite tombé : Google interprète ce genre de manipulation légère, et cette pirouette en JavaScript n’est donc plus la bonne solution (par contre Google ne donne pas suite aux requête ajax, ce qui m’avais conforté dans l’erreur lors de mes tests plus récents).
Pour rendre l’ensemble du lien d’un bloc cliquable, il reste une solution pure CSS dont les bases sont issues de cet article d’HTeuMeuLeu et que j’ai légèrement modifié.
L’idée c’est toujours d’avoir un lien, et un élément contenant (gardons leurs les attributs data-expand-target
sur le parent et data-expand-link
sur le lien, comme pour la méthode JS), mais cette fois-ci nous allons utiliser un pseudo élément du lien pour le faire déborder, en CSS du lien. Il suffit donc de mettre ce code CSS dans votre feuille de style :
Par rapport à l’article d’HTeuMeuLeu j’ai juste ajouté un overflow:hidden
sur l’élément conteneur et une marge négatif sur le pseudo-élément. En effet, si le lien est positionné autrement qu’en static le pseudo-élément serait bloqué aux frontière du lien, le margin:-250px
(il est possible de mettre plus si besoin) permet de le propager au-delà, et l’overflow de cacher ce qui dépasse de l’élément parent.Voilà…
En partant du même constat et avec un éclairage accessibilité plutôt que SEO / ergo, je suis arrivé à une solution différente : mettre plusieurs vers la même cible (titre, « lire la suite », miniature) ainsi ils sont tous utilisables, cependant j’en sors deux de l’index de tabulation et de la liste des liens — tel qu’exposée par un lecteur d’écran — en leur conférant un
aria-hidden="true"
et untabindex="-1"
.Ainsi le lien vers l’article n’apparaît qu’une fois dans la liste de liens exposée, et en naviguant on ne franchit qu’un seul lien au lieu de trois (ce qui se traduit par un confort et une navigation plus fluide au clavier).
L’idée a été proposée par Johan Ramon, dans cette présentation : http://www.johanramon.fr/accessibiliser-subtilite/ (allez au slide 13, mais lisez aussi le reste, hein :p).
Je n’ai cependant pas réfléchi aux impacts SEO, je suppose malheureusement que les liens sont suivis et donc « diluent le jus », pour parler le jargon.
Effectivement cela fonctionne parfaitement en terme d’accessibilité 🙂
Thomas Villain m’a aussi parlé d’une autre astuce qui consiste à jouer du css pour faire dépasser un pseudo élément d’une balise
<a/>
pour l’étendre aux limites de son parent. Par contre du coup ça veut dire que l’on ne peut pas utiliser de règle de positionnement css à l’intérieur du parent.Merci pour ce partage.
As tu des exemple concret de cette mise en place ?
Merci
<h2>
et repositionnés sur le bloc 🙂Comme tu le commentes un peu plus haut, moi je suis partisan d’un :before en position: absolute qui occupe toute la widht et la height de son container.
C’est facilement faconnable pour etre rendu accessible et le CSS est super simple du coup.
Une petite mixin SASS et le tour est joué! 🙂
– Si le lien est positionné, il faut alors jouer avec la marge négative pour aller jusqu’aux bords du conteneur (cela dépend des cas) ;
– s’il y a un élément en
overflow:hidden
entre le lien et son wrapper, l’astuce ne fonctionnera pas (c’est par exemple le cas si on souhaite faire un contexte de formatage de blocs) ;– Les effets
:focus
sur le lien ne pourront pas remonter sur le conteneur :-/ ;– On est obligé de se « sacrifier » un pseudo-élément qui peut servir au design.
Après, ces défauts sont évidemment à nuancer 🙂