Need free liquid code for a sticky bottom navigation bar/footer menu

Hello, I am looking for free and mobile-friendly Liquid code to add a sticky bottom navigation bar or footer menu to my Shopify store. I want it to always remain visible on mobile screens. Can anyone please provide the code or guide me on how to set this up?"

Try this code shared below.

<div class="mobile-bottom-nav">
  <a href="{{ routes.root_url }}" class="nav-item {% if request.page_type == 'index' %}active{% endif %}">
    <span>🏠</span>
    <small>Home</small>
  </a>

  <a href="/collections/all" class="nav-item {% if request.page_type == 'collection' %}active{% endif %}">
    <span>🛍️</span>
    <small>Shop</small>
  </a>

  <a href="{{ routes.cart_url }}" class="nav-item {% if request.page_type == 'cart' %}active{% endif %}">
    <span>🛒</span>
    <small>Cart</small>
  </a>

  <a href="{{ routes.account_url }}" class="nav-item {% if request.page_type == 'customers/account' %}active{% endif %}">
    <span>👤</span>
    <small>Account</small>
  </a>
</div>

<style>
.mobile-bottom-nav{
    position:fixed;
    bottom:0;
    left:0;
    width:100%;
    height:65px;
    background:#fff;
    display:flex;
    justify-content:space-around;
    align-items:center;
    box-shadow:0 -2px 10px rgba(0,0,0,.12);
    z-index:9999;
    border-top:1px solid #e5e5e5;
}

.mobile-bottom-nav .nav-item{
    flex:1;
    text-align:center;
    text-decoration:none;
    color:#666;
    font-size:12px;
    display:flex;
    flex-direction:column;
    align-items:center;
    justify-content:center;
    gap:3px;
}

.mobile-bottom-nav .nav-item span{
    font-size:22px;
    line-height:1;
}

.mobile-bottom-nav .nav-item.active{
    color:#000;
    font-weight:600;
}

@media(min-width:768px){
    .mobile-bottom-nav{
        display:none;
    }
}

body{
    padding-bottom:70px;
}
</style>

{% schema %}
{
  "name": "Mobile Bottom Navigation",
  "settings": [],
  "presets": [
    {
      "name": "Mobile Bottom Navigation"
    }
  ]
}
{% endschema %}

You can change the icons based on what you looking for.

Result:

  • Fixed to the bottom on phones, hidden on desktop automatically.
  • Each button’s label, link and icon are set in the theme editor, so no code editing after the first paste.
  • Live cart count badge on the Cart button.
  • Clean line icons, and it clears the iPhone home bar.

Steps:

1. Add the code

  • Online Store > Themes > your theme > ... > Edit code.
  • Under Sections, click Add a new section, name it mobile-bottom-nav, delete the starter code, paste the code below, then Save.

2. Turn it on for every page

  • Go back and click Customize.
  • In the left panel, under the Footer group, click Add section, and choose Mobile bottom nav. Save.

3. Set your links

  • Click the section, then each Nav item, and set its Label, Link and Icon.
  • Turn on Show cart item count on your Cart item.

The code

{%- comment -%} Sticky mobile bottom navigation bar {%- endcomment -%}
{%- liquid
  assign wrap_id = 'mbn-' | append: section.id
-%}

<style>
  #{{ wrap_id }}{
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 9998;
    display: flex;
    align-items: stretch;
    background: {{ section.settings.bg_color }};
    border-top: 1px solid {{ section.settings.border_color }};
    box-shadow: 0 -2px 12px rgba(0,0,0,.10);
    padding-bottom: env(safe-area-inset-bottom);
  }
  #{{ wrap_id }} .mbn-item{
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 3px;
    height: {{ section.settings.bar_height }}px;
    text-decoration: none;
    color: {{ section.settings.icon_color }};
    font-size: 11px;
    line-height: 1;
    position: relative;
  }
  #{{ wrap_id }} .mbn-item svg{ width: 24px; height: 24px; }
  #{{ wrap_id }} .mbn-item.is-active{ color: {{ section.settings.active_color }}; font-weight: 600; }
  #{{ wrap_id }} .mbn-badge{
    position: absolute;
    top: 6px;
    left: 54%;
    min-width: 17px;
    height: 17px;
    padding: 0 4px;
    border-radius: 9px;
    background: {{ section.settings.badge_color }};
    color: #fff;
    font-size: 10px;
    font-weight: 700;
    line-height: 17px;
    text-align: center;
  }
  #{{ wrap_id }} .mbn-badge[hidden]{ display: none; }
  @media (min-width: {{ section.settings.hide_above }}px){
    #{{ wrap_id }}{ display: none; }
  }
  @media (max-width: {{ section.settings.hide_above | minus: 1 }}px){
    body{ padding-bottom: calc({{ section.settings.bar_height }}px + env(safe-area-inset-bottom)); }
  }
