Skip to content

Home / Case studies

Product badges show through the sticky header on mobile

Symptoms

After we restyled the SALE badges and Wishlist hearts on product photos, the store owner sent a screenshot from their phone. When scrolling, the badge and the heart slid over the sticky header with the menu instead of disappearing under it.

Environment

WordPress with WooCommerce and a page builder. The header is sticky (position: sticky). The badges are absolutely positioned in the corner of the photo and have a z-index so they sit above the image.

Diagnosis

  • It didn't show on desktop. On mobile the header is shorter and more product cards scroll underneath it.
  • In DevTools: the header itself had a high z-index, but it was wrapped in a page builder container with z-index: 1, which created its own stacking context. From the outside, the whole header behaved as layer 1.
  • The badges had a z-index higher than 1 and weren't in a stacking context of their own. So they competed directly with the header's wrapper, and won.
Why the badge beat a header with a high z-index The header had z-index 999, but inside a wrapper with z-index 1, so from the outside it counted as 1. The badge with z-index 5 beat it. After adding isolation: isolate to the product card, the badge competes only inside the card. Before header wrapper · z-index: 1 menu header z-index: 999 product card badge · 5 5 > 1 → badge is above the header After header wrapper · z-index: 1 menu header z-index: 999 card · isolation: isolate badge · 5 5 applies only inside the card z-index is compared only within the same stacking context.
The header had z-index 999, but inside a wrapper with z-index 1, so from the outside it counted as 1. The badge with z-index 5 beat it. After adding isolation: isolate to the product card, the badge competes only inside the card.

Cause

z-index is only compared within the same stacking context. A high number inside a wrapper with z-index: 1 doesn't help against an element outside it with 2 or more.

Risks if left untreated

On mobile, where most customers shop today, the site looks broken: badges slide over the menu and cover it. A small flaw, but it erodes trust in the shop and can block navigation. An amateur fix that just raises z-index numbers only moves the problem elsewhere.

Fix

Instead of raising the header's numbers (and fighting the page builder), we put the badges in a stacking context of their own:

.woocommerce ul.products li.product,
.single-product .elementor-widget-container:has(> span.onsale),
.single-product .woocommerce-product-gallery {
  isolation: isolate !important;
}

isolation: isolate turns the product card and the product page photo into a separate layer. The badge stays above the photo inside the card, but the card as a whole behaves like regular content relative to the header. The CSS lives in a separate mu-plugin, so reverting means deleting one file.

Verification

After purging the cache, we went through the shop, a category and a product page with its Related products section on both mobile and desktop. The badges and the heart sit above the photo and slide under the header when scrolling.

Prevention and lessons

When you give an element a z-index, wrap its parent with isolation: isolate. The number then only applies inside it and never collides with a sticky header or a popup. Test scrolling on mobile, not just a static screenshot.

Related services: Crashes and errors Online store and checkout

Having similar symptoms?

Send me your website address and describe its symptoms. The diagnosis is free and non-binding. I usually reply within one business day.

Describe the symptoms

or email me directly at [email protected]