Compatibility: Compatible with any Shopify 2.0 FREE themes
If you're running a Shopify store, you know how important it is to provide your customers with an enjoyable and seamless shopping experience. One way to do this is by adding a quickview button to your product cards.
A quickview button allows customers to see a preview of a product without having to leave the current page they're on. This feature can significantly improve the user experience of your website, as it eliminates the need for customers to navigate away from their current location and wait for a new page to load.
By using Shopify's section rendering API, you can easily add a quickview button to your product cards without having to install any external libraries or apps. This means you can customize the functionality and design of the button to match your brand's aesthetic and needs.
With a quickview button, customers can easily view product information, add items to their cart, and continue shopping without interruption. By providing this feature, you're showing your customers that you value their time and want to make their shopping experience as enjoyable as possible.
It's worth noting that while some of Shopify's free 2.0 themes do offer a built-in quick view button, the features may be limited and not fully customizable to your preferences. By using our code, you'll have more control over the design and functionality of your quick view button.
Don't miss out on the opportunity to improve your store's user experience. Add a quickview button to your product cards today and watch your conversion rates soar.
Check DEMO store here 💻. Password: made4uo
What is a quick view button?
A quick view button is a user interface element typically placed on product listings that allows customers to see a product's details in a pop-up window without leaving the current page. This functionality provides a convenient way for customers to browse product information without interrupting their shopping flow.
Why add a quick view button?
There are several reasons to incorporate a quick view button into your Shopify store:
- Improved User Experience: Quick view buttons allow customers to efficiently explore product details without navigating away from the current page.
- Increased Sales: By providing easy access to product information, quick view buttons can encourage customers to learn more about products and potentially add them to their cart.
- Reduced Bounce Rate: Quick view functionality can help keep customers engaged on your store by minimizing the need to click through to individual product pages.
Additional Considerations
- Mobile-friendliness: Ensure the quick view button and pop-up function seamlessly on all devices, especially smartphones.
- Content Optimization: For optimal presentation within the quick view pop-up, consider the structure and detail level of the displayed product information.
- Loading Speed: A quick view pop-up that loads slowly can disrupt the user experience. Ensure the pop-up content is optimized for fast loading times.
What you are buying:
- Hide and show the quickview button with hover
- Mobile friendly with small button provided
- Previous and next navigation provided for easy collection view
- Thumbnail sliders available
What makes our code better:
- We do not use external libraries, with that being said, our code will have no to minimal effect to your website's speed performance
- We do not leave or add codes use to advertise for our website
- Our code is mobile friendly
Any issues related to the code will be fix with no additional cost, excluding code customization requests. Simply contact us with "Chat with us." We are just a button away.
[]
Steps on how to add quick view button:
Step #1. Open your code editor
From you Admin page, go to Online store, then Themes. Choose the theme you want to edit, then click the three dots, then Edit code.
Step #2. Create a new section file
In Section folder, create a new section, name it "quick-view", then replace the default code with the code below.
{{ 'quick-view.css' | asset_url | stylesheet_tag }} <product-viewer> <div class="hidden"> <div id="buttonViewer"> <div class="buttonViewer" style="background: {{section.settings.button_background}}; color: {{section.settings.button_font_color}}; font-size: clamp(12px, 1vw, 20px);" > <span class="desktopbutton"> <span>{{ section.settings.button_label }}</span> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 40 40"> <style type="text/css"> .st--0{fill:none;} .st--1{fill: {{section.settings.button_font_color}};} </style> <g id="icon-eye"> <path class="st--0" d="M19.86,8.36c-5.96,0.26-11.2,3.82-15.25,8.02c-1.03,1.11-2,2.31-2.98,3.51c-0.33,0.41-0.31,0.96-0.01,1.42 c0.21,0.31,0.41,0.63,0.66,0.9c10.1,13.8,25.85,13.6,35.76-0.3C40.34,16.95,24.74,7.44,19.86,8.36z"/> <path class="st--1" d="M19.86,8.36c8.91,0.49,17.14,7.75,18.5,12.53c0.05,0.19-0.01,0.47-0.13,0.63 C28.31,35.31,12.34,35.96,2.27,22.2c-0.24-0.26-0.45-0.58-0.66-0.9c-0.3-0.45-0.32-1.01,0.01-1.42c0.98-1.19,1.95-2.4,2.98-3.51 C8.65,12.18,13.9,8.62,19.86,8.36z M20.06,11.35c-8.99-0.25-8.86,18.67-0.1,18.52C28.97,30.08,28.9,11.12,20.06,11.35z M26.06,29.26c4.06-1.67,7.57-4.94,10.49-8.36c-1.8-3.77-6.61-7.15-10.51-8.97C29.7,17.74,29.68,23.5,26.06,29.26z M13.99,11.95 c-0.03-0.04-0.03-0.03-0.06-0.07c-3.85,2.02-8.6,5.13-10.43,9.01c2.96,3.35,6.39,6.72,10.52,8.4 C10.36,23.49,10.37,17.72,13.99,11.95z"/> <path class="st--0" d="M20.06,11.35c8.84-0.23,8.91,18.73-0.1,18.52C11.2,30.02,11.07,11.1,20.06,11.35z M21.23,15.55 c-4.52-2.07-6.82,6.52-3.77,9.19c3.95,4.36,8.16-3.43,6.07-6.51C21.77,20.95,19.51,17.29,21.23,15.55z"/> <path class="st--0" d="M26.06,29.26c3.62-5.76,3.64-11.51-0.02-17.34c3.89,1.82,8.7,5.21,10.51,8.97 C33.64,24.32,30.12,27.58,26.06,29.26z"/> <path class="st--0" d="M13.98,11.96c-3.61,5.77-3.62,11.53,0.04,17.33c-4.13-1.68-7.56-5.05-10.52-8.4 c1.83-3.88,6.57-6.98,10.43-9.01C13.95,11.91,13.96,11.93,13.98,11.96z"/> <path class="st--1" d="M21.23,15.55c-1.72,1.75,0.54,5.39,2.3,2.68c2.1,3.09-2.11,10.87-6.07,6.51 C14.41,22.07,16.71,13.48,21.23,15.55z"/> </g> </svg></span ><span class="mobilebutton"> <svg viewBox="0 0 40 40" x="121" y="112"> <use xlink:href="#icon-eye" /> </svg> </span> </div> </div> </div> <div class="viewerBackground {% if template == 'page' %} view {% endif %}"> <div class="productViewContainer color-{{ section.settings.color_scheme }}"> <div class="quickViewButtonContainer"> <div class="navigatorWrapper"> <button type="button" class="prevNavigator navigatorBtn" name="prev" style="background: {{section.settings.button_background}}; color: {{section.settings.button_font_color}}" > PREV </button> <button type="button" class="nextNavigator navigatorBtn" name="next" style="background: {{section.settings.button_background}}; color: {{section.settings.button_font_color}}" > NEXT </button> <span class="errorMessage"></span> </div> <span class="productViewerClose" style=" stroke: {{section.settings.button_font_color}}; background: {{section.settings.button_background}}" > {%- render 'icon-close' -%} </span> </div> <div class="productViewer"></div> </div> </div> </product-viewer> <script src="{{ 'product-form.js' | asset_url }}" defer="defer"></script> <script> document.addEventListener("DOMContentLoaded", function () { function o() { const o = window.navigator.userAgent; const n = o.indexOf("MSIE "); const t = o.indexOf("Trident/"); return n > 0 || t > 0; } if (!o()) return; const n = document.querySelector('#{{ product_form_id }} input[name="id"]'); const t = document.createElement("div"); const d = document.querySelector( 'variant-radios[data-section="{{ product.id }}-{{forloop.index0}}"]' ) || document.querySelector( 'variant-selects[data-section="{{ product.id }}-{{forloop.index0}}"]' ); t.innerHTML = document.querySelector( ".product-form__noscript-wrapper-{{ product.id }}-{{forloop.index0}}" ).textContent; d.outerHTML = t.outerHTML; document .querySelector("#Variants-{{ product.id }}") .addEventListener("change", function (o) { n.value = o.currentTarget.value; }); }); </script> <script type="application/ld+json"> { "@context": "http://schema.org/", "@type": "Product", "name": {{ product.title | json }}, "url": {{ shop.url | append: product.url | json }}, {% if seo_media -%} {%- assign media_size = seo_media.preview_image.width | append: 'x' -%} "image": [ {{ seo_media | img_url: media_size | prepend: "https:" | json }} ], {%- endif %} "description": {{ product.description | strip_html | json }}, {% if product.selected_or_first_available_variant.sku != blank -%} "sku": {{ product.selected_or_first_available_variant.sku | json }}, {%- endif %} "brand": { "@type": "Thing", "name": {{ product.vendor | json }} }, "offers": [ {%- for variant in product.variants -%} { "@type" : "Offer", {%- if variant.sku != blank -%} "sku": {{ variant.sku | json }}, {%- endif -%} "availability" : "http://schema.org/{% if variant.available %}InStock{% else %}OutOfStock{% endif %}", "price" : {{ variant.price | divided_by: 100.00 | json }}, "priceCurrency" : {{ cart.currency.iso_code | json }}, "url" : {{ shop.url | append: variant.url | json }} }{% unless forloop.last %},{% endunless %} {%- endfor -%} ] } </script> {% schema %} { "name": "Quickview", "settings": [ { "type": "header", "content": "Quickview button style" }, { "type": "color", "id": "button_background", "label": "Button background", "default": "#000" }, { "type": "color", "id": "button_font_color", "label": "Button font color", "default": "#fff" }, { "type": "text", "id": "button_label", "label": "Button text", "default": "QUICKVIEW" }, { "type": "header", "content": "Pop-up modal style" }, { "type": "select", "id": "color_scheme", "options": [ { "value": "accent-1", "label": "Accent 1" }, { "value": "accent-2", "label": "Accent 2" }, { "value": "background-1", "label": "Background 1" }, { "value": "background-2", "label": "Background 2" }, { "value": "inverse", "label": "Inverse" } ], "default": "background-1", "label": "t:sections.all.colors.label" } ], "presets": [ { "name": "Quickview" } ] } {% endschema %} |
Step #3. Create another section.
We need to create another section for our template. We are using Section Rendering API from Shopify. Name this newly created section "quick-view-template." Then paste the code below.
{{ 'section-main-product.css' | asset_url | stylesheet_tag }} {{ 'section-featured-product.css' | asset_url | stylesheet_tag }} {{ 'component-price.css' | asset_url | stylesheet_tag }} {{ 'component-rte.css' | asset_url | stylesheet_tag }} {{ 'component-loading-overlay.css' | asset_url | stylesheet_tag }} {{ 'quick-view.css' | asset_url | stylesheet_tag }} <link rel="stylesheet" href="{{ 'component-deferred-media.css' | asset_url }}" media="print" onload="this.media='all'"> {%- assign first_3d_model = product.media | where: 'media_type', 'model' | first -%} {%- if first_3d_model -%} {{ 'component-product-model.css' | asset_url | stylesheet_tag }} <link id="ModelViewerStyle" rel="stylesheet" href="https://cdn.shopify.com/shopifycloud/model-viewer-ui/assets/v1.0/model-viewer-ui.css" media="print" onload="this.media='all'" > <link id="ModelViewerOverride" rel="stylesheet" href="{{ 'component-model-viewer-ui.css' | asset_url }}" media="print" onload="this.media='all'" > {%- endif -%} <section> <div class="section-{{ section.id }}-padding"> <div class="featured-product product grid grid--1-col gradient color-{{ section.settings.color_scheme }}{% if section.settings.secondary_background == false %} isolate{% endif %} {% if product.media.size > 0 %}grid--2-col-tablet{% else %}product--no-media{% endif %}"> <div class="grid__item product__media-wrapper"> {% if product %} <slider-quick-view> <ul class="largeImage"> {%- for media in product.media -%} <li class=" large-image-item product__media-item grid__item slider__slide {% if forloop.first %} is-active {% endif %} {% if media.media_type != 'image' %} hide-modal {% endif %} " data-media-id="{{ media.id }}" > {% render 'product-thumbnail', media: media, position: forloop.index, loop: true, modal_id: product.id, xr_button: true %} </li> {%- endfor -%} </ul> <div class="slider-wrapper"> <button type="button" class="slider-button slider-button--prev bigger-slider {% if product.media.size <= 4 %}hidden{% endif %}" name="previous" aria-label="{{ 'accessibility.previous_slide' | t }}" > {% render 'icon-caret' %} </button> <ul class="product-slider-box slider" role="list"> {%- assign variant_images = product.images | where: 'attached_to_variant?', true | map: 'src' -%} {%- for media in product.media -%} <li class="product-slider slider__slide" data-thumb-id="{{ media.id }}"> {% if media.media_type == 'video' %} <div class="video-btn" style="display: block"> <span class="product__media-icon motion-reduce v-btn" aria-hidden="true"> {%- liquid case media.media_type when 'video', 'external_video' render 'icon-play' when 'model' render 'icon-3d-model' else render 'icon-zoom' endcase -%} </span> <img class="slide-image {% if forloop.first %}active-thumb {% endif %}" src="{{ media.preview_image | img_url: 'large' }}" alt="{{ media.alt}}" style="aspect-ratio: 1;" > </div> {% else %} <img class="slide-image {% if forloop.first %}active-thumb {% endif %}" src="{{ media.preview_image | img_url: 'large' }}" alt="{{ media.alt }}" style="aspect-ratio: 1;" > {% endif %} </li> {% endfor %} </ul> <button type="button" class="slider-button slider-button--next bigger-slider {% if product.media.size <= 4 %}hidden{% endif %}" name="next" aria-label="{{ 'accessibility.next_slide' | t }}" > {% render 'icon-caret' %} </button> </div> </slider-quick-view> {% endif %} </div> <div class="product__info-wrapper grid__item"> <div id="ProductInfo-{{ section.id }}" class="product__info-container"> {%- assign product_form_id = 'product-form-' | append: section.id -%} <h2 class="h2 product__title" {{ section.shopify_attributes }}> {%- if product.title != blank -%} {{ product.title | escape }} {%- else -%} {{ 'onboarding.product_title' | t }} {%- endif -%} </h2> <div class="no-js-hidden" id="price-{{ section.id }}" role="status" {{ block.shopify_attributes }}> {%- render 'price', product: product, use_variant: true, show_badges: true, price_class: 'price--large' -%} </div> {%- if shop.taxes_included or shop.shipping_policy.body != blank -%} <div class="product__tax caption rte"> {%- if shop.taxes_included -%} {{ 'products.product.include_taxes' | t }} {%- endif -%} {%- if shop.shipping_policy.body != blank -%} {{ 'products.product.shipping_policy_html' | t: link: shop.shipping_policy.url }} {%- endif -%} </div> {%- endif -%} {%- if product != blank -%} <div {{ block.shopify_attributes }}> {%- form 'product', product -%} <input type="hidden" name="id" value="{{ product.selected_or_first_available_variant.id }}"> {{ form | payment_terms }} {%- endform -%} </div> {%- endif -%} <div class="product-form__input product-form__quantity{% if settings.inputs_shadow_vertical_offset != 0 and settings.inputs_shadow_vertical_offset < 0 %} product-form__quantity-top{% endif %}" {{ block.shopify_attributes }} > <label class="form__label" for="Quantity-{{ section.id }}"> {{ 'products.product.quantity.label' | t }} </label> <quantity-input class="quantity"> <button class="quantity__button no-js-hidden" name="minus" type="button"> <span class="visually-hidden"> {{- 'products.product.quantity.decrease' | t: product: product.title | escape -}} </span> {% render 'icon-minus' %} </button> <input class="quantity__input" type="number" name="quantity" id="Quantity-{{ section.id }}" min="1" value="1" form="{{ product_form_id }}" > <button class="quantity__button no-js-hidden" name="plus" type="button"> <span class="visually-hidden"> {{- 'products.product.quantity.increase' | t: product: product.title | escape -}} </span> {% render 'icon-plus' %} </button> </quantity-input> </div> <variant-viewer class="no-js-hidden" data-section="{{ section.id }}" data-url="{{ product.url }}" data-update-url="false" {{ block.shopify_attributes }} > {%- for option in product.options_with_values -%} <div class="product-form__input product-form__input--dropdown"> <label class="form__label" for="Option-{{ section.id }}-{{ forloop.index0 }}"> {{ option.name }} </label> <div class="select"> <select id="Option-{{ section.id }}-{{ forloop.index0 }}" class="select__select" name="options[{{ option.name | escape }}]" form="{{ product_form_id }}" > {%- for value in option.values -%} <option value="{{ value | escape }}" {% if option.selected_value == value %} selected="selected" {% endif %} > {{ value }} </option> {%- endfor -%} </select> {% render 'icon-caret' %} </div> </div> {%- endfor -%} <script type="application/json"> {{ product.variants | json }} </script> </variant-viewer> <noscript class="product-form__noscript-wrapper-{{ section.id }}"> <div class="product-form__input{% if product.has_only_default_variant %} hidden{% endif %}"> <label class="form__label" for="Variants-{{ section.id }}"> {{- 'products.product.product_variants' | t -}} </label> <div class="select"> <select name="id" id="Variants-{{ section.id }}" class="select__select" form="{{ product_form_id }}"> {%- for variant in product.variants -%} <option {% if variant == product.selected_or_first_available_variant %} selected="selected" {% endif %} {% if variant.available == false %} disabled {% endif %} value="{{ variant.id }}" > {{ variant.title }} {%- if variant.available == false %} - {{ 'products.product.sold_out' | t }}{% endif %} - {{ variant.price | money | strip_html }} </option> {%- endfor -%} </select> {% render 'icon-caret' %} </div> </div> </noscript> <div {{ block.shopify_attributes }}> {%- if product != blank -%} <product-form class="product-form"> <div class="product-form__error-message-wrapper" role="alert" hidden> <svg aria-hidden="true" focusable="false" role="presentation" class="icon icon-error" viewBox="0 0 13 13" > <circle cx="6.5" cy="6.50049" r="5.5" stroke="white" stroke-width="2"/> <circle cx="6.5" cy="6.5" r="5.5" fill="#EB001B" stroke="#EB001B" stroke-width="0.7"/> <path d="M5.87413 3.52832L5.97439 7.57216H7.02713L7.12739 3.52832H5.87413ZM6.50076 9.66091C6.88091 9.66091 7.18169 9.37267 7.18169 9.00504C7.18169 8.63742 6.88091 8.34917 6.50076 8.34917C6.12061 8.34917 5.81982 8.63742 5.81982 9.00504C5.81982 9.37267 6.12061 9.66091 6.50076 9.66091Z" fill="white"/> <path d="M5.87413 3.17832H5.51535L5.52424 3.537L5.6245 7.58083L5.63296 7.92216H5.97439H7.02713H7.36856L7.37702 7.58083L7.47728 3.537L7.48617 3.17832H7.12739H5.87413ZM6.50076 10.0109C7.06121 10.0109 7.5317 9.57872 7.5317 9.00504C7.5317 8.43137 7.06121 7.99918 6.50076 7.99918C5.94031 7.99918 5.46982 8.43137 5.46982 9.00504C5.46982 9.57872 5.94031 10.0109 6.50076 10.0109Z" fill="white" stroke="#EB001B" stroke-width="0.7"/> </svg> <span class="product-form__error-message"></span> </div> {%- form 'product', product, id: product_form_id, class: 'form', novalidate: 'novalidate', data-type: 'add-to-cart-form' -%} <input type="hidden" name="id" value="{{ product.selected_or_first_available_variant.id }}" disabled> <div class="product-form__buttons"> <button type="submit" name="add" class="product-form__submit button button--full-width {% if section.settings.show_dynamic_checkout and product.selling_plan_groups == empty %}button--secondary{% else %}button--primary{% endif %}" {% if product.selected_or_first_available_variant.available == false %} disabled {% endif %} > <span> {%- if product.selected_or_first_available_variant.available -%} {{ 'products.product.add_to_cart' | t }} {%- else -%} {{ 'products.product.sold_out' | t }} {%- endif -%} </span> <div class="loading-overlay__spinner hidden"> <svg aria-hidden="true" focusable="false" role="presentation" class="spinner" viewBox="0 0 66 66" xmlns="http://www.w3.org/2000/svg" > <circle class="path" fill="none" stroke-width="6" cx="33" cy="33" r="30"></circle> </svg> </div> </button> {%- if section.settings.show_dynamic_checkout -%} {{ form | payment_button }} {%- endif -%} </div> {%- endform -%} </product-form> {%- else -%} <div class="product-form"> <div class="product-form__buttons form"> <button type="submit" name="add" class="product-form__submit button button--full-width button--primary" disabled > {{ 'products.product.sold_out' | t }} </button> </div> </div> {%- endif -%} </div> {%- if product.metafields.reviews.rating.value != blank -%} {% liquid assign rating_decimal = 0 assign decimal = product.metafields.reviews.rating.value.rating | modulo: 1 if decimal >= 0.3 and decimal <= 0.7 assign rating_decimal = 0.5 elsif decimal > 0.7 assign rating_decimal = 1 endif %} <div class="rating" role="img" aria-label="{{ 'accessibility.star_reviews_info' | t: rating_value: product.metafields.reviews.rating.value, rating_max: product.metafields.reviews.rating.value.scale_max }}" > <span aria-hidden="true" class="rating-star color-icon-{{ settings.accent_icons }}" style="--rating: {{ product.metafields.reviews.rating.value.rating | floor }}; --rating-max: {{ product.metafields.reviews.rating.value.scale_max }}; --rating-decimal: {{ rating_decimal }};" ></span> </div> <p class="rating-text caption"> <span aria-hidden="true"> {{- product.metafields.reviews.rating.value }} / {{ product.metafields.reviews.rating.value.scale_max -}} </span> </p> <p class="rating-count caption"> <span aria-hidden="true">({{ product.metafields.reviews.rating_count }})</span> <span class="visually-hidden"> {{- product.metafields.reviews.rating_count }} {{ 'accessibility.total_reviews' | t -}} </span> </p> {%- endif -%} <a href="{{ product.url }}" class="link product__view-details animate-arrow"> {{ 'products.product.view_full_details' | t }} {% render 'icon-arrow' %} </a> </div> </div> </div> <product-modal id="ProductModal-{{ section.id }}" class="product-media-modal media-modal"> <div class="product-media-modal__dialog" role="dialog" aria-label="{{ 'products.modal.label' | t }}" aria-modal="true" tabindex="-1" > <button id="ModalClose-{{ section.id }}" type="button" class="product-media-modal__toggle" aria-label="{{ 'accessibility.close' | t }}" > {% render 'icon-close' %} </button> <div class="product-media-modal__content" role="document" aria-label="{{ 'products.modal.label' | t }}" tabindex="0" > {%- liquid if product.selected_or_first_available_variant.featured_media != null assign media = product.selected_or_first_available_variant.featured_media render 'product-media', media: media, loop: section.settings.enable_video_looping, variant_image: section.settings.hide_variants endif -%} {%- for media in product.media -%} {%- liquid if section.settings.hide_variants and media_to_render contains media.id assign variant_image = true else assign variant_image = false endif unless media.id == product.selected_or_first_available_variant.featured_media.id render 'product-media', media: media, loop: section.settings.enable_video_looping, variant_image: variant_image endunless -%} {%- endfor -%} </div> </div> </product-modal> </div> </section> {% javascript %} if (!customElements.get("product-modal")) { customElements.define( "product-modal", class t extends ModalDialog { constructor() { super(); } hide() { super.hide(); } show(t) { super.show(t); this.t(); } t() { this.querySelectorAll( `[data-media-id]:not([data-media-id="${this.i.getAttribute( "data-media-id" )}"])` ).forEach((t) => { t.classList.remove("active"); }); const t = this.querySelector( `[data-media-id="${this.i.getAttribute("data-media-id")}"]` ); const a = t.querySelector("template"); const d = a ? a.content : null; t.classList.add("active"); t.scrollIntoView(); const e = this.querySelector('[role="document"]'); e.scrollLeft = (t.width - e.clientWidth) / 2; if ( t.nodeName == "DEFERRED-MEDIA" && d && d.querySelector(".js-youtube") ) t.o(); } } ); } {% endjavascript %} <script src="{{ 'product-form.js' | asset_url }}" defer="defer"></script> {%- if first_3d_model -%} <script type="application/json" id="ProductJSON-{{ product.id }}"> {{ product.media | where: 'media_type', 'model' | json }} </script> <script src="{{ 'product-model.js' | asset_url }}" defer></script> {%- endif -%} {%- liquid if product.selected_or_first_available_variant.featured_media assign seo_media = product.selected_or_first_available_variant.featured_media else assign seo_media = product.featured_media endif -%} <script type="application/ld+json"> { "@context": "http://schema.org/", "@type": "Product", "name": {{ product.title | json }}, "url": {{ shop.url | append: product.url | json }}, {% if seo_media -%} {%- assign media_size = seo_media.preview_image.width | append: 'x' -%} "image": [ {{ seo_media | img_url: media_size | prepend: "https:" | json }} ], {%- endif %} "description": {{ product.description | strip_html | json }}, {% if product.selected_or_first_available_variant.sku != blank -%} "sku": {{ product.selected_or_first_available_variant.sku | json }}, {%- endif %} "brand": { "@type": "Thing", "name": {{ product.vendor | json }} }, "offers": [ {%- for variant in product.variants -%} { "@type" : "Offer", {%- if variant.sku != blank -%} "sku": {{ variant.sku | json }}, {%- endif -%} "availability" : "http://schema.org/{% if variant.available %}InStock{% else %}OutOfStock{% endif %}", "price" : {{ variant.price | divided_by: 100.00 | json }}, "priceCurrency" : {{ cart.currency.iso_code | json }}, "url" : {{ shop.url | append: variant.url | json }} }{% unless forloop.last %},{% endunless %} {%- endfor -%} ] } </script> <script> document.addEventListener("DOMContentLoaded", function () { function n() { const n = window.navigator.userAgent; const t = n.indexOf("MSIE "); const o = n.indexOf("Trident/"); return t > 0 || o > 0; } if (!n()) return; const t = document.querySelector('#{{ product_form_id }} input[name="id"]'); const o = document.createElement("div"); const c = document.querySelector('variant-radios[data-section="{{ section.id }}"]') || document.querySelector('variant-selects[data-section="{{ section.id }}"]'); o.innerHTML = document.querySelector( ".product-form__noscript-wrapper-{{ section.id }}" ).textContent; c.outerHTML = o.outerHTML; document .querySelector("#Variants-{{ section.id }}") .addEventListener("change", function (n) { t.value = n.currentTarget.value; }); }); </script> {% if product.media.size > 0 %} <script src="{{ 'media-gallery.js' | asset_url }}" defer="defer"></script> {% endif %} {% schema %} { "name": "Quick view template", "tag": "section", "class": "section section-featured-product", "settings": [ { "type": "header", "content": "t:sections.featured-product.settings.header.content", "info": "t:sections.featured-product.settings.header.info" }, { "type": "checkbox", "id": "hide_variants", "default": false, "label": "t:sections.main-product.settings.hide_variants.label" }, { "type": "checkbox", "id": "show_dynamic_checkout", "default": true, "label": "t:sections.featured-product.blocks.buy_buttons.settings.show_dynamic_checkout.label", "info": "t:sections.featured-product.blocks.buy_buttons.settings.show_dynamic_checkout.info" }, { "type": "text", "id": "share_label", "label": "t:sections.featured-product.blocks.share.settings.text.label", "default": "Share" } ], "presets": [ { "name": "Quick view template" } ] } {% endschema %} |
Step #4. Create a new CSS file.
Next, find the Asset folder, and create a new CSS file. Name it "quick-view." Then open the newly created file and paste the code below.
.card-wrapper { position: relative; } .card-wrapper:hover .buttonViewer { display: flex; } .buttonViewer { width: 80%; max-height: 4rem; height: max-content; top: 33%; margin: auto; left: 0; right: 0; position: absolute; z-index: 4; display: none; align-items: center; justify-content: center; transition: all 0.3s ease; border-radius: 5px; padding: 3px; } .buttonViewer:hover { transform: scale(1.1); } .desktopbutton { display: flex; align-items: center; } .buttonViewer svg { max-width: 30px; width: 90%; margin: auto; aspect-ratio: 1; } .mobilebutton { display: none; } .productViewContainer { position: absolute; height: 65%; width: 60%; top: 0; left: 0; right: 0; bottom: 0; margin: auto; display: flex; flex-direction: column; overflow-y: auto; border-radius: 5px; } .productViewerClose { width: 30px; padding: 5px; border-radius: 3px; height: max-content; top: 15px; position: sticky; z-index: 1; display: flex; align-self: flex-end; transition: transform 0.2s ease; } .productViewerClose:hover { transform: scale(1.1); } .productViewerClose > svg { stroke-width: 1px; } .viewerBackground { position: fixed; width: 100vw; height: 100vh; top: 0; left: 0; bottom: 0; right: 0; background: rgba(0, 0, 0, 0.7); z-index: 6; display: none; } .productViewer { display: flex; width: 100%; padding: 0% 5%; } .productViewer > section { width: 100%; } .productViewer .product__media-wrapper { width: 35%; height: max-content; } .productViewer .product__info-wrapper { padding: 0 !important; max-width: 65% !important; } .productViewer .featured-product { gap: 5% !important; } .largeImage { width: 70%; margin: auto; } .slider-wrapper img { width: 100%; } .productViewer:not(.product--no-media) > .product__info-wrapper { padding: 0 0 0 5% !important; } .cart__warnings a:after { z-index: 0; } .productViewContainer .is-active { padding: 0 !important; display: block !important; } .productViewContainer .product__media-item:not(.is-active) { display: none; } .productViewContainer .thumbnail-slider { display: flex !important; } .productViewContainer .thumbnail-list { margin: auto !important; } .productViewContainer .thumbnail-list.slider--tablet-up .thumbnail-list__item.slider__slide { width: calc(35% - 0.8rem) !important; aspect-ratio: 1; } .productViewContainer .slider-button { align-self: center; width: 25px; } .slider-button > .iconArrow { fill: black; } .slider-button[disabled] > .iconArrow { fill: rgba(var(--color-foreground), 0.3); cursor: not-allowed; } .quick-view-modal { display: flex !important; } .fixed { overflow: hidden !important; } @media only screen and (max-width: 750px) { .productViewContainer { width: 100%; } } @media only screen and (max-width: 481px) { .productViewer .featured-product { display: flex; flex-direction: column; flex-wrap: nowrap; } .productViewer .product__media-wrapper { width: 100% !important; margin: auto; max-width: 25rem; } .productViewer .product__info-wrapper { width: 100% !important; max-width: 100% !important; } .productViewer:not(.product--no-media) > .product__info-wrapper { padding: 0 !important; } .mobilebutton { display: flex; } .desktopbutton { display: none; } .desktopbutton > span { width: 100%; font-size: clamp(12px, 2vw, 20px); } .buttonViewer { width: 20%; height: 3rem; top: 5%; left: 75%; display: flex; } } .slider-container { margin: 0 auto; width: 90%; display: flex; flex-flow: column wrap; align-items: center; position: relative; } .large-image { width: 100%; height: 100%; position: relative; overflow: hidden; } .large-image-item { max-width: 100%; width: 100%; max-height: 100%; padding: 0; position: relative; margin: 0 auto; } .xoomImage { position: absolute; top: 0; left: 0; } .large-image-item:not(:first-child) { display: none !important; } ul { padding-inline-start: 0px !important; } slider-component { position: relative; display: block; width: 100%; } .slider-wrapper { display: flex; justify-content: center; width: 100%; margin-top: 1rem; } .slider__slide { scroll-snap-align: start; flex-shrink: 0; } .product-slider-box { flex-wrap: inherit; overflow-x: auto; scroll-snap-type: x mandatory; scroll-behavior: smooth; -webkit-overflow-scrolling: touch; width: 100%; display: flex; z-index: 1; margin: 0 !important; } .product-slider { height: 100%; width: 25%; padding: 5px; display: inline-block; } .slide-image { width: 100%; object-fit: cover; } .slider { scrollbar-color: rgb(var(--color-foreground)) rgba(var(--color-foreground), 0.04); -ms-overflow-style: none; scrollbar-width: none; } .slider::-webkit-scrollbar { height: 0.4rem; width: 0.4rem; display: none; } .no-js .slider { -ms-overflow-style: auto; scrollbar-width: auto; } .no-js .slider::-webkit-scrollbar { display: initial; } .slider::-webkit-scrollbar-thumb { background-color: rgb(var(--color-foreground)); border-radius: 0.4rem; border: 0; } .slider::-webkit-scrollbar-track { background: rgba(var(--color-foreground), 0.04); border-radius: 0.4rem; } .button-wrapper { height: 100%; width: 105%; position: absolute; display: flex; justify-content: space-between; align-items: center; } .slider-container::-webkit-scrollbar { display: none; } .slider-buttons { display: flex; align-items: center; justify-content: center; } .slider-button { color: rgba(var(--color-foreground), 0.75); background: transparent; border: none; cursor: pointer; width: 44px; height: 44px; } .slider-button:not([disabled]):hover { color: rgb(var(--color-foreground)); } .slider-button .icon { height: 1.2rem; } .slider-button[disabled] .icon { color: rgba(var(--color-foreground), 0.3); } .slider-button--next .icon { margin-right: -0.2rem; transform: rotate(-90deg) translateX(0.15rem); } .slider-button--prev .icon { margin-left: -0.2rem; transform: rotate(90deg) translateX(-0.15rem); } .slider-button--next:not([disabled]):hover .icon { transform: rotate(-90deg) translateX(0.15rem) scale(1.07); } .slider-button--prev:not([disabled]):hover .icon { transform: rotate(90deg) translateX(-0.15rem) scale(1.07); } .video-btn { width: 100%; height: 100%; position: relative; } .v-btn { top: 2% !important; left: 2% !important; } .active-thumb { border: 3px solid white; outline: 2px solid black; } @media screen and (min-width: 750px) { .custom-width { padding: 0 10% !important; } } @media screen and (min-width: 990px) { .product__media-wrapper { max-width: 50% !important; width: calc(50% - 1rem / 2); } .product__info-wrapper { padding-left: 5rem !important; max-width: 50% !important; width: calc(50% - 1rem / 2); } } .quickViewButtonContainer { top: 5px; margin: 1rem; display: flex; justify-content: space-between; position: sticky; z-index: 2; } .errorMessage { margin-left: 5px; font-weight: 600; } .navigatorBtn { border-radius: 3px; height: 100%; padding: 1px 3px; margin-left: 5px; } .navigatorBtn:hover { background: red; } .navigatorBtn:disabled { cursor: not-allowed; opacity: 0.5; } .productViewer .product__media-icon { display: none !important; } .video-btn .product__media-icon { display: flex !important; } .productViewer .product__media-toggle:hover { cursor: pointer !important; } .productViewer .slider-button > svg { stroke-width: 1px; height: 1.2rem !important; } |
Step #5. Open global.js file
Next, open the global.js file under the same folder, Asset and add the code below.
class SliderQuickView extends HTMLElement { constructor() { super(); this.t = this.querySelector(".slider"); this.i = this.querySelectorAll(".product-slider"); this.pageCount = this.querySelector(".slider-counter--current"); this.h = this.querySelector(".slider-counter--total"); this.u = this.querySelector('button[name="previous"]'); this.l = this.querySelector('button[name="next"]'); if (!this.t || !this.l) return; const t = new ResizeObserver((t) => this.o()); t.observe(this.t); this.t.addEventListener("scroll", this.update.bind(this)); this.u.addEventListener("click", this.m.bind(this)); this.l.addEventListener("click", this.m.bind(this)); this.i.forEach((t) => t.addEventListener("click", this.v.bind(this))); } o() { const t = Array.from(this.i).filter((t) => t.clientWidth > 0); this.p = t[t.length - 1]; if (t.length === 0) return; this.k = Math.floor(this.t.clientWidth / t[0].clientWidth); this.g = t.length - this.k + 1; this.update(); } update() { if (!this.pageCount || !this.h) return; this.currentPage = Math.round(this.t.scrollLeft / this.p.clientWidth) + 1; if (this.currentPage === 1) { this.u.setAttribute("disabled", true); } else { this.u.removeAttribute("disabled"); } if (this.currentPage === this.g) { this.l.setAttribute("disabled", true); } else { this.l.removeAttribute("disabled"); } this.pageCount.textContent = this.currentPage; this.h.textContent = this.g; } m(t) { t.preventDefault(); const i = t.currentTarget.name === "next" ? this.t.scrollLeft + this.t.clientWidth : this.t.scrollLeft - this.t.clientWidth; this.t.scrollTo({ left: Math.floor(i) }); this.M = Math.round(i / this.t.clientWidth); if (this.M === 0) { this.u.setAttribute("disabled", true); } else { this.u.removeAttribute("disabled"); } if (this.M === this.g / 3) { this.l.setAttribute("disabled", true); } else { this.l.removeAttribute("disabled"); } } v(t) { this.V = t.currentTarget.dataset.P; this.q(this.V); this.T(this.V); } q(t) { this.$ = this.querySelector(`[data-media-id="${t}"]`); this.B = this.$.parentElement; this.B.prepend(this.$); this.$.style.display = "block"; } T(t) { this.C = this.querySelector(`[data-thumb-id='${t}']`); this.i.forEach((t) => t.querySelector("img").classList.remove("active-thumb") ); this.C.scrollIntoView({ H: "nearest", L: "center" }); this.C.querySelector("img").classList.add("active-thumb"); } } customElements.define("slider-quick-view", SliderQuickView); class ButtonViewer extends HTMLElement { constructor() { super(); this.O = document.querySelector("product-viewer"); this.D(); this.addEventListener("click", this.I.bind(this)); this.N; this.U; this.buttons = document.querySelectorAll("button-viewer"); this.A; } D() { this.closest("ul") .querySelectorAll("button-viewer") .forEach((t, i) => { t.setAttribute("data-view-index", i); }); this.A = this.closest("ul").querySelectorAll("button-viewer").length; this.innerHTML = this.O.querySelector("#buttonViewer").innerHTML; this.insertAdjacentHTML("afterbegin", this.R(this.innerHTML)); } R(t) { return new DOMParser().parseFromString(t, "text/html").querySelector("body") .innerHTML; } I(t) { this.S = t.currentTarget.dataset.product; this.O._(this.S); this.j = t.currentTarget.dataset.F; this.O.G(this.closest("ul"), this.j, this.A); } } customElements.define("button-viewer", ButtonViewer); class ProductViewer extends HTMLElement { constructor() { super(); this.J = this.querySelector(".viewerBackground"); this.O = this.querySelector(".productViewer"); this.K = this.querySelector(".productViewerClose"); this.K.addEventListener("click", this.W.bind(this)); this.u = this.querySelector(".prevNavigator"); this.l = this.querySelector(".nextNavigator"); this.X = this.querySelector(".errorMessage"); this.u.addEventListener("click", this.m.bind(this)); this.l.addEventListener("click", this.m.bind(this)); this.Y = new Event("change", { bubbles: true }); this.current; this.parent; this.A; } _(t) { this.Z(t); document.body.classList.toggle("fixed"); this.J.classList.toggle("quick-view-modal"); } Z(t) { fetch(`/products/${t}?section_id=quick-view-template`) .then((t) => t.text()) .then((t) => { this.tt = this.R(t); this.O.innerHTML = this.tt; }); } R(t) { return new DOMParser().parseFromString(t, "text/html").querySelector("body") .innerHTML; } W() { this.J.classList.toggle("quick-view-modal"); document.body.classList.toggle("fixed"); } m(t) { t.preventDefault(); t.target.getAttribute("name") == "next" ? (this.current = this.current + 1) : (this.current = this.current - 1); if (this.current == 0) { this.it = "This is the first product."; this.u.disabled = true; } else if (this.current == this.A) { this.it = "This is the last product."; this.l.disabled = true; } else { this.it = " "; this.u.disabled = false; this.l.disabled = false; } this.X.innerHTML = this.it; this.st = this.parent.querySelector(`[data-view-index='${this.current}']`); if (!this.st) return; this.Z(this.st.dataset.product); } G(t, i, s) { this.parent = t; this.current = i * 1; this.A = s - 1; } } customElements.define("product-viewer", ProductViewer); class VariantViewer extends VariantSelects { constructor() { super(); this.O = document.querySelector("slider-quick-view"); } ht() { if (!this.et) return; if (!this.et.rt) return; this.ct = this.et.rt.id; this.O.q(this.ct); this.O.T(this.ct); } } customElements.define("variant-viewer", VariantViewer); |
Step #6. Call quick-view.
We need to call this quick-view in the product card. Go to Snippet folder, if you have Dawn Theme version 2.5 above, open the card-product.liquid. Find the class "card-wrapper", then paste the code, after the line.
<button-viewer class="quickViewBtn" data-product="{{card_product.handle}}" ></button-viewer> |
For Dawn Theme 2.5 and lower, follow same instruction above but paste the code below instead.
<button-viewer class="quickViewBtn" data-product="{{product_card_product.handle}}" ></button-viewer> |
Step #7. Go to theme.liquid
Last thing, go to the theme.liquid folder on top. Then find the {% section 'announcement-bar' %}, paste the code above it.
| {% section 'quick-view' %} |
Step #8. Save the changes
Once you've added the code, save your changes to the theme code by clicking the SAVE button on the right hand upper corner.
Step #9. Customize theme
Go to the theme editor by clicking three dots on your left hand upper corner, then Customize theme. Make sure to SAVE once you are done customizing
Conclusion
Adding a quick view button to your Dawn theme can be a valuable way to enhance the user experience and potentially boost sales within your Shopify store. By providing a convenient method for customers to explore product details without navigating away from the current page, quick view functionality can keep them engaged and informed throughout their shopping journey.
The article likely provides specific instructions for adding a quick view button using the Dawn theme, either through a recommended app or by manual code edits. Remember to consider factors like mobile-friendliness, content optimization, and loading speed to ensure the quick view experience is seamless and efficient. By implementing a well-designed and user-friendly quick view button, you can encourage customers to learn more about your products and ultimately drive sales within your store.
0 comments