</style>

<nav id="{{ wrap_id }}" role="navigation" aria-label="Bottom navigation">
  {%- for block in section.blocks -%}
    {%- liquid
      assign is_active = false
      if block.settings.link == routes.root_url and request.page_type == 'index'
        assign is_active = true
      elsif block.settings.link contains '/cart' and request.page_type == 'cart'
        assign is_active = true
      elsif block.settings.link contains '/collections' and request.page_type == 'collection'
        assign is_active = true
      elsif block.settings.link contains '/account' and request.page_type contains 'customers'
        assign is_active = true
      endif
    -%}
    <a href="{{ block.settings.link | default: '#' }}"
       class="mbn-item{% if is_active %} is-active{% endif %}"
       {{ block.shopify_attributes }}>
      {%- case block.settings.icon -%}
        {%- when 'home' -%}
          <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><path d="M3 10.5 12 3l9 7.5"/><path d="M5 9.5V21h14V9.5"/></svg>
        {%- when 'shop' -%}
          <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><path d="M4 7h16l-1 13H5L4 7Z"/><path d="M8.5 7a3.5 3.5 0 0 1 7 0"/></svg>
        {%- when 'search' -%}
          <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="7"/><path d="m20 20-3.2-3.2"/></svg>
        {%- when 'cart' -%}
          <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><circle cx="9" cy="20" r="1.4"/><circle cx="18" cy="20" r="1.4"/><path d="M3 4h2l2.2 11.2a1 1 0 0 0 1 .8h8.6a1 1 0 0 0 1-.8L21 8H6"/></svg>
        {%- when 'account' -%}
          <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="8" r="4"/><path d="M4 21c1.5-4 5-6 8-6s6.5 2 8 6"/></svg>
        {%- when 'heart' -%}
          <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><path d="M12 20s-7-4.4-9.2-8.6C1.3 8.5 2.8 5 6 5c2 0 3.2 1.2 4 2.4C10.8 6.2 12 5 14 5c3.2 0 4.7 3.5 3.2 6.4C19 15.6 12 20 12 20Z"/></svg>
        {%- when 'menu' -%}
          <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><path d="M4 7h16M4 12h16M4 17h16"/></svg>
        {%- when 'phone' -%}
          <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><path d="M6 3h3l1.5 5-2 1.5a12 12 0 0 0 6 6l1.5-2 5 1.5v3a2 2 0 0 1-2 2A17 17 0 0 1 4 5a2 2 0 0 1 2-2Z"/></svg>
      {%- endcase -%}
      {%- if block.settings.show_cart_count -%}
        <span class="mbn-badge" data-mbn-count {% if cart.item_count == 0 %}hidden{% endif %}>{{ cart.item_count }}</span>
      {%- endif -%}
      <span>{{ block.settings.label }}</span>
    </a>
  {%- endfor -%}
</nav>

<script>
  (function(){
    var badges = document.querySelectorAll('#{{ wrap_id }} [data-mbn-count]');
    if(!badges.length) return;
    function paint(n){
      badges.forEach(function(b){ b.textContent = n; b.hidden = (n <= 0); });
    }
    function refresh(){
      fetch('{{ routes.cart_url }}.js', {headers:{'Accept':'application/json'}})
        .then(function(r){ return r.json(); })
        .then(function(c){ paint(c.item_count); })
        .catch(function(){});
    }
    var _fetch = window.fetch;
    window.fetch = function(){
      var url = arguments[0] && (arguments[0].url || arguments[0]);
      var p = _fetch.apply(this, arguments);
      if(typeof url === 'string' && /\/cart\/(add|change|update|clear)/.test(url)){
        p.then(function(){ setTimeout(refresh, 60); });
      }
      return p;
    };
    document.addEventListener('visibilitychange', function(){ if(!document.hidden) refresh(); });
  })();
</script>

