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.
- Go to your All Products page.
- Select any product.
- 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:
- Preview your product pages on both desktop and mobile to ensure the sticky bar is functional.
- 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.