How To Make A Sticky Add to Cart Bar on Shopify [Dawn V15]


Welcome to IPSense Pro! Today, we’re diving into another Shopify tips and tricks tutorial. In this post, you’ll learn how to add a sticky add-to-cart bar to your Shopify store without using any apps. This is a cost-effective way to enhance your store’s functionality without worrying about ongoing fees from third-party apps.

Step 1: Preview the Sticky Add-to-Cart Bar

Before jumping into the code, let’s visualize how the sticky add-to-cart bar will function.

  1. Go to your All Products page.
  2. Select any product.
  3. As you scroll down, you’ll notice that the add-to-cart bar stays sticky at the bottom of the screen. When you scroll up, the bar disappears, and when you scroll down, it reappears.

The feature works seamlessly on both desktop and mobile versions. If your products have multiple variations (e.g., colors, sizes), the bar will include options for these as well.

Step 2: Customization in the Theme Settings

Now, let’s explore how you can customize this sticky add-to-cart bar:

  • Color Scheme: Like other Shopify sections, you can adjust the color scheme to fit your brand.
  • Size of the Add-to-Cart Button: Choose different button sizes (e.g., H1, H4) depending on your preference.
  • Quantity Field and Button Style: You can enable the quantity field and change the style of the add-to-cart button.
  • Padding and Offset: If you encounter any visibility issues (like the bar overlapping other elements), you can adjust the padding and offset settings.

Step 3: Adding the Sticky Add-to-Cart Bar Code




