Shopify themes, liquid, logos, and UX
My website: https://shopstellory.com/products/calmpulse
Hi guys, I'm using the 15.1.0 dawn theme. When I press the add to cart button, it doesn't give any 'feedback' like a loading circle or change in colour for example. Instead, it just stays the same without any animation.
I want the add to cart button to change into a loading circle when it is pressed, like the one here: https://bleame.com/products/crystal-hair-eraser
Please check this video for a better visual explanation: https://www.youtube.com/shorts/2byjI2xil0g
Thank you so much!
Hi,
Hope this will help
- Find Add to Cart Button Code
- Add spinner HTML
- Add css for spinner
- Add JavaScript to make it work
Code example
document.addEventListener("DOMContentLoaded", function () {
const addToCartBtn = document.querySelector('[id^="ProductSubmitButton"]');
const form = addToCartBtn.closest("form");
if (addToCartBtn && form) {
form.addEventListener("submit", function () {
const spinner = addToCartBtn.querySelector(".loading-spinner");
if (spinner) {
spinner.style.display = "inline-block";
addToCartBtn.setAttribute("disabled", "true");
addToCartBtn.style.opacity = "0.6"; // fades the button
addToCartBtn.style.pointerEvents = "none";
}
});
}
});
I can‘t see your code but the way to do this is maybe a little more involved than you might think. Shopify has a built in add to cart url that is generated with liquid, so if you want to build this you need to hijack the process of adding to the cart. Basically you need to fetch POST to the add to cart endpoint with the cart items, and while that request is going through you need to show the loader. When the request completes you need to stop showing the spinner and since you build this yourself, you need to account for any errors that happen during the request lifecycle, which includes showing the user an error message if the item was not added.
1. Modify the HTML:
Locate the add-to-cart button in your theme's code (usually within the product.liquid or similar file).
Add an SVG element containing the loading circle inside the button. For example:
<button type="submit" class="btn add-to-cart">
<span>Add to Cart</span>
<span class="loading-indicator">
<svg class="spinner" width="20" height="20" viewBox="0 0 20 20">
<circle cx="10" cy="10" r="8" stroke="currentColor" stroke-width="2" fill="none" stroke-dasharray="100" stroke-dashoffset="100" />
</svg>
</span>
</button>
2. Style the Loading Circle:
In your theme's CSS (e.g., base.css), add CSS to style the loading-indicator and the spinner (the SVG element).
Initially, hide the loading circle using display: none;.
Set up the animation for the rotating circle using animation: spin 1s linear infinite; and the @keyframes spin rule:
.loading-indicator {
display: none;
}
.spinner {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
animation: spin 1s linear infinite;
}
@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
3. Add JavaScript to Toggle the Circle:
In your theme's JavaScript (e.g., theme.js), add a function that:
Listens for the click event on the add-to-cart button.
Hides the button text.
Shows the loading circle.
Adds a class (e.g., disabled) to the button to prevent multiple clicks.
Hides the loading circle and shows the button text again when the cart is updated (you'll need to listen for a cart update event, possibly using the Shopify.cart.on event).
const addToCartButtons = document.querySelectorAll('.add-to-cart');
addToCartButtons.forEach(button => {
const loadingIndicator = button.querySelector('.loading-indicator');
const buttonText = button.querySelector('span:not(.loading-indicator)');
button.addEventListener('click', (event) => {
event.preventDefault();
buttonText.style.display = 'none';
loadingIndicator.style.display = 'block';
button.classList.add('disabled'); // Disable further clicks
});
// When cart updates, hide loading and show button text again
shopify.cart.on('update', () => {
loadingIndicator.style.display = 'none';
buttonText.style.display = 'inline';
button.classList.remove('disabled');
});
});
4. Adjust the loading circle's appearance to match your theme.
You can customize the color, size, and animation of the loading circle by modifying the CSS styles.
Consider using a CSS library or tool like Animate.css for more advanced animation options.
Thanks!
Your cart button originally did it.
However, the "monster cart upsell" app overrides the cart button functionality.
Have you checked the app configuration whether it's possible to add some kind of loading animation there?
If not -- the app has some hooks which we can use.
Add a "Custom liquid" block in your "Product information" section and paste the following code:
<script>
var showSpinner = (submitButton) => {
submitButton.setAttribute("aria-disabled", !0), // taken from the theme code
submitButton.classList.add("loading"),
submitButton.querySelector(".loading__spinner").classList.remove("hidden");
}
var hideSpinner = (submitButton) => {
submitButton.setAttribute("aria-disabled", !!0), // taken from the theme code
submitButton.classList.remove("loading"),
submitButton.querySelector(".loading__spinner").classList.add("hidden");
}
var old_hook = window.mu_custom_atc_logic;
// app calls this function when adding to cart
window.mu_custom_atc_logic = () => {
const atcButton = document.querySelector('form[action*="/cart/add"] [type=submit');
if (atcButton) {
showSpinner(atcButton);
// this is called when adding to cart finished
window.addToCartCallBack = () => {
hideSpinner(atcButton)
};
}
if (old_hook) return old_hook();
}
</script>
I could not fully test the code for obvious reasons, so it would be best to make a theme copy and try it there first.
Learn how to build powerful custom workflows in Shopify Flow with expert guidance from ...
By Jacqui May 7, 2025Did You Know? May is named after Maia, the Roman goddess of growth and flourishing! ...
By JasonH May 2, 2025Discover opportunities to improve SEO with new guidance available from Shopify’s growth...
By Jacqui May 1, 2025