Une agence partenaire nous a signalé un problème sur la page catégorie d’une boutique WooCommerce fraîchement refondue : à la souris, tout semblait normal, les cartes produit s’affichaient dans une grille propre à trois colonnes. Mais dès qu’un testeur clavier appuyait sur Tab pour parcourir les fiches, le focus sautait d’une carte à une autre dans un ordre qui ne correspondait à rien de visible à l’écran : de la carte en haut à gauche, il passait directement à celle du milieu de la deuxième ligne, puis revenait en haut à droite.
Ce type de bug est particulièrement déroutant pour un utilisateur de clavier, car il perd tout repère spatial : impossible de prédire où le focus va atterrir après la prochaine pression sur Tab. Voici comment nous avons remonté jusqu’à la cause exacte.
Symptôme : un focus qui saute sans logique apparente
En activant l’indicateur de focus visible du navigateur et en parcourant la grille touche par touche, nous avons noté sur papier l’ordre réel de passage du focus : carte 1, carte 4, carte 2, carte 6, carte 3, carte 5. L’ordre visuel attendu aurait été 1, 2, 3, 4, 5, 6, de gauche à droite puis de haut en bas. L’écart maximal entre position visuelle et position de tabulation atteignait six rangs sur une grille de neuf cartes.
Diagnostic : la propriété CSS order en cause
L’intégrateur qui avait réalisé la refonte souhaitait mettre en avant certains produits en promotion en les faisant apparaître visuellement en premier, sans toucher à l’ordre dans lequel WooCommerce générait les fiches dans le HTML. Il avait utilisé la propriété CSS order, disponible sur les enfants d’un conteneur en display: grid ou display: flex, pour repositionner visuellement certaines cartes :
.produit-en-promo {
order: -1;
}

Cette propriété modifie uniquement l’ordre de peinture des éléments à l’écran. Elle ne touche à aucun moment à l’ordre des éléments dans le document HTML sous-jacent. Or, la navigation au clavier avec Tab suit strictement l’ordre du DOM, jamais l’ordre visuel produit par CSS. Le navigateur affichait donc les produits en promotion en premier visuellement, tout en gardant leur position réelle, plus loin dans le document, pour la navigation clavier.
Correctif : réordonner dans le HTML, pas en CSS
La correction propre consistait à faire en sorte que WooCommerce génère directement les fiches produit dans l’ordre voulu, plutôt que de tricher visuellement après coup. Nous avons utilisé le filtre woocommerce_shortcode_products_query pour ajuster la requête de tri des produits en fonction d’une méta-donnée « en promotion », de sorte que l’ordre du DOM corresponde exactement à l’ordre visuel souhaité :
add_filter('woocommerce_shortcode_products_query', function ($args) {
$args['meta_key'] = '_en_promotion';
$args['orderby'] = 'meta_value_num title';
$args['order'] = 'DESC';
return $args;
});
Une fois ce tri appliqué en amont, la propriété CSS order est devenue superflue et a été retirée de la feuille de style. L’ordre visuel et l’ordre de tabulation ont alors coïncidé parfaitement, sans aucune divergence.
Vérification après correctif
Nous avons repris le même relevé qu’au début du diagnostic : carte 1, carte 2, carte 3, carte 4, carte 5, carte 6, dans l’ordre visuel exact. Le test a été refait sur trois résolutions d’écran différentes, car une grille responsive peut réorganiser ses colonnes selon la largeur disponible, ce qui aurait pu réintroduire un écart sur mobile si le tri avait dépendu du CSS plutôt que du DOM.
- Bureau, trois colonnes : ordre cohérent
- Tablette, deux colonnes : ordre cohérent
- Mobile, une colonne : ordre cohérent
Prévention pour les futures refontes
La propriété CSS order reste utile dans des cas précis, par exemple pour adapter une mise en page entre desktop et mobile sans dupliquer le HTML. Mais dès qu’elle sert à créer un ordre de lecture ou de priorisation éditoriale, comme mettre en avant des produits, elle devient un piège pour la navigation clavier. Notre règle interne, ajoutée depuis à notre guide de recette, est simple : toute utilisation de order doit être justifiée en revue de code, et jamais utilisée pour exprimer une priorité de contenu qui devrait plutôt être décidée au niveau de la requête ou du gabarit PHP.
CSS décide de ce que l’œil voit en premier. Le DOM décide de ce que le clavier rencontre en premier. Les deux ordres n’ont aucune obligation de coïncider, et c’est précisément ce qui rend ce bug si facile à introduire sans s’en rendre compte.