# « Skip link target not found » : une ancre supprimée casse le lien

> Un audit Lighthouse signale un lien d'évitement mort après une refonte de menu. Symptôme, recherche dans le DOM, correctif de l'ancre, et prévention par un test automatisé.

- Auteur : WordPress Développement
- Publié le : 2020-10-21
- Mis à jour le : 2020-10-21
- Catégorie : Accessibilité
- URL : https://www.wpmoderne.fr/accessibilite/skip-link-target-not-found-ancre-supprimee/

## L’essentiel

- Le lien d'évitement pointe vers un id qui n'existe plus après la refonte
- Le correctif tient en une ligne dans le gabarit du contenu
- Un test automatisé évite que l'erreur revienne à chaque refonte

« Skip link target not found » : ce message apparaît dans le rapport Lighthouse, section accessibilité, après une refonte du menu principal d'un thème vitrine. Le lien d'évitement en haut de page, celui qui permet de sauter directement au contenu, existait depuis des mois sans problème. Ce qui a changé, ce n'est pas le lien lui-même, mais sa cible.

## Symptôme : un score qui chute sans modification visible

Rien ne semble cassé à l'œil nu : le lien « Aller au contenu principal » est toujours présent en haut de la page, il reste le premier élément atteignable au `Tab`, son style visuel n'a pas bougé. Pourtant Lighthouse, dans la catégorie accessibilité, remonte l'avertissement `skip-link` avec le message `Skip link target not found`. Un test manuel confirme le problème : activer le lien avec la touche `Entrée` ne déplace ni le focus, ni la position de défilement.

## Diagnostic dans le DOM

La cause se trouve en général dans l'attribut `href` du lien d'évitement, comparé à l'identifiant réellement présent dans le gabarit de contenu. Sur ce projet, le lien pointait vers `#contenu` :

```
<a class="lien-evitement" href="#contenu">Aller au contenu principal</a>
```

Mais la refonte du menu, qui a réorganisé les gabarits pour introduire un méga-menu, a déplacé l'ouverture de la zone principale dans un nouveau fichier `template-parts/contenu-principal.php`. Ce fichier ouvre la région avec :

```
<main id="main-content">
```

L'identifiant a changé de `contenu` à `main-content` lors de cette réorganisation, sans qu'aucune recherche globale n'ait été faite sur l'ancien identifiant. Le lien d'évitement pointe donc vers une ancre qui n'existe plus nulle part dans le document, et le navigateur ne fait rien quand on l'active : ni déplacement du focus, ni défilement.

> L'essentiel à retenir : Le lien d'évitement pointe vers un id qui n'existe plus après la refonte ; Le correctif tient en une ligne dans le gabarit du contenu ; Un test automatisé évite que l'erreur revienne à chaque refonte

## Correctif : réaligner le lien et l'ancre

Deux options existent pour corriger ce décalage, selon la source de vérité qu'on choisit de garder. La première consiste à mettre à jour le lien d'évitement pour qu'il pointe vers le nouvel identifiant :

```
<a class="lien-evitement" href="#main-content">Aller au contenu principal</a>
```

La seconde, souvent préférable quand plusieurs gabarits utilisent le même identifiant historique, consiste à renommer la cible dans le nouveau fichier pour rester cohérent avec l'existant :

```
<main id="contenu">
```

Dans les deux cas, il faut vérifier que l'élément ciblé peut recevoir le focus programmatique. Un `<main>` reçoit le défilement automatique du navigateur, mais pour que le focus clavier s'y positionne réellement après activation du lien (utile pour l'annonce par un lecteur d'écran), on ajoute `tabindex="-1"` sur la cible.

## Prévention par un test automatisé

Pour éviter que cette régression revienne à chaque refonte de gabarit, un test simple s'intègre facilement dans une suite existante. L'idée : extraire l'attribut `href` du lien d'évitement et vérifier qu'un élément portant cet identifiant existe bien dans la page rendue.

```
test('le lien d\'évitement pointe vers une ancre existante', async ({ page }) => {
  await page.goto('/');
  const cible = await page.getAttribute('.lien-evitement', 'href');
  const id = cible.replace('#', '');
  const element = page.locator(`#${id}`);
  await expect(element).toHaveCount(1);
});
```

Ce test, exécuté sur chaque page type du thème (accueil, article, page), attrape immédiatement une future réorganisation de gabarit qui renommerait l'identifiant sans mettre à jour le lien correspondant.

> Sur ce type de régression, l'outil automatisé donne le symptôme mais jamais la cause exacte : c'est la recherche de l'identifiant dans l'ensemble des gabarits qui révèle où la refonte a rompu le lien.

### Étendre la vérification aux autres ancres du gabarit

Une fois ce correctif appliqué, il vaut la peine de vérifier si d'autres liens internes du thème reposent sur des ancres du même type : un sommaire en haut d'un article long, un lien « Retour au formulaire » après un message de confirmation, ou un lien vers une section précise du pied de page. Chacun de ces liens partage exactement le même risque qu'une refonte future casse silencieusement, sans qu'aucune erreur visible n'apparaisse ailleurs que dans un futur audit.

```
grep -rn 'href="#' wp-content/themes/mon-theme/*.php
```

Cette recherche, à exécuter après toute réorganisation de gabarit, liste chaque lien d'ancre du thème et permet de vérifier, un par un, que l'identifiant ciblé existe encore dans le fichier correspondant.

## En résumé

Un lien d'évitement mort ne se voit pas à l'écran, seulement au clavier ou dans un rapport d'audit. La cause vient presque toujours d'une refonte de gabarit qui a renommé l'identifiant de la cible sans toucher au lien lui-même. Un test automatisé qui compare systématiquement les deux, exécuté sur chaque type de page et étendu aux autres ancres internes du thème, évite que le problème ne se reproduise à la prochaine refonte de menu.
