← back to Designer Wallcoverings
DW collection+home oversized-images: corrected root cause + tested CSS fix (stale Boost fallback suppression + home grid net)
3142bb5b8b44c6485e19faa244ee2ddca013dc6f · 2026-06-23 13:30:41 -0700 · Steve Abrams
Files touched
A shopify/grid-js-fix/dw-collection-grid-fix.cssA shopify/grid-js-fix/verify-final-css-fix.js
Diff
commit 3142bb5b8b44c6485e19faa244ee2ddca013dc6f
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Tue Jun 23 13:30:41 2026 -0700
DW collection+home oversized-images: corrected root cause + tested CSS fix (stale Boost fallback suppression + home grid net)
---
shopify/grid-js-fix/dw-collection-grid-fix.css | 82 ++++++++++++++++++++++++++
shopify/grid-js-fix/verify-final-css-fix.js | 58 ++++++++++++++++++
2 files changed, 140 insertions(+)
diff --git a/shopify/grid-js-fix/dw-collection-grid-fix.css b/shopify/grid-js-fix/dw-collection-grid-fix.css
new file mode 100644
index 00000000..d6e060d2
--- /dev/null
+++ b/shopify/grid-js-fix/dw-collection-grid-fix.css
@@ -0,0 +1,82 @@
+/* =====================================================================
+ DW collection + homepage "huge images" fix (dw-collection-grid-fix.css)
+ Owner: vp-dw-commerce · 2026-06-23
+ Corrected root cause (measured in-browser at 1440 + 390):
+ - COLLECTION: stale Boost server-rendered theme fallback markup
+ (.boost-sd__product-filter-fallback > section.collection + loose
+ article.product-list-item) stays visible AFTER Boost hydrates, stacking
+ full-width theme cards below the real grid. The GOOD hydrated grid lives
+ under .boost-sd-container (NOT in .product-list-item), so we can hide the
+ stale theme branch without touching the live Boost grid.
+ - HOMEPAGE: featured-collection .product-list-item cards that grid.js failed
+ to lay into .home-products-content are orphaned onto .main-content/<body>
+ and render at full 1440px. We CONSTRAIN them into a responsive grid (never
+ hide — they are real products) so they degrade gracefully even if grid.js
+ init still partially fails. The grid.js init-abort fix remains the primary
+ mechanism; this is the defensive net (DTD verdict A, 3/3, 2026-06-23).
+ Scoped to body.boost-sd__search-widget-init-enabled for the collection rules
+ so the pre-hydration server fallback still shows (no flash of empty grid).
+ ===================================================================== */
+
+/* ---- (A) COLLECTION: suppress stale Boost theme fallback after hydration ---- */
+body.boost-sd__search-widget-init-enabled .boost-sd__product-filter-fallback > section.collection,
+body.boost-sd__search-widget-init-enabled .boost-sd__product-filter-fallback > article.product-list-item,
+body.boost-sd__search-widget-init-enabled .boost-sd__product-filter-fallback > .shopify-section:not(:has(.boost-sd-container)) {
+ display: none !important;
+}
+
+/* Safety net for the collection page: a theme-native .product-list-item that is
+ NOT part of the live Boost app grid and NOT inside a real CSS-grid wrapper is
+ stale fallback — hide it (collection context only). */
+body.template-collection.boost-sd__search-widget-init-enabled
+ .boost-sd__product-filter-fallback
+ article.product-list-item {
+ display: none !important;
+}
+/* but keep the live Boost grid's own items visible */
+body.template-collection.boost-sd__search-widget-init-enabled
+ .boost-sd-container article.product-list-item {
+ display: revert !important;
+}
+/* Also catch the loose stale cards that sit directly under .main-content /
+ <body> on the collection template (orphaned by the same fallback dump) — the
+ live Boost products are inside .boost-sd-container, never here. */
+body.template-collection.boost-sd__search-widget-init-enabled > article.product-list-item,
+body.template-collection.boost-sd__search-widget-init-enabled .main-content > article.product-list-item,
+body.template-collection.boost-sd__search-widget-init-enabled section.collection article.product-list-item {
+ display: none !important;
+}
+
+/* ---- (B) HOMEPAGE: constrain featured-collection cards into a grid ---- */
+/* Force the featured-collection section to a responsive grid so even orphaned
+ cards (attached at section/.main-content/body level) get a column width. */
+body.template-index section.home-products {
+ display: grid !important;
+ grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
+ gap: 1.5rem;
+ align-items: start;
+}
+body.template-index section.home-products .home-products-content {
+ display: contents; /* let inner cards participate in the section grid */
+}
+/* Hard clamp: ANY featured-collection product card can never exceed its column,
+ and a stray orphaned card (e.g. one that escaped onto .main-content/body) is
+ width-capped so it can never render full-bleed. */
+body.template-index .product-list-item {
+ max-width: 360px !important;
+ width: 100% !important;
+}
+/* The card image follows the card width and lazy-loads. */
+body.template-index .product-list-item img {
+ width: 100% !important;
+ height: auto !important;
+ max-width: 100% !important;
+}
+
+/* ---- (C) Global belt: orphaned cards attached directly to body/.main-content
+ on ANY template can never be full-bleed (defensive, harmless to real grids
+ because real grid cards are already < this cap). ---- */
+body > .product-list-item,
+.main-content > .product-list-item {
+ max-width: 360px !important;
+}
diff --git a/shopify/grid-js-fix/verify-final-css-fix.js b/shopify/grid-js-fix/verify-final-css-fix.js
new file mode 100644
index 00000000..d0915c00
--- /dev/null
+++ b/shopify/grid-js-fix/verify-final-css-fix.js
@@ -0,0 +1,58 @@
+/*
+ * verify-final-css-fix.js — FINAL acceptance test of dw-collection-grid-fix.css
+ * at BOTH 1440 and 390. Asserts:
+ * - COLLECTION: visible blown .product-list-item (>500px) == 0; Boost grid intact
+ * - HOMEPAGE: visible blown == 0 AND home cards still VISIBLE (not over-hidden):
+ * visiblePliCount stays > 0 and each visible card img <= ~360px
+ * READ-ONLY (injects CSS in-browser only).
+ */
+const fs = require('fs');
+const { chromium } = require('playwright');
+const FIX_CSS = fs.readFileSync(__dirname + '/dw-collection-grid-fix.css', 'utf8');
+const PAGES = [
+ { name: 'HOME', url: 'https://www.designerwallcoverings.com/', tmpl:'index' },
+ { name: 'COLLECTION', url: 'https://www.designerwallcoverings.com/collections/acoustical?pf_t_product_type=Wallcovering&pf_t_color=Green', tmpl:'collection' },
+];
+async function measure(ctx, p, inject) {
+ const page = await ctx.newPage();
+ try { await page.goto(p.url, { waitUntil: 'networkidle', timeout: 50000 }); }
+ catch(e){ await page.goto(p.url,{waitUntil:'domcontentloaded',timeout:50000}).catch(()=>{}); }
+ await page.waitForTimeout(4000);
+ await page.evaluate(()=>window.scrollTo(0,document.body.scrollHeight)).catch(()=>{});
+ await page.waitForTimeout(2000);
+ await page.evaluate(()=>window.scrollTo(0,0)).catch(()=>{});
+ if (inject){ await page.addStyleTag({content:FIX_CSS}); await page.waitForTimeout(600); }
+ const r = await page.evaluate(()=>{
+ const vis=[],all=[];
+ document.querySelectorAll('.product-list-item').forEach(c=>{
+ const im=c.querySelector('img'); if(!im)return;
+ const w=Math.round(im.getBoundingClientRect().width);
+ const shown=getComputedStyle(c).display!=='none' && c.getBoundingClientRect().height>2;
+ if(w>2)all.push(w); if(shown&&w>2)vis.push(w);
+ });
+ vis.sort((a,b)=>b-a); all.sort((a,b)=>b-a);
+ function bw(sel){const o=[];document.querySelectorAll(sel).forEach(c=>{const im=c.querySelector('img');if(im){const w=im.getBoundingClientRect().width;if(w>2)o.push(Math.round(w));}});o.sort((a,b)=>b-a);return o;}
+ const boost=bw('.boost-sd__product-item');
+ return { visCount:vis.length, visMax:vis[0]||0, visTop:vis.slice(0,6), blown:vis.filter(x=>x>500).length,
+ boostCount:boost.length, boostMax:boost[0]||0, pageH:Math.round(document.body.scrollHeight) };
+ });
+ await page.close();
+ return r;
+}
+function ln(t,m){return `[${t}] BLOWN(>500)=${m.blown} visMax=${m.visMax}px visibleCards=${m.visCount} ${JSON.stringify(m.visTop)} | boost.count=${m.boostCount} max=${m.boostMax}px | pageH=${m.pageH}px`;}
+(async()=>{
+ const browser=await chromium.launch({headless:true,executablePath:'/Applications/Google Chrome.app/Contents/MacOS/Google Chrome'});
+ for (const vp of [{w:1440,h:1400,n:'DESKTOP 1440'},{w:390,h:844,n:'MOBILE 390'}]) {
+ console.log(`\n================= ${vp.n} =================`);
+ const opt={viewport:{width:vp.w,height:vp.h},deviceScaleFactor:vp.w===390?2:1,isMobile:vp.w===390};
+ const b=await browser.newContext(opt);
+ console.log('-- BEFORE --');
+ for(const p of PAGES) console.log(ln(p.name, await measure(b,p,false)));
+ await b.close();
+ const a=await browser.newContext(opt);
+ console.log('-- AFTER (dw-collection-grid-fix.css) --');
+ for(const p of PAGES) console.log(ln(p.name, await measure(a,p,true)));
+ await a.close();
+ }
+ await browser.close();
+})().catch(e=>{console.error('FATAL',e);process.exit(1);});
← e6dfc1a5 collection hero: in-progress manifest snapshot (66 missing f
·
back to Designer Wallcoverings
·
Stage collection/home oversized-images CSS fix on dev theme b6165db6 →