{% schema %}
{
  "name": "Mobile bottom nav",
  "tag": "section",
  "settings": [
    { "type": "header", "content": "Appearance" },
    { "type": "color", "id": "bg_color", "label": "Background", "default": "#ffffff" },
    { "type": "color", "id": "icon_color", "label": "Icon and label", "default": "#5c5c5c" },
    { "type": "color", "id": "active_color", "label": "Active page", "default": "#111111" },
    { "type": "color", "id": "badge_color", "label": "Cart count badge", "default": "#e02b2b" },
    { "type": "color", "id": "border_color", "label": "Top border", "default": "#e6e6e6" },
    { "type": "range", "id": "bar_height", "min": 50, "max": 80, "step": 1, "unit": "px", "label": "Bar height", "default": 62 },
    { "type": "range", "id": "hide_above", "min": 600, "max": 1000, "step": 10, "unit": "px", "label": "Hide on screens wider than", "default": 750 }
  ],
  "blocks": [
    {
      "type": "link",
      "name": "Nav item",
      "settings": [
        { "type": "text", "id": "label", "label": "Label", "default": "Home" },
        { "type": "url", "id": "link", "label": "Link" },
        {
          "type": "select", "id": "icon", "label": "Icon", "default": "home",
          "options": [
            { "value": "home", "label": "Home" },
            { "value": "shop", "label": "Shop" },
            { "value": "search", "label": "Search" },
            { "value": "cart", "label": "Cart" },
            { "value": "account", "label": "Account" },
            { "value": "heart", "label": "Wishlist" },
            { "value": "menu", "label": "Menu" },
            { "value": "phone", "label": "Contact" }
          ]
        },
        { "type": "checkbox", "id": "show_cart_count", "label": "Show cart item count", "default": false }
      ]
    }
  ],
  "max_blocks": 5,
  "presets": [
    {
      "name": "Mobile bottom nav",
      "blocks": [
        { "type": "link", "settings": { "label": "Home", "icon": "home" } },
        { "type": "link", "settings": { "label": "Shop", "icon": "shop" } },
        { "type": "link", "settings": { "label": "Search", "icon": "search" } },
        { "type": "link", "settings": { "label": "Cart", "icon": "cart", "show_cart_count": true } },
        { "type": "link", "settings": { "label": "Account", "icon": "account" } }
      ]
    }
  ]
}
{% endschema %}

Adjustable in the section settings:

  • colours,
  • bar height,
  • Hide on screens wider than (default 750px, so it stays mobile only). It ships with Home, Shop, Search, Cart and Account, and you can add up to five buttons.

Hi @rakhirani ,
Here’s a simple, free approach — add this via Online Store → Themes → Edit code → theme.liquid (paste before </body>):

<div class="sticky-bottom-nav">
  <a href="/" class="nav-item">
    <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor"><path d="M3 9l9-7 9 7v11a2 2 0 01-2 2H5a2 2 0 01-2-2z"/></svg>
    <span>Home</span>
  </a>
  <a href="/collections/all" class="nav-item">
    <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor"><rect x="3" y="3" width="7" height="7"/><rect x="14" y="3" width="7" height="7"/><rect x="14" y="14" width="7" height="7"/><rect x="3" y="14" width="7" height="7"/></svg>
    <span>Shop</span>
  </a>
  <a href="/search" class="nav-item">
    <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor"><circle cx="11" cy="11" r="8"/><path d="M21 21l-4.35-4.35"/></svg>
    <span>Search</span>
  </a>
  <a href="/cart" class="nav-item">
    <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor"><circle cx="9" cy="21" r="1"/><circle cx="20" cy="21" r="1"/><path d="M1 1h4l2.68 13.39a2 2 0 002 1.61h9.72a2 2 0 002-1.61L23 6H6"/></svg>
    <span>Cart ({{ cart.item_count }})</span>
  </a>
  <a href="/account" class="nav-item">
    <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor"><path d="M20 21v-2a4 4 0 00-4-4H8a4 4 0 00-4 4v2"/><circle cx="12" cy="7" r="4"/></svg>
    <span>Account</span>
  </a>
</div>

<style>
.sticky-bottom-nav {
  display: none;
}
@media (max-width: 768px) {
  .sticky-bottom-nav {
    display: flex;
    justify-content: space-around;
    align-items: center;
    position: fixed;
    bottom: 0;
    left: 0;
    width: 100%;
    background: #fff;
    border-top: 1px solid #e5e5e5;
    z-index: 999;
    padding: 6px 0;
    box-shadow: 0 -2px 6px rgba(0,0,0,0.05);
  }
  .sticky-bottom-nav .nav-item {
    display: flex;
    flex-direction: column;
    align-items: center;
    font-size: 11px;
    color: #333;
    text-decoration: none;
    gap: 2px;
  }
  body {
    padding-bottom: 60px;
  }
}
</style>

Hi Ajay,
I am reaching out to get some help with a few issues I’m experiencing on my website.
First, the bottom navigation bar appears in the mobile preview but is not visible on real mobile devices.
Second, there is excessive spacing at the bottom of the screen that needs to be reduced.
Finally, the navigation bar is scrolling with the page instead of remaining fixed in place.
Could you please take a look at these and apply the necessary fixes?
Thanks

rakhi rani