White bar appearing at bottom of mobile viewport – only on custom section

Topic summary

A white bar appears at the bottom of the mobile viewport (primarily iOS/Safari) when a specific custom Shopify section is present. The issue is isolated to that section; other sections render normally, and removing the section eliminates the bar.

Key observations:

  • Not related to popups/modals; the bar shows even when overlays are closed.
  • The bar appears when scrolling and the section enters view.
  • Occurs only on this custom section built with Custom Liquid, HTML, CSS, and a bit of JS.

Environment and references:

  • Product page link provided for reproduction.
  • Code snippet shared with section markup and CSS, including absolute-positioned overlay (.ms-hotspot-overlay-tag), hotspot buttons (.ms-hotspot-dot), z-index layering, and a pulse animation (@keyframes msPulse).
  • Screenshot attached illustrating the white bar at the viewport bottom.

Requested help:

  • Looking for known causes of this behavior in mobile Safari with custom sections.

Status:

  • No resolution yet; discussion remains open with unanswered questions.
Summarized with AI on December 13. AI used: gpt-5.

Hi everyone

I’m currently working on a custom Shopify section (built with Custom Liquid, HTML, CSS and a bit of JS). Link here: Tailor-Made Fireproof Watch Safe

Everything works as expected (layout, hotspots, popups, responsiveness), however I’m facing one issue that I’ve been stuck with for hours:

On mobile (especially iOS), a white bar appears at the bottom of the viewport, only when this specific section is present on the page.

Important details:

  • The white bar is not related to a popup or modal (it appears even when everything is closed).

  • It only happens on this custom section.

  • All other sections on the website behave correctly (the browser UI overlays transparently as expected).

  • When scrolling down, the page looks fine at first, but then the white bar appears once the section is in view.

  • Removing this section immediately removes the white bar.

Has anyone experienced something similar or knows what typically causes this behavior in custom sections on mobile Safari?

Any help would be highly appreciated :folded_hands:

Thanks in advance!

**Current Code here: **

<section
  id="shopify-section-{{ section.id }}"
  class="ms-hotspot-section"
  data-ms-hotspot
>
  <div class="page-width">

    <div class="ms-hotspot-card">

      <!-- IMAGE + HOTSPOTS -->
      <div class="ms-hotspot-media">

        <!-- INFO OVERLAY -->
        <div class="ms-hotspot-overlay-tag">
          <img
            src="https://cdn.shopify.com/s/files/1/0925/3381/7721/files/info.png?v=1764102669"
            alt=""
            class="ms-hotspot-overlay-icon"
          >
          <span>TAP THE MARKERS TO EXPLORE PERSONALIZATION OPTIONS</span>
        </div>

        {% if section.settings.image != blank %}
          <img
            src="{{ section.settings.image | image_url: width: 1600 }}"
            alt=""
            class="ms-hotspot-image"
          >
        {% endif %}

        {% for block in section.blocks %}
          <button
            type="button"
            class="ms-hotspot-dot"
            data-hotspot-id="{{ block.id }}"
            style="
              top: {{ block.settings.top }}%;
              left: {{ block.settings.left }}%;
            "
            aria-label="{{ block.settings.title }}"
          >
            <span class="ms-hotspot-pulse"></span>
            <img
              src="https://cdn.shopify.com/s/files/1/0925/3381/7721/files/Design_ohne_Titel_12.png?v=1765537820"
              alt=""
              class="ms-hotspot-icon"
            >
          </button>

          <!-- POPUP TEMPLATE -->
          <template id="ms-hotspot-template-{{ block.id }}">
            {% if block.settings.popup_image != blank %}
              <img
                src="{{ block.settings.popup_image | image_url: width: 900 }}"
                class="ms-hotspot-popup-image"
                alt=""
              >
            {% endif %}
            <h3>{{ block.settings.title }}</h3>
            {{ block.settings.text }}
          </template>
        {% endfor %}

      </div>

      <!-- TEXT CONTENT -->
      <div class="ms-hotspot-content">
        {% if section.settings.eyebrow != blank %}
          <p class="ms-hotspot-eyebrow">{{ section.settings.eyebrow }}</p>
        {% endif %}
        {% if section.settings.heading != blank %}
          <h2 class="ms-hotspot-heading">{{ section.settings.heading }}</h2>
        {% endif %}
        {% if section.settings.body_text != blank %}
          <div class="ms-hotspot-body">{{ section.settings.body_text }}</div>
        {% endif %}
      </div>

    </div>
  </div>

  <!-- POPUP -->
  <div class="ms-hotspot-overlay">
    <div class="ms-hotspot-popup">
      <button class="ms-hotspot-close" type="button">×</button>
      <div class="ms-hotspot-popup-content"></div>
    </div>
  </div>
</section>

<style>
/* ===== SECTION ===== */
.ms-hotspot-section {
  padding: 32px 0;
}

.ms-hotspot-section .page-width {
  padding-left: 16px;
  padding-right: 16px;
}

/* ===== CARD ===== */
.ms-hotspot-card {
  display: grid;
  grid-template-columns: 1.2fr 1fr;
  border: 1px solid rgba(0,0,0,0.08);
  border-radius: 10px;
  overflow: hidden;
  background: #fff;
}

/* ===== IMAGE ===== */
.ms-hotspot-media {
  position: relative;
}

.ms-hotspot-image {
  width: 100%;
  min-height: 320px;
  object-fit: cover;
  display: block;
}

