Key takeaways
- A quick view modal lets shoppers preview a product - image, price, variant picker, add-to-cart - in an overlay from a collection grid, without leaving the page.
- The clean native build is a small web component that fetches the product card with the Section Rendering API and adds to cart with /cart/add.js. No third-party widget.
- Quick view can lift conversion on weak collection pages, but it adds JavaScript and can mask a product list that just needs better information.
- Accessibility is not optional: you need a focus trap, ESC to close,
aria-modal, and focus returned to the trigger.- Fudge builds the whole thing as native theme code from a plain-English description, so nothing renders over your theme and nothing breaks on uninstall.
A Shopify quick view modal opens a product preview in an overlay when a shopper clicks a button on a collection or grid. They see the image, price, options, and an add-to-cart button without loading the full product page.
Done well, it shortens the path to cart on browse-heavy stores. Done badly, it slows the collection page and papers over a product grid that needed more information in the first place. This guide covers both, then shows the native way to build one.
Why you can trust us
Jacques has 15+ years of Shopify development experience and has shipped storefront features for hundreds of brands. We build Fudge, a native-code storefront editor with a 5.0 rating on the Shopify App Store. We sit on the same theme layer every quick-view widget renders next to, so we see the speed and accessibility costs firsthand.
What a quick view modal is, and when it helps
A quick view is an overlay triggered from a product card on a collection page. Instead of navigating to the product page (PDP), the shopper gets a compact version of it in place.
A typical quick view includes:
- One or two product images
- Title and price
- Variant pickers (size, colour)
- An add-to-cart button
- A link through to the full PDP for everything else
It helps most when shoppers are comparing several similar products and the only thing they need before adding to cart is a size or a second photo. Apparel, accessories, and supplements with simple variant choices are the usual fit.
It also keeps people on the collection page, so a shopper can preview three products in a row without three full page loads and three back-button trips.
Related: how to customise a Shopify product page, which covers the full PDP the modal links out to.
When a quick view modal hurts
Quick view is not a free win. Baymard Institute’s product-list research found that quick view usually tests well only on sites that show too little information on the list view in the first place. Their read is that the overlay is often a symptom treatment for a weak product grid, and that adding the primary details to the card itself is the better fix.1
So before you build, ask whether the real problem is a bare collection card. If your cards already show price, a clear image, and swatches, a quick view adds less than you think.
There are two other costs to weigh.
Page speed. A quick view ships JavaScript and, in most app versions, its own CSS to every collection page. Collection pages are already image-heavy, and speed maps directly to conversion. If you go the app route, test it. See how to speed up a Shopify theme for the measurement steps.
PDP SEO. A quick view is a supplement to the product page, never a replacement. Keep real, crawlable PDPs with their own URLs and structured data. If you ever hide product content behind a modal that only loads on click, you risk keeping it out of the indexable page. The modal is a shortcut for shoppers, not a place to move your product copy.
A quick view earns its place when it speeds up comparison shopping. It does not fix a collection page that is missing the basics.
How to build a quick view modal on Shopify
The native pattern has three moving parts: a trigger on each product card, a modal shell that lives once in the theme, and a small script that fetches the product content and handles add-to-cart. Building it as a web component keeps the DOM references clean.
Add a trigger to the product card
Product cards render from a snippet, usually card-product.liquid or similar in your theme. Add a button that carries the product handle so the modal knows what to load.
<button
class="quick-view-trigger"
data-product-handle="{{ card_product.handle }}"
aria-haspopup="dialog"
>
Quick view
</button>
Nothing loads yet. The handle is all the trigger needs to carry.
Fetch the product card with the Section Rendering API
Rather than rebuild the product form in JavaScript, fetch a rendered section from Shopify and drop its HTML into the modal. The Section Rendering API returns the HTML for a section in the context of any page.2
Create a section (for example quick-view.liquid) that renders the product form, variant pickers, price, and image. Then request it for a specific product using section_id:
const handle = trigger.dataset.productHandle
const url = `${window.Shopify.routes.root}products/${handle}?section_id=quick-view`
const res = await fetch(url)
const html = await res.text()
modal.querySelector(".qv-body").innerHTML = html
Using window.Shopify.routes.root keeps the URL correct across locales and subfolders. Because the section renders on the product’s own URL, all the product’s Liquid objects are available, so you get real variant data and real prices without reconstructing them by hand.
Handle variant selection
The fetched section already contains the variant inputs. To keep price and the selected variant in sync, load the product’s JSON and match the chosen options.
const product = await fetch(
`${window.Shopify.routes.root}products/${handle}.js`,
).then((r) => r.json())
// On input change, find the variant whose options match the selection
const match = product.variants.find((v) =>
v.options.every((opt, i) => opt === selectedOptions[i]),
)
From match you get the variant id for add-to-cart and the price to display. This is the same JSON Shopify’s own theme code reads, so it stays accurate as inventory and prices change.
Add to cart with /cart/add.js
The add-to-cart button posts to the Cart AJAX API. A POST to /cart/add.js adds the selected variant without a page reload.3
await fetch(`${window.Shopify.routes.root}cart/add.js`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ items: [{ id: variantId, quantity: 1 }] }),
})
One detail worth using: /cart/add.js accepts a sections parameter, so a single request can add the item and return the re-rendered cart drawer or cart-count HTML. That lets you update the cart UI from the same call instead of firing a second fetch.3
Accessibility: a modal has real requirements
A modal that traps keyboard users or hides from screen readers is a broken modal. The overlay must follow the standard dialog pattern.
- Mark it as a dialog. Put
role="dialog"andaria-modal="true"on the overlay, and give it an accessible name witharia-labelledbypointing at the product title. - Trap focus. While the modal is open, Tab and Shift+Tab must cycle only through elements inside it. Nothing behind the overlay should be reachable.
- Close on ESC. The Escape key must close the modal, in addition to a visible close button and a click on the backdrop.
- Return focus. When the modal closes, move focus back to the Quick view button that opened it, so keyboard users do not lose their place in the grid.
- Stop background scroll. Lock scrolling on the page body while the overlay is open.
Building the modal as a web component makes this easier to manage: you handle open and close inside connectedCallback, keep a reference to the triggering element, and restore focus to it on close.
Performance: load it late, not on every card
The point of native quick view is to avoid the weight an app adds. Keep it light.
- Do not fetch anything on page load. The product content should be requested only when a shopper clicks Quick view, not preloaded for every card in the grid.
- Defer the script. Load the modal’s JavaScript with
defer, or import it lazily so it does not block the collection page render. - Render one modal shell, reuse it. Keep a single modal element in the DOM and swap its contents per product, rather than injecting a fresh modal for every card.
- Cache within a session. If a shopper opens the same product twice, you can hold the fetched HTML so the second open is instant.
This keeps the collection page fast for the many shoppers who never open a quick view, while the feature stays available for those who do.
Mobile considerations
On a phone, a quick view competes with the tap that would just open the PDP. The screen is small, so the overlay ends up nearly full-height anyway.
Two practical calls:
- Consider skipping quick view on mobile and letting the card link straight to the PDP. The overlay saves less when the full page is one tap and a fast load away.
- If you keep it on mobile, make the modal a bottom sheet or a full-screen panel with a large close target and easily tappable variant options. A cramped desktop modal shrunk onto a phone converts poorly.
Quick view vs the full product page
They serve different jobs. Use this to decide what belongs where.
| Dimension | Quick view modal | Full product page (PDP) |
|---|---|---|
| Goal | Fast preview and add-to-cart while browsing | Full detail and the decision to buy |
| Content | Image, price, variants, add-to-cart | Everything: full gallery, description, reviews, upsells |
| Best for | Comparison shopping, simple variant choices | Considered purchases, rich product stories |
| SEO | Not indexed on its own | Crawlable URL, structured data, canonical |
| Speed cost | Extra JS on collection pages | Standard page load |
Rule of thumb: quick view speeds up the browse. The PDP still closes the sale. Never move product content off the PDP into a modal.
For the wider picture of how these pieces move conversion, see our Shopify CRO guide. If your goal is a persistent buy button rather than an overlay, a sticky add-to-cart bar is often the simpler lever.
Where Fudge fits
Everything above is real work: a new section, a web component, variant-matching logic, focus management, and cross-browser testing. Most stores reach for a third-party quick-view app to skip it, and inherit a monthly fee, an off-brand widget, and script weight on every collection page.
Fudge is an AI storefront editor that writes the feature as native theme code. You describe what you want:
“Add a quick view button to my collection cards that opens a modal with the product image, variant picker, and add to cart, with ESC to close and focus returned to the button.”
Fudge builds it into your theme using the Section Rendering API and /cart/add.js, with the accessibility handling in place. There is no widget rendering over your theme, no extra JavaScript bundle loading on every page, and because it is native code, it survives uninstall. You can refine it with follow-up prompts, the same way you would with anything built in the Shopify store editor or the Shopify page builder.
FAQ
It is an overlay that previews a product - image, price, variant picker, and add-to-cart - directly from a collection or grid, without loading the full product page. Shoppers can add to cart from the browse view, which shortens the path to purchase on comparison-heavy stores.
Add a trigger button to your product card snippet, create a modal shell in the theme, and use a small web component that fetches the product content with the Section Rendering API and adds to cart with /cart/add.js. Describe it to Fudge if you would rather not hand-code the section, variant logic, and focus trap.
Not if you keep real product pages. The modal is a shortcut for shoppers, not a replacement for the PDP. Keep crawlable product URLs with their own structured data, and never move product copy off the PDP into a modal that only loads on click.
It can, because it adds JavaScript to pages that are already image-heavy. Keep it fast by fetching product content only on click, deferring the script, and reusing one modal shell. App-based quick views tend to add more weight than a native build. Run Lighthouse before and after.
It returns the HTML for a theme section rendered in the context of a specific product URL, using a section_id parameter. That means you can fetch a real product form with live variant and price data and drop it into the modal, instead of rebuilding the product form in JavaScript.
Often not. On a phone the full product page is one tap and a fast load away, so the overlay saves little. If you keep it, use a full-screen or bottom-sheet layout with large tap targets rather than a shrunk-down desktop modal.
Footnotes
-
Baymard Institute, “E-Commerce Product Lists & Filtering UX” - quick view overlays typically test well only on sites with too little information on the list view, and are best treated as a symptom of a weak product grid rather than a fix. https://baymard.com/research/ecommerce-product-lists ↩
-
Shopify Dev, “Section Rendering API” - request rendered section HTML in the context of any page using the
sectionsorsection_idquery parameters. https://shopify.dev/docs/api/section-rendering ↩ -
Shopify Dev, “Cart AJAX API” - POST /cart/add.js adds one or more variants to the cart, accepts an
itemsarray and asectionsparameter to return re-rendered section HTML in the same response. https://shopify.dev/docs/api/ajax/reference/cart ↩ ↩2