Identifier l’élément plus large que le viewport en JavaScript

Sur mobile, un site peut parfois bouger horizontalement alors qu’aucun élément ne semble dépasser. Vous faites glisser la page vers la gauche, et une vilaine bande apparaît à droite. Elle était là, tapie dans l’ombre. Très professionnelle, évidemment.

Ce problème vient presque toujours d’un élément plus large que le viewport. Il peut s’agir d’une image, d’un tableau, d’un slider, d’un bloc WooCommerce, d’un menu mobile, d’une section en width:100vw, d’une grille CSS, ou d’un élément positionné hors écran.

Voici une méthode moderne pour identifier l’élément responsable avec Vanilla JavaScript, puis corriger proprement l’overflow horizontal sans masquer le problème sous un grand tapis CSS.

Kinsta: Premium Managed WordPress hosting

Le symptôme : un scroll horizontal sur mobile

Le cas typique : sur desktop, tout semble normal. Sur mobile, la page peut se déplacer horizontalement. Le contenu principal reste visible, mais une zone vide apparaît sur le côté droit.

Dans Chrome DevTools ou Firefox DevTools, vous pouvez reproduire le problème en mode responsive. Choisissez une largeur mobile, par exemple 375px, puis essayez de faire glisser la page horizontalement.

Si la page bouge, le document est plus large que le viewport. Pour le confirmer dans la console :

document.documentElement.scrollWidth > window.innerWidthLangage du code : CSS (css)

Si la commande retourne true, un élément dépasse horizontalement.

Vous pouvez aussi afficher les deux valeurs :

console.log({
	viewport: window.innerWidth,
	documentWidth: document.documentElement.scrollWidth,
	overflow: document.documentElement.scrollWidth - window.innerWidth,
});Langage du code : JavaScript (javascript)

Si documentWidth est plus grand que viewport, il faut trouver le coupable.

Méthode rapide : trouver les éléments qui dépassent

Voici un script Vanilla JS simple à coller dans la console du navigateur. Il liste les éléments qui dépassent à gauche ou à droite du viewport.

(() => {
	const viewportWidth = document.documentElement.clientWidth;

	document.querySelectorAll('body *').forEach((element) => {
		const rect = element.getBoundingClientRect();

		if (rect.left < 0 || rect.right > viewportWidth) {
			console.log('Élément qui dépasse le viewport :', {
				element,
				left: Math.round(rect.left),
				right: Math.round(rect.right),
				width: Math.round(rect.width),
				viewportWidth,
				overflowRight: Math.round(rect.right - viewportWidth),
			});
		}
	});
})();Langage du code : JavaScript (javascript)

Cette version utilise getBoundingClientRect(). Elle est souvent plus utile que offsetWidth, car elle tient compte de la position réelle de l’élément dans le viewport.

Le script affiche chaque élément suspect dans la console. Cliquez sur l’objet element pour le sélectionner dans l’inspecteur. Ensuite, regardez ses styles CSS, ses marges, sa largeur, son positionnement et ses parents.

Kinsta: Premium Managed WordPress hosting

Version avec surlignage visuel

Pour rendre le diagnostic plus visible, ce script ajoute un contour rouge aux éléments qui dépassent :

(() => {
	const viewportWidth = document.documentElement.clientWidth;
	const overflowingElements = [];

	document.querySelectorAll('body *').forEach((element) => {
		const rect = element.getBoundingClientRect();
		const overflowsLeft = rect.left < 0;
		const overflowsRight = rect.right > viewportWidth;

		if (!overflowsLeft && !overflowsRight) {
			return;
		}

		element.style.outline = '3px solid red';
		element.style.outlineOffset = '-3px';

		overflowingElements.push({
			element,
			left: Math.round(rect.left),
			right: Math.round(rect.right),
			width: Math.round(rect.width),
			});
	});

	console.table(
		overflowingElements.map((item) => ({
			tag: item.element.tagName.toLowerCase(),
			className: item.element.className,
			left: item.left,
			right: item.right,
			width: item.width,
		}))
	);

	console.log('Éléments qui dépassent :', overflowingElements);
})();Langage du code : JavaScript (javascript)

Cette version aide beaucoup sur les pages complexes. Cependant, elle modifie temporairement les styles inline dans le navigateur. Rechargez la page pour tout remettre à zéro.