{% if section.settings.enable_section and request.page_type == 'product' and product.available %}
    {% liquid 
        assign current_variant = product.selected_or_first_available_variant
        assign product_form_id = 'product-form-' | append: section.id
        assign image = current_variant.image | default: product.featured_image 
        assign img_size = section.settings.img_width | append: 'x' | append: section.settings.img_height
    %}


    <style>
        #md-sticky-atc {
            position: fixed;
            bottom: 0;
            left: 0;
            width: 100%;
            z-index: 2;
            padding-top: {{ section.settings.pt }}rem;
            padding-bottom: {{ section.settings.pb }}rem;
            visibility: hidden;
            opacity: 0;
            transform: translateY(100%);
            transition: all .15s ease-out;
            border-top: 0.1rem solid rgba(var(--color-foreground),.08);
        }
        #md-sticky-atc.show {
            visibility: visible;
            opacity: 1;
            transform: translateY(0);
        }
        #md-sticky-atc .page-width-inner {
        }
        @media (min-width: 990px) {
            #md-sticky-atc .page-width-inner {
                display: flex;
                align-items: center;
                justify-content: space-between;
            }
        }
        #md-sticky-atc .product-content {
            display: flex;
            align-items: center;
            padding-bottom: .5rem;
        }
        @media (min-width: 990px) {
            #md-sticky-atc .product-content {
                padding-bottom: 0;
                padding-right: 2rem;
            }
        }
        #md-sticky-atc .product-content .product__title {
            margin: 0 0 .5rem;
        }
        #md-sticky-atc .product-content .price {
            display: flex;
            align-items: center;
        }
        #md-sticky-atc .product-content img {
            margin-right: .75rem;
        }
        #md-sticky-atc .product-form {
            flex-shrink: 0;
        }
        #md-sticky-atc .product-form .select {
            flex-shrink: 0;
            width: auto;
            margin-right: .75rem;
            flex-grow: 1;
            max-width: 50%;
        }
        @media (min-width: 990px) {
            #md-sticky-atc .product-form .select {
                flex-grow: 0;
            }
        }
        
        #md-sticky-atc .product-form .quantity-input-wrapper {
            display: flex;
            align-items: center;
        }
        #md-sticky-atc .product-form .quantity {
            /* display: none; */
            flex-shrink: 0;
            margin-right: .75rem;
        }
        @media (min-width: 990px) {
            #md-sticky-atc .product-form .quantity {
                display: flex;
            }
        }
        #md-sticky-atc .product-form button[name="add"] {
            flex-shrink: 0;
            flex-grow: 1;
            margin: 0;
        }
        @media (min-width: 990px) {
            #md-sticky-atc .product-form button[name="add"] {
                flex-grow: 0;
            }
        }
        @media (max-width: 800px) {
            #md-sticky-atc {
                display: block;
            }
        }

      #md-sticky-atc .icon.icon-caret {
    width: 12px;
    display: inline-block;
    vertical-align: middle;
        margin-right: 15px;
}

      .select__select {
        padding-right: 0 !important;
}

      @media (max-width: 768px) {
    #md-sticky-atc .product-form .quantity-input-wrapper {
        display: flex;
        align-items: center;
        justify-content: center;
    }

    #md-sticky-atc .product-form .select {
        max-width: 40%; /* Increase width for mobile */
    }

    .quantity {
        width: 32%; /* Adjust width for better mobile layout */
    }

    .button {
        padding: 0px 12px; /* Reduce padding for smaller screen */
        font-size: 15px !important; /* Slightly smaller font for mobile */
      min-width: unset !important;
    }
}

    </style>


    <script>
        window.addEventListener('DOMContentLoaded', (event) => {
            const stickyATC = document.querySelector('#md-sticky-atc')
            const img = stickyATC.querySelector('.product-content img')
            const btn = stickyATC.querySelector('[name="add"]')
            const btnSpinner = btn.querySelector('.loading__spinner')
            const selectField = stickyATC.querySelector('select[name="id"]')
            const threshold = document.querySelector('button[name="add"]').getBoundingClientRect().bottom + Number(stickyATC.dataset.offset)

            window.addEventListener('scroll', () => {
                if (window.scrollY > threshold) {
                    stickyATC.classList.add('show')
                    document.documentElement.style.paddingBottom = `${stickyATC.clientHeight}px`
                    document.documentElement.style.height = 'auto'
                } else {
                    stickyATC.classList.remove('show')
                    document.documentElement.style.paddingBottom = '0'
                }
            })

            if (selectField) {
                selectField.addEventListener('change', () => {
                    img.setAttribute('src', selectField.options[selectField.selectedIndex].dataset.img)
                })
            }

            document.querySelector('.product-form [name="id"]')?.addEventListener('change', (e) => {
                const value = Number(e.target.value)

                if (value) {
                    selectField.value = value
                }
            })
            
        })
    </script>

    <div id="md-sticky-atc" class="color-{{ section.settings.color_scheme }}" aria-hidden="true" data-offset="{{ section.settings.offset }}">
        <div class="page-width">
            <div class="page-width-inner">
                <div class="product-content">
                    {% if section.settings.show_img %}
                        <img
                            src="{{ image | img_url: img_size, crop: 'center' }}"
                            class=""
                            width="{{ section.settings.img_width }}"
                            height="{{ section.settings.img_height }}"
                            loading="lazy">
                    {% endif %}
                    <div class="">
                        <h3 class="product__title {{ section.settings.title_size }}">
                            {{ product.title }}
                        </h3>
                        <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: '' -%}
                        </div>
                    </div>
                </div>
                <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' -%}
                        <div class="quantity-input-wrapper">
                            <div class="select" style="{% if product.has_only_default_variant %}display: none;{% endif %}">
                                <select class="select__select" name="id" aria-label="Select variant">
                                    {% for variant in product.variants %}
                                        {% assign variant_image = variant.image | default: product.featured_image %}
                                        <option 
                                            value="{{ variant.id }}"
                                            data-img="{{ variant_image | img_url: img_size }}"
                                            {% if current_variant.id == variant.id %}selected{% endif %}>
                                            {{ variant.title }} - {{ variant.price | money }}
                                        </option>
                                    {% endfor %}
                                </select>
                                <svg aria-hidden="true" focusable="false" role="presentation" class="icon icon-caret" viewBox="0 0 10 6">
                                    <path fill-rule="evenodd" clip-rule="evenodd" d="M9.354.646a.5.5 0 00-.708 0L5 4.293 1.354.646a.5.5 0 00-.708.708l4 4a.5.5 0 00.708 0l4-4a.5.5 0 000-.708z" fill="currentColor"></path>
                                </svg>
                            </div>
                            {% if section.settings.show_quantity_input %}
                                <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>
                                        <span class="svg-wrapper">
                          {{- 'icon-minus.svg' | inline_asset_content -}}
                        </span>
                                    </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>
                                        <span class="svg-wrapper">
                          {{- 'icon-plus.svg' | inline_asset_content -}}
                        </span>
                                    </button>
                                </quantity-input>
                            {% endif %}
                            <button type="submit" name="add" class="product-form__submit button button--{{ section.settings.btn_style }}">
                                <span>
                                    {%- if current_variant.available -%}
                                        {{ 'products.product.add_to_cart' | t }}
                                    {%- else -%}
                                        {{ 'products.product.sold_out' | t }}
                                    {%- endif -%}
                                </span>
                                <div class="loading__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" style="stroke: rgb(var(--color-background));"></circle>
                                    </svg>
                                </div>
                            </button>
                        </div>
                    {% endform %}
                </product-form>
            </div>
        </div>
    </div>
{% endif %}