/* ===== OVERLAY INFO ===== */
.ms-hotspot-overlay-tag {
  position: absolute;
  top: 12px;
  left: 12px;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: rgba(255,255,255,0.95);
  padding: 4px 8px;
  border-radius: 6px;
  font-size: 8px;
  letter-spacing: .08em;
  text-transform: uppercase;
  z-index: 3;
}

.ms-hotspot-overlay-icon {
  width: 12px;
  opacity: .7;
}

/* ===== CONTENT ===== */
.ms-hotspot-content {
  padding: 22px;
}

.ms-hotspot-eyebrow {
  font-size: 11px;
  letter-spacing: .18em;
  text-transform: uppercase;
  opacity: .6;
}

.ms-hotspot-heading {
  font-size: 22px;
  margin: 6px 0 10px;
}

.ms-hotspot-body {
  font-size: 13px;
  line-height: 1.6;
  opacity: .75;
}

/* ===== HOTSPOTS ===== */
.ms-hotspot-dot {
  position: absolute;
  transform: translate(-50%, -50%);
  width: 26px;
  height: 26px;
  border-radius: 50%;
  border: none;
  background: transparent;
  padding: 0;
  cursor: pointer;
  z-index: 5;
}

/* PNG ICON */
.ms-hotspot-icon {
  width: 100%;
  height: 100%;
  display: block;
  position: relative;
  z-index: 2;
}

/* PULSE RING */
.ms-hotspot-pulse {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: rgba(255,255,255,0.6);
  animation: msPulse 2.4s ease-out infinite;
  z-index: 1;
}

@keyframes msPulse {
  0% {
    transform: scale(1);
    opacity: .7;
  }
  70% {
    transform: scale(2);
    opacity: 0;
  }
  100% {
    transform: scale(2);
    opacity: 0;
  }
}

/* ===== POPUP ===== */
.ms-hotspot-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0,0,0,.45);
  display: none;
  align-items: center;
  justify-content: center;
  z-index: 9999;
}

.ms-hotspot-overlay.active {
  display: flex;
}

.ms-hotspot-popup {
  background: #fff;
  max-width: 520px;
  width: calc(100% - 32px);
  padding: 22px;
  border-radius: 12px;
  position: relative;
}

.ms-hotspot-close {
  position: absolute;
  top: 10px;
  right: 14px;
  font-size: 22px;
  background: none;
  border: none;
  cursor: pointer;
}

.ms-hotspot-popup-image {
  width: 100%;
  border-radius: 8px;
  margin-bottom: 12px;
}

.ms-hotspot-section {
  overflow: hidden;
}

html, body {
  max-height: 100%;
  overscroll-behavior-y: none;
}

.ms-hotspot-section, 
.ms-hotspot-card {
  transform: translateZ(0);
}

.ms-hotspot-overlay {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
}


/* ===== MOBILE ===== */
@media (max-width: 900px) {
  .ms-hotspot-card {
    grid-template-columns: 1fr;
  }
}
</style>

<script>
document.addEventListener('click', function(e) {
  const dot = e.target.closest('.ms-hotspot-dot');
  if (!dot) return;

  const section = dot.closest('[data-ms-hotspot]');
  const overlay = section.querySelector('.ms-hotspot-overlay');
  const content = section.querySelector('.ms-hotspot-popup-content');
  const template = section.querySelector('#ms-hotspot-template-' + dot.dataset.hotspotId);

  if (!template) return;

  content.innerHTML = template.innerHTML;
  overlay.classList.add('active');
});

document.addEventListener('click', function(e) {
  if (
    e.target.classList.contains('ms-hotspot-overlay') ||
    e.target.classList.contains('ms-hotspot-close')
  ) {
    e.target.closest('.ms-hotspot-overlay').classList.remove('active');
  }
});
</script>

{% schema %}
{
  "name": "Hotspot Card",
  "settings": [
    { "type": "image_picker", "id": "image", "label": "Main image" },
    { "type": "text", "id": "eyebrow", "label": "Eyebrow" },
    { "type": "text", "id": "heading", "label": "Heading" },
    { "type": "richtext", "id": "body_text", "label": "Text" }
  ],
  "blocks": [
    {
      "type": "hotspot",
      "name": "Hotspot",
      "settings": [
        {
          "type": "range",
          "id": "top",
          "label": "Top position (%)",
          "min": 0,
          "max": 100,
          "step": 1,
          "default": 50
        },
        {
          "type": "range",
          "id": "left",
          "label": "Left position (%)",
          "min": 0,
          "max": 100,
          "step": 1,
          "default": 50
        },
        {
          "type": "text",
          "id": "title",
          "label": "Popup title"
        },
        {
          "type": "richtext",
          "id": "text",
          "label": "Popup text"
        },
        {
          "type": "image_picker",
          "id": "popup_image",
          "label": "Popup image"
        }
      ]
    }
  ],
  "presets": [
    { "name": "Hotspot Card" }
  ]
}
{% endschema %}

1 Like

This is happening because there is a sticky-buy-button element which is creating that white bar. It seems like the elements inside of it already have display: none with the intent of hiding them but the container itself doesn’t, creating this effect.

The solution is to add CSS that applies display: none to this element as well.

sticky-buy-button {
    display: none !important;
}

Once added you should not see the bar anymore

To add to the above – this sticky button container is hidden when either product title, product form or page footer are in viewport.

So, adding more sections below product info section will push product title and product form to be “above” the viewport.

Hey @kronbergcollection,

Could you please share your store url and password [if applicable] so that I can take a look and provide you with the solution code.

Thanks