Version propre avec data-attribute

Si vous voulez éviter de polluer les styles inline, ajoutez plutôt un attribut data-overflow-debug, puis injectez une règle CSS temporaire.

(() => {
	const style = document.createElement('style');

	style.textContent = `
		[data-overflow-debug="true"] {
			outline: 3px solid red !important;
			outline-offset: -3px !important;
		}
	`;

	document.head.appendChild(style);

	const viewportWidth = document.documentElement.clientWidth;
	const results = [];

	document.querySelectorAll('body *').forEach((element) => {
		const rect = element.getBoundingClientRect();

		if (rect.left >= 0 && rect.right <= viewportWidth) {
			return;
		}

		element.dataset.overflowDebug = 'true';

		results.push({
			element,
			tag: element.tagName.toLowerCase(),
			id: element.id || '',
			className: typeof element.className === 'string' ? element.className : '',
			left: Math.round(rect.left),
			right: Math.round(rect.right),
			width: Math.round(rect.width),
			overflowRight: Math.round(rect.right - viewportWidth),
		});
	});

	console.table(
		results.map(({ tag, id, className, left, right, width, overflowRight }) => ({
			tag,
			id,
			className,
			left,
			right,
			width,
			overflowRight,
		}))
	);

	console.log('Résultats complets :', results);
})();Langage du code : JavaScript (javascript)

Le tableau donne une vue rapide. Le log complet permet ensuite d’inspecter les éléments directement dans DevTools.

WPEngine: Premium Managed WooCommerce hosting

Nettoyer le debug après test

Pour retirer les attributs de debug sans recharger la page :

document.querySelectorAll('[data-overflow-debug]').forEach((element) => {
	delete element.dataset.overflowDebug;
});Langage du code : JavaScript (javascript)

Si vous avez ajouté des outlines inline avec la version précédente, rechargez simplement la page. C’est le moyen le plus rapide.

Pourquoi offsetWidth ne suffit pas toujours

Le script original utilisait une logique de ce type :

document.querySelectorAll('body *').forEach((element) => {
	if (element.offsetWidth > document.documentElement.clientWidth) {
		console.log('Element causing overflow:', element);
	}
});Langage du code : JavaScript (javascript)

Cette méthode reste utile pour trouver un élément dont la largeur physique dépasse le viewport. Mais elle rate certains cas fréquents.

  • Un élément peut être déplacé avec transform.
  • Un élément peut être positionné avec left, right ou une marge négative.
  • Un élément peut avoir une largeur correcte, mais être décalé hors écran.
  • Un enfant peut dépasser à l’intérieur d’un parent qui semble normal.
  • Un pseudo-élément peut créer un débordement sans apparaître dans le DOM.

Pour ces cas, getBoundingClientRect() donne une information plus exploitable, car il mesure la boîte réelle de l’élément dans le viewport.

Kinsta: Premium Managed WordPress hosting

Utiliser scrollWidth pour confirmer l’overflow

scrollWidth permet de savoir si le contenu d’un élément dépasse sa largeur visible. C’est utile pour repérer un conteneur qui déborde à cause de son contenu interne.

(() => {
	const results = [];

	document.querySelectorAll('body *').forEach((element) => {
		if (element.scrollWidth <= element.clientWidth) {
			return;
		}

		results.push({
			element,
			tag: element.tagName.toLowerCase(),
			id: element.id || '',
			className: typeof element.className === 'string' ? element.className : '',
			clientWidth: element.clientWidth,
			scrollWidth: element.scrollWidth,
			overflow: element.scrollWidth - element.clientWidth,
		});
	});

	console.table(
		results.map(({ tag, id, className, clientWidth, scrollWidth, overflow }) => ({
			tag,
			id,
			className,
			clientWidth,
			scrollWidth,
			overflow,
		}))
	);

	console.log('Éléments avec contenu horizontal débordant :', results);
})();Langage du code : JavaScript (javascript)

Cette méthode complète bien getBoundingClientRect(). La première repère les éléments visibles hors viewport. La seconde repère les éléments dont le contenu interne dépasse.

Les causes fréquentes d’un overflow horizontal

Une fois l’élément trouvé, il faut comprendre pourquoi il dépasse. Les causes reviennent souvent.