{% schema %}
{
    "name": "Sticky ATC",
    "settings": [
        {
            "type": "header",
            "content": "General"
        },
        {
            "type": "checkbox",
            "id": "enable_section",
            "label": "Enable \"Sticky ATC\"",
            "info": "Quickly enable or disable this feature",
            "default": true
        },
        {
          "type": "color_scheme",
          "id": "color_scheme",
          "label": "t:sections.all.colors.label",
          "default": "scheme-1"
        },
        {
            "type": "select",
            "id": "title_size",
            "label": "Title Size",
            "default": "h4",
            "options": [
                {  "value": "h1", "label": "H1" },
                {  "value": "h2", "label": "H2" },
                {  "value": "h3", "label": "H3" },
                {  "value": "h4", "label": "H4" },
                {  "value": "h5", "label": "H5" },
                {  "value": "h6", "label": "H6" }
            ]
        },
        {
            "type": "checkbox",
            "id": "show_img",
            "default": true,
            "label": "Show image"
        },
        {
            "type": "text",
            "id": "img_width",
            "default": "80",
            "label": "Image width (px)"
        },
        {
            "type": "text",
            "id": "img_height",
            "default": "80",
            "label": "Image height (px)"
        },
        {
            "type": "checkbox",
            "id": "show_quantity_input",
            "default": true,
            "label": "Show quantity field"
        },
        {
            "type": "select",
            "id": "btn_style",
            "options": [
                { "value": "primary", "label": "Primary" },
                { "value": "secondary", "label": "Secondary" }
            ],
            "default": "primary",
            "label": "'Add to cart' button style"
        },
        {
            "type": "header",
            "content": "Advanced"
        },
        {
            "type": "range",
            "id": "offset",
            "label": "Offset",
            "min": 0,
            "max": 500,
            "step": 10,
            "default": 0,
            "info": "Adjust the offset value when showing the Sticky ATC section related to the main product form."
        },
        {
            "type": "header",
            "content": "Spacing",
            "info": "Based on 'rem' values [Learn more](https://developer.mozilla.org/en-US/docs/Learn/CSS/Building_blocks/Values_and_units)"
        },
        {
            "type": "range",
            "id": "pt",
            "label": "Padding top",
            "min": 0,
            "max": 5,
            "step": 0.5,
            "default": 0.5
        },
        {
            "type": "range",
            "id": "pb",
            "label": "Padding bottom",
            "min": 0,
            "max": 5,
            "step": 0.5,
            "default": 0.5
        }
    ]
}
{% endschema %}

Include newly created section in theme.liquid below footer section

Locate the following piece of code {% sections ‘footer-group’ %} and below it, add the following code

{% section 'sticky-atc' %}

Step 4: Enable the Sticky Add-to-Cart Bar

Once the code is in place, you’ll need to enable the sticky add-to-cart bar in your theme’s Customize settings:

  • Go to your Shopify dashboard and open the Theme Customizer.
  • You’ll see an option for Sticky Add-to-Cart in the settings. Enable it by checking the box.

Step 5: Customize the Appearance

Within the customizer, you’ll have several options to tweak the bar’s appearance, including:

  • Choosing color schemes.
  • Adjusting button size and style.
  • Enabling/disabling specific features like the quantity field.

Once you’re satisfied with the appearance, click Save.

Step 6: Mobile Compatibility

The sticky add-to-cart bar works flawlessly on mobile devices, ensuring a seamless shopping experience for your customers on all platforms. Be sure to test it by previewing the changes on both desktop and mobile views.

Step 7: Final Touches and Testing

Before wrapping up, let’s make sure everything works as expected:

  1. Preview your product pages on both desktop and mobile to ensure the sticky bar is functional.
  2. If you encounter any issues with offset (the bar overlapping sections), adjust the offset in the customizer.

Conclusion

By following this guide, you’ve successfully added a sticky add-to-cart bar to your Shopify store without needing to install any paid apps. This simple addition can significantly improve the user experience on your site, leading to higher sales and better conversions.

5/5 - (31 votes)

About

Leave a Comment

Your email address will not be published. Required fields are marked *