[object Object]

← 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

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 →