1. Une largeur en 100vw

width:100vw semble logique pour une section pleine largeur. Pourtant, sur certains navigateurs, 100vw peut inclure la largeur de la barre de scroll verticale. Résultat : l’élément devient légèrement plus large que la page.

Au lieu de :

.section {
	width: 100vw;
}Langage du code : CSS (css)

Essayez plutôt :

.section {
	width: 100%;
}Langage du code : CSS (css)

Si vous devez vraiment créer une section pleine largeur dans WordPress, inspectez aussi les marges négatives ajoutées par le thème ou le bloc.

2. Une image sans max-width

Une image trop large peut dépasser son conteneur si elle n’est pas contrainte.

img,
video,
iframe {
	max-width: 100%;
}Langage du code : CSS (css)

Pour les images, ajoutez aussi :

img {
	height: auto;
}Langage du code : CSS (css)

Sur WordPress, ce problème peut venir d’un ancien contenu HTML, d’une image injectée par un plugin, ou d’un bloc personnalisé qui ne respecte pas les styles globaux.

3. Un tableau trop large

Les tableaux sont des champions du débordement mobile. Surtout les tableaux avec beaucoup de colonnes, des URLs longues, ou des cellules non cassables.

La bonne solution consiste souvent à rendre le conteneur du tableau scrollable horizontalement, pas toute la page.

.table-wrapper {
	overflow-x: auto;
	-webkit-overflow-scrolling: touch;
}

.table-wrapper table {
	min-width: 640px;
}Langage du code : CSS (css)

Ensuite, enveloppez le tableau :

<div class="table-wrapper">
	<table>
		<!-- contenu du tableau -->
	</table>
</div>Langage du code : HTML, XML (xml)

L’utilisateur peut alors faire défiler le tableau, mais la page ne part plus en balade horizontale.

4. Un texte ou une URL trop longue

Une longue URL, une chaîne technique ou un mot sans espace peut forcer un conteneur à dépasser.

.entry-content {
	overflow-wrap: break-word;
}

.entry-content a {
	word-break: break-word;
}Langage du code : CSS (css)

Pour les blocs de code, préférez un scroll interne plutôt qu’un retour à la ligne agressif qui rend le code illisible.

.wp-block-code {
	overflow-x: auto;
}

.wp-block-code code {
	white-space: pre;
}Langage du code : CSS (css)

Si vous optimisez des articles techniques WordPress, c’est un détail important. Un bloc de code ne doit pas casser toute la mise en page mobile.

5. Une grille CSS trop rigide

Une grille CSS peut dépasser si ses colonnes ont des largeurs fixes ou des gaps trop grands.

Exemple fragile :

.cards {
	display: grid;
	grid-template-columns: repeat(3, 320px);
	gap: 32px;
}Langage du code : CSS (css)

Version plus souple :

.cards {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(min(100%, 280px), 1fr));
	gap: clamp(1rem, 2vw, 2rem);
}Langage du code : CSS (css)

La grille s’adapte alors à la largeur disponible. Moins de drame, plus de responsive.

6. Un flex item qui refuse de rétrécir

Dans un layout flex, un enfant peut dépasser parce que sa largeur minimale implicite reste trop grande. C’est fréquent avec du texte long, des images ou des cartes.

Ajoutez souvent ceci à l’enfant flex :

.flex-item {
	min-width: 0;
}Langage du code : CSS (css)

Et si nécessaire :

.flex-container {
	display: flex;
	flex-wrap: wrap;
}Langage du code : CSS (css)

Ce petit min-width:0 corrige beaucoup de débordements mystérieux dans les cartes, colonnes et layouts WooCommerce.

7. Une marge négative

Les marges négatives servent souvent à créer un effet full-width. Elles peuvent aussi envoyer un bloc hors écran.

.full-width-block {
	margin-left: calc(50% - 50vw);
	margin-right: calc(50% - 50vw);
}Langage du code : CSS (css)

Cette technique peut fonctionner, mais elle devient fragile si le thème ajoute déjà ses propres contraintes, paddings ou scrollbars.

Dans WordPress, préférez d’abord les alignements natifs alignwide et alignfull quand le thème les gère correctement.

8. Un slider ou carousel

