jelonyx
Section library · Section 08

Mobile sticky add-to-cart section
for Dawn and Horizon.

Boost conversions on mobile by keeping the Add to Cart button visible at all times. This section intelligently hides itself when the main product page button is visible and reappears when the user scrolls past it. No apps required.

TypeSection
Filesections/jlx-mobile-sticky-atc.liquid
Schema settings1 section setting
CostFree
Compatible with:Dawn 12+HorizonMost OS 2.0 themes

The code

One file. Paste the whole thing into a new section.

sections/jlx-mobile-sticky-atc.liquid
Liquid · CSS · JS · Schema
{% comment %}
  Jelonyx · Mobile Sticky ATC Section
  Compatible with Dawn 12+, Horizon, and most OS 2.0 themes
  Source: jelonyx.com/shopify/sections/mobile-sticky-atc
{% endcomment %}

{%- if product != blank -%}
<section id="jlx-sticky-atc-{{ section.id }}" class="jlx-sticky-atc">
  <div class="jlx-sticky-atc__inner">
    <div class="jlx-sticky-atc__details">
      {%- if product.featured_image != blank -%}
        <img 
          src="{{ product.featured_image | image_url: width: 100 }}" 
          alt="{{ product.featured_image.alt | escape }}"
          width="50" height="50"
          loading="lazy"
          class="jlx-sticky-atc__img"
        >
      {%- endif -%}
      <div class="jlx-sticky-atc__info">
        <p class="jlx-sticky-atc__title">{{ product.title }}</p>
        <p class="jlx-sticky-atc__price">{{ product.price | money }}</p>
      </div>
    </div>
    <div class="jlx-sticky-atc__form">
      {%- form 'product', product, id: 'jlx-sticky-atc-form' -%}
        <input type="hidden" name="id" value="{{ product.selected_or_first_available_variant.id }}">
        <button 
          type="submit" 
          name="add" 
          class="jlx-sticky-atc__button"
          {% unless product.selected_or_first_available_variant.available %}disabled{% endunless %}
        >
          {% if product.selected_or_first_available_variant.available %}
            {{ section.settings.button_text | default: 'Add to cart' }}
          {% else %}
            Sold out
          {% endif %}
        </button>
      {%- endform -%}
    </div>
  </div>
</section>

<style>
  .jlx-sticky-atc {
    display: none;
  }
  @media screen and (max-width: 767px) {
    .jlx-sticky-atc {
      display: block;
      position: fixed;
      bottom: 0;
      left: 0;
      width: 100%;
      background: var(--color-background, #fff);
      border-top: 1px solid var(--color-border, rgba(0,0,0,0.1));
      padding: 10px 15px;
      z-index: 99;
      box-shadow: 0 -2px 10px rgba(0,0,0,0.05);
      transform: translateY(100%);
      transition: transform 0.3s ease;
    }
    .jlx-sticky-atc.is-visible {
      transform: translateY(0);
    }
    .jlx-sticky-atc__inner {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: 15px;
    }
    .jlx-sticky-atc__details {
      display: flex;
      align-items: center;
      gap: 10px;
      min-width: 0;
    }
    .jlx-sticky-atc__img {
      width: 40px;
      height: 40px;
      object-fit: cover;
      border-radius: 4px;
    }
    .jlx-sticky-atc__info {
      min-width: 0;
    }
    .jlx-sticky-atc__title {
      font-size: 13px;
      font-weight: 600;
      margin: 0;
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
      color: var(--color-foreground, #1a1a1a);
    }
    .jlx-sticky-atc__price {
      font-size: 12px;
      margin: 0;
      color: var(--color-foreground-secondary, #6b6b6b);
    }
    .jlx-sticky-atc__form {
      flex-shrink: 0;
    }
    .jlx-sticky-atc__button {
      background: var(--color-button, #1a1a1a);
      color: var(--color-button-text, #fff);
      border: none;
      padding: 10px 20px;
      border-radius: 4px;
      font-size: 14px;
      font-weight: 600;
      cursor: pointer;
    }
    .jlx-sticky-atc__button:disabled {
      opacity: 0.5;
      cursor: not-allowed;
    }
  }
</style>

<script>
  document.addEventListener('DOMContentLoaded', function() {
    if (window.innerWidth > 767) return;
    
    var stickyBar = document.getElementById('jlx-sticky-atc-{{ section.id }}');
    var mainAtc = document.querySelector('form[action="/cart/add"] button[name="add"], .product-form__submit');
    
    if (!stickyBar || !mainAtc) return;
    
    var observer = new IntersectionObserver(function(entries) {
      if (entries[0].isIntersecting) {
        stickyBar.classList.remove('is-visible');
      } else {
        if (window.scrollY > entries[0].boundingClientRect.top) {
          stickyBar.classList.add('is-visible');
        }
      }
    }, { threshold: 0 });
    
    observer.observe(mainAtc);
  });
</script>
{%- endif -%}

{% schema %}
{
  "name": "Mobile sticky ATC",
  "tag": "section",
  "settings": [
    {
      "type": "text",
      "id": "button_text",
      "label": "Button text",
      "default": "Add to cart"
    }
  ],
  "presets": [
    {
      "name": "Mobile sticky ATC"
    }
  ],
  "templates": ["product"]
}
{% endschema %}

How to add the section

  1. 01
    Open your theme code editor.

    In Shopify Admin, go to Online Store → Themes. On your active theme, click the three-dot menu and select Edit code.

  2. 02
    Create a new section file.

    Under the Sections folder, click Add a new section. Name it jlx-mobile-sticky-atc and click Done.

  3. 03
    Paste the full section code.

    Delete any placeholder content in the new file, paste the entire code block above, and save.

  4. 04
    Add the section to your product template.

    Open the theme editor (Customize). Navigate to your Products → Default product template. Scroll down and click Add section, then select Mobile sticky ATC.

Schema settings

Section-level settings:

SettingTypeNotes
button_texttextOverride the default 'Add to cart' text on the button.
Shopify Section Build

Need this built for your store?

If you need complex variant logic support, quantity selectors integrated, or specific UI design alignment, we can help.