Un magazine en ligne que nous accompagnons publie deux types de contenus très différents : de longs dossiers d’analyse, publiés au rythme d’un ou deux par semaine, et de courtes brèves d’actualité, publiées plusieurs fois par jour. Le réglage « Lecture » de WordPress, qui définit un nombre unique d’articles par page pour l’ensemble du site, ne peut évidemment pas satisfaire les deux logiques à la fois : douze articles par page convient bien aux dossiers, mais rend l’archive des brèves interminable à faire défiler.
Changer ce réglage général revient à choisir un compromis insatisfaisant pour l’une des deux archives. La bonne approche consiste à cibler précisément l’archive concernée avec pre_get_posts, sans toucher au réglage global qui continue de s’appliquer partout ailleurs.
Cibler une archive de type de contenu personnalisé
function mag_pagination_breves( $query ) {
if ( is_admin() || ! $query->is_main_query() ) {
return;
}
if ( $query->is_post_type_archive( 'breve' ) ) {
$query->set( 'posts_per_page', 30 );
}
}
add_action( 'pre_get_posts', 'mag_pagination_breves' );
La vérification is_main_query() reste essentielle ici : sans elle, cette modification s’appliquerait à toutes les requêtes secondaires de la page, y compris un éventuel bloc de mise en avant utilisant lui aussi le type breve, ce qui produirait un résultat incohérent.

Cibler une archive de catégorie précise
Pour une seule catégorie plutôt qu’un type de contenu entier, is_category() accepte un slug ou un identifiant en paramètre, ce qui évite d’affecter les autres catégories du site :
function mag_pagination_categorie_dossiers( $query ) {
if ( is_admin() || ! $query->is_main_query() ) {
return;
}
if ( $query->is_category( 'dossiers-approfondis' ) ) {
$query->set( 'posts_per_page', 6 );
}
}
add_action( 'pre_get_posts', 'mag_pagination_categorie_dossiers' );
Combiner plusieurs archives dans une seule fonction
Pour un site avec plusieurs cas particuliers, il est plus lisible de centraliser la logique dans une seule fonction plutôt que de multiplier les accroches sur pre_get_posts, dont l’ordre d’exécution devient vite difficile à suivre :
function mag_paginations_personnalisees( $query ) {
if ( is_admin() || ! $query->is_main_query() ) {
return;
}
$regles = array(
array( 'test' => $query->is_post_type_archive( 'breve' ), 'valeur' => 30 ),
array( 'test' => $query->is_category( 'dossiers-approfondis' ), 'valeur' => 6 ),
array( 'test' => $query->is_tag( 'brulant' ), 'valeur' => 15 ),
);
foreach ( $regles as $regle ) {
if ( $regle['test'] ) {
$query->set( 'posts_per_page', $regle['valeur'] );
return;
}
}
}
add_action( 'pre_get_posts', 'mag_paginations_personnalisees' );
Effet sur le calcul de la pagination
Modifier posts_per_page via pre_get_posts recalcule automatiquement max_num_pages en cohérence, à condition de ne pas avoir désactivé no_found_rows par ailleurs sur cette même requête : les deux réglages sont incompatibles, puisque l’un dépend directement du calcul que l’autre supprime.
Vérifications avant mise en production
- Contrôler que les liens de pagination générés par
the_posts_pagination()restent cohérents avec la nouvelle valeur sur chaque archive concernée. - Vérifier qu’aucun flux RSS de l’archive n’est affecté involontairement, puisque
is_main_query()reste vrai également en contexte de flux. - Tester le comportement sur la page d’accueil si elle affiche elle-même une archive par défaut, cas fréquent sur un site qui n’a pas défini de page d’accueil statique.
La tentation de tout régler depuis l’écran « Lecture » est compréhensible, mais elle mène systématiquement à un compromis bancal dès qu’un site publie plusieurs formats de contenu aux rythmes très différents.
En résumé
pre_get_posts, combiné aux conditions is_category(), is_post_type_archive() ou is_tag(), permet d’ajuster la pagination archive par archive sans jamais toucher au réglage général du site. Cette approche laisse intact le comportement de la recherche interne, qui répond à une problématique de pagination différente déjà traitée séparément.