Les sliders créent souvent un overflow horizontal pendant leur initialisation. Certains ajoutent des clones de slides, des wrappers transformés ou des largeurs inline.

Dans ce cas, vérifiez :

  • la largeur du wrapper ;
  • les clones de slides ;
  • les options responsive du slider ;
  • les paddings latéraux ;
  • les transformations translateX() ;
  • les éléments positionnés en absolu.

Évitez de corriger un slider avec un overflow-x:hidden global sur body. Corrigez plutôt le wrapper du slider ou ses options responsive.

Ne pas corriger avec body overflow-x hidden trop vite

La tentation est forte :

body {
	overflow-x: hidden;
}Langage du code : CSS (css)

Parfois, cela règle visuellement le problème. Mais cela peut aussi masquer le vrai bug. Pire, cela peut couper un menu mobile, un panneau latéral, une animation, un sticky element ou un panier WooCommerce hors-canvas.

Si vous devez vraiment cacher l’overflow globalement, faites-le comme dernier recours, après avoir identifié l’élément responsable.

Sur les navigateurs modernes, vous pouvez aussi envisager overflow-x: clip, qui coupe le dépassement sans créer de conteneur scrollable horizontal.

html,
body {
	overflow-x: clip;
}Langage du code : CSS (css)

Mais là encore, ce n’est pas une excuse pour ignorer le vrai élément fautif. Le CSS ne doit pas devenir un cache-misère avec une cape.

Correction ciblée : limiter le conteneur fautif

Une meilleure correction consiste à cibler l’élément qui dépasse.

Exemple pour une section WooCommerce trop large :

.woocommerce .products {
	max-width: 100%;
	overflow-x: clip;
}Langage du code : CSS (css)

Exemple pour un bloc Cover ou Group qui sort du viewport :

.entry-content > .alignfull {
	max-width: 100vw;
}Langage du code : CSS (css)

Exemple pour une image injectée dans un contenu ancien :

.entry-content img {
	max-width: 100%;
	height: auto;
}Langage du code : CSS (css)

La règle doit être aussi précise que possible. Plus le sélecteur est global, plus vous risquez de casser autre chose.

Utiliser DevTools pour confirmer

Après avoir identifié un élément avec JavaScript, ouvrez l’inspecteur et désactivez temporairement certaines règles CSS.

  • Désactivez width ou min-width.
  • Désactivez les marges négatives.
  • Désactivez les transforms.
  • Désactivez les paddings excessifs.
  • Désactivez les positions absolues.
  • Désactivez les règles responsive suspectes.

Le bon test : dès que le scroll horizontal disparaît, vous avez isolé la règle fautive. Ensuite seulement, écrivez la correction propre dans votre CSS.

Dans les DevTools récents, les badges de scroll peuvent aussi aider à repérer les conteneurs scrollables et les enfants qui provoquent un débordement.

Cas WordPress : blocs Gutenberg alignfull et alignwide

Sur WordPress, les blocs alignfull et alignwide peuvent créer un overflow horizontal si le thème ne gère pas correctement les largeurs, les paddings ou les marges négatives.

Vérifiez notamment :

  • les blocs Cover ;
  • les blocs Group pleine largeur ;
  • les galeries ;
  • les colonnes ;
  • les embeds ;
  • les patterns full-width ;
  • les blocs de plugins tiers.

Une correction fréquente consiste à s’assurer que le contenu ne dépasse pas la largeur disponible :

.wp-site-blocks,
.site,
.site-content,
.entry-content {
	max-width: 100%;
}Langage du code : CSS (css)

Mais cette règle reste générale. Si un bloc précis déborde, ciblez ce bloc.

Pour les articles techniques avec beaucoup de blocs de code, l’article sur l’exécution d’un shortcode dans une fonction PHP complète bien ce sujet : les contenus injectés dynamiquement doivent aussi respecter le layout du thème.

Cas WooCommerce : produits, filtres et panier latéral

WooCommerce ajoute plusieurs zones susceptibles de déborder sur mobile :

  • grilles de produits ;
  • filtres latéraux ;
  • tableaux panier ;
  • formulaires checkout ;
  • mini-panier off-canvas ;
  • badges promo ;
  • carrousels de produits ;
  • images produit avec zoom ou galerie.

Pour un tableau panier trop large, préférez un scroll interne au tableau :

.woocommerce-cart-form {
	overflow-x: auto;
	-webkit-overflow-scrolling: touch;
}

.woocommerce-cart-form table {
	min-width: 640px;
}Langage du code : CSS (css)

Pour une grille produit trop rigide :

.woocommerce ul.products {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(min(100%, 220px), 1fr));
	gap: 1.5rem;
}

.woocommerce ul.products::before,
.woocommerce ul.products::after {
	content: none;
}Langage du code : CSS (css)

Adaptez selon le thème. Astra, GeneratePress, Kadence, Flatsome ou un thème FSE ne structurent pas toujours WooCommerce de la même manière.

Pour les audits WooCommerce plus larges, le guide sur la mise à jour de la base WooCommerce avec WP-CLI rappelle une règle valable ici aussi : tester le vrai parcours client, pas seulement la page d’accueil.

Cas GeneratePress, Astra et thèmes légers

Les thèmes légers génèrent souvent peu de CSS, mais ils laissent aussi beaucoup de liberté aux blocs et aux plugins. L’overflow peut donc venir d’un bloc tiers, d’un constructeur, d’un shortcode, d’un module WooCommerce ou d’un CSS custom.

Sur un thème bien codé, ne partez pas du principe que le thème est fautif. Inspectez d’abord l’élément exact. Le débordement peut venir d’un simple bloc HTML copié depuis un ancien article.

Pour les optimisations côté thème, vous pouvez aussi consulter l’article sur l’optimisation d’un thème WordPress et des requêtes SQL. Ce n’est pas le même bug, mais la méthode est identique : mesurer, isoler, corriger.

Script complet : diagnostic responsive réutilisable

Voici une version plus complète du script. Elle détecte le débordement du document, liste les éléments suspects, les marque visuellement, puis trie les résultats par dépassement.

(() => {
	const viewportWidth = document.documentElement.clientWidth;
	const documentWidth = document.documentElement.scrollWidth;
	const overflowAmount = documentWidth - viewportWidth;

	console.log('Diagnostic viewport :', {
		viewportWidth,
		documentWidth,
		overflowAmount,
		hasHorizontalOverflow: overflowAmount > 0,
	});

	if (overflowAmount <= 0) {
		console.log('Aucun overflow horizontal détecté sur le document.');
		return;
	}

	const style = document.createElement('style');

	style.textContent = `
		[data-viewport-overflow="true"] {
			outline: 3px solid red !important;
			outline-offset: -3px !important;
		}
	`;

	document.head.appendChild(style);

	const results = [];

	document.querySelectorAll('body *').forEach((element) => {
		const rect = element.getBoundingClientRect();

		const overflowLeft = Math.max(0, Math.round(0 - rect.left));
		const overflowRight = Math.max(0, Math.round(rect.right - viewportWidth));
		const totalOverflow = overflowLeft + overflowRight;

		if (totalOverflow === 0) {
			return;
		}

		element.dataset.viewportOverflow = 'true';

		results.push({
			element,
			tag: element.tagName.toLowerCase(),
			id: element.id || '',
			className: typeof element.className === 'string' ? element.className : '',
			left: Math.round(rect.left),
			right: Math.round(rect.right),
			width: Math.round(rect.width),
			overflowLeft,
			overflowRight,
			totalOverflow,
		});
	});

	results.sort((a, b) => b.totalOverflow - a.totalOverflow);

	console.table(
		results.map(({ tag, id, className, left, right, width, overflowLeft, overflowRight, totalOverflow }) => ({
			tag,
			id,
			className,
			left,
			right,
			width,
			overflowLeft,
			overflowRight,
			totalOverflow,
		}))
	);

	console.log('Éléments suspects complets :', results);
})();Langage du code : JavaScript (javascript)

Ce script est volontairement prévu pour la console DevTools. Ne l’ajoutez pas en production. Il sert à diagnostiquer, pas à charger sur chaque page vue.

Tester plusieurs largeurs de viewport

Un overflow peut apparaître seulement à certaines largeurs. Testez au minimum :

  • 320px pour les très petits mobiles ;
  • 360px pour beaucoup d’Android ;
  • 375px pour plusieurs iPhone ;
  • 390px pour les iPhone récents ;
  • 768px pour les tablettes ;
  • 1024px pour les tablettes paysage.

Dans Chrome DevTools, activez le mode responsive, changez la largeur, puis relancez le script. Un élément peut être parfait à 390px et casser à 375px. Le responsive a son petit caractère.

Ajouter un test Playwright pour détecter l’overflow

Si vous maintenez un site ou un thème, vous pouvez automatiser ce contrôle avec Playwright. Exemple simple :

import { test, expect } from '@playwright/test';

const viewports = [
	{ width: 320, height: 800 },
	{ width: 375, height: 800 },
	{ width: 390, height: 844 },
	{ width: 768, height: 1024 },
];

for (const viewport of viewports) {
	test(`no horizontal overflow at ${viewport.width}px`, async ({ page }) => {
		await page.setViewportSize(viewport);
		await page.goto('https://www.example.com/', {
			waitUntil: 'networkidle',
		});

		const overflow = await page.evaluate(() => {
			return document.documentElement.scrollWidth - document.documentElement.clientWidth;
		});

		expect(overflow).toBeLessThanOrEqual(0);
	});
}Langage du code : JavaScript (javascript)

Ce test vérifie que la page d’accueil ne dépasse pas horizontalement. Vous pouvez ensuite l’étendre aux pages importantes : article, archive, produit WooCommerce, panier et checkout.

Checklist de diagnostic

  • Reproduire le scroll horizontal en mode responsive.
  • Comparer documentElement.scrollWidth et window.innerWidth.
  • Lancer le script getBoundingClientRect().
  • Surligner les éléments suspects.
  • Inspecter les styles dans DevTools.
  • Désactiver les règles CSS suspectes une par une.
  • Vérifier width:100vw, min-width, marges négatives et transforms.
  • Vérifier les images, tableaux, iframes et blocs de code.
  • Vérifier les sliders et menus off-canvas.
  • Tester plusieurs largeurs mobiles.
  • Corriger l’élément fautif, pas seulement le body.
  • Re-tester après purge du cache CSS.

Commandes et snippets utiles

Confirmer l’overflow horizontal :

document.documentElement.scrollWidth > window.innerWidthLangage du code : CSS (css)

Afficher la largeur du document :

console.log(document.documentElement.scrollWidth, window.innerWidth);Langage du code : CSS (css)

Trouver les éléments qui dépassent :

document.querySelectorAll('body *').forEach((element) => {
	const rect = element.getBoundingClientRect();

	if (rect.left < 0 || rect.right > document.documentElement.clientWidth) {
		console.log(element);
	}
});Langage du code : JavaScript (javascript)

CSS de base pour médias responsives :

img,
video,
iframe {
	max-width: 100%;
}Langage du code : CSS (css)

CSS pour blocs de code :

.wp-block-code {
	overflow-x: auto;
}

.wp-block-code code {
	white-space: pre;
}Langage du code : CSS (css)

CSS pour flex items trop larges :

.flex-item {
	min-width: 0;
}Langage du code : CSS (css)

Conclusion

Pour identifier un élément plus large que le viewport, commencez par confirmer l’overflow avec scrollWidth, puis utilisez getBoundingClientRect() pour lister les éléments qui dépassent réellement à gauche ou à droite.

Ensuite, inspectez l’élément fautif dans DevTools. Cherchez les causes classiques : width:100vw, image trop large, tableau, long texte, slider, marge négative, grille rigide ou flex item sans min-width:0.

La vraie correction consiste à réparer l’élément responsable. overflow-x:hidden ou overflow-x:clip peuvent dépanner, mais ils ne doivent pas devenir le réflexe principal. On ne soigne pas une fracture avec un joli pull à manches longues.

Sources

Demandez à l'IA son opinion
Gravatar for Matt Biscay

Je suis Matt Biscay, développeur WordPress & WooCommerce certifié chez Codeable, administrateur système et enseignant.

J’aide les entreprises à créer, optimiser et fiabiliser leurs sites WordPress avec une approche technique propre : performance, sécurité, maintenance, développement sur mesure et résolution de problèmes complexes.

Sur Skyminds, je partage des tutoriels WordPress, WooCommerce, Linux et administration système, avec des solutions testées sur des cas réels et pensées pour durer.

Découvrez mes services WordPress et WooCommerce.

Laisser un commentaire