WooCommerce Cart Block Quantity Stepper Mobile Fix

WooCommerce Cart block quantity stepper not responding to taps on iOS Safari mobile after the 10.5 update? Here is the touch event bug and a clean fix.
WooCommerceWordPressCart Block
May 9, 20265 min read980 words

The Problem

A subscription store on WooCommerce 10.5 came back to me this week with the same complaint three of their support tickets had landed in 24 hours: customers on phones could not change cart quantities. The plus and minus buttons in the Cart block did nothing on tap, and the input field would not accept keyboard input on iOS Safari. Desktop was fine. The classic cart shortcode was fine. Only the new Cart block on mobile.

If you upgraded to WooCommerce 10.5 (or 10.4 with WordPress 6.9.1) and the Cart block quantity stepper stopped responding to taps on mobile devices but still works on desktop, this is the regression. It hits hardest on iOS Safari and Chrome for Android, and it silently kills conversions because users assume the site is broken and bounce.

Why It Happens

The Cart block ships from the @woocommerce/block-library package and registers a React tree inside wp-content/plugins/woocommerce/assets/js/blocks/cart-checkout. The quantity stepper is a controlled input wrapped in a button cluster, and in 10.5 the team changed the event handler from onClick to a delegated pointer handler to fix a separate bug with keyboard focus.

That delegated handler attaches a pointerdown listener to the cart container with passive: true. Three things go wrong on mobile:

  1. pointerdown with passive: true on iOS Safari does not fire reliably for synthesised pointer events from touch. WebKit treats pointerdown differently when the parent has touch-action: manipulation set by the surrounding theme. The native event still bubbles, but the React event system swallows it because the synthetic event pool was rewired in 18.3 and the new delegate code paths assume the native event fired.
  2. Theme CSS is overriding touch-action. A lot of block themes set touch-action: pan-y or touch-action: none on the cart wrapper to fix horizontal scroll. That blocks the stepper buttons from receiving the tap because the browser interprets the gesture as scroll-only.
  3. The input's inputmode="numeric" triggers the iOS number pad which captures focus before the React handler binds. When the page hydrates slowly on a mobile network, you get a race between the input picking up native focus and the controlled-input wiring up.

The 10.5 changelog calls the change a "minor refactor". For desktop users it is. For mobile it broke a primary purchase action.

The Fix

Step 1: Force touch-action: manipulation on the stepper container. Add this CSS in your theme or as a snippet, scoped tightly so you do not regress horizontal scroll:

.wp-block-woocommerce-cart-line-items-block .wc-block-components-quantity-selector,
.wp-block-woocommerce-cart-line-items-block .wc-block-components-quantity-selector__button,
.wp-block-woocommerce-cart-line-items-block .wc-block-components-quantity-selector__input {
  touch-action: manipulation;
}

touch-action: manipulation tells the browser to allow pan and pinch but skip the 300ms double-tap delay and let the click and pointer events fire immediately. This restores the tap behaviour on iOS without affecting scroll inside the cart container.

Step 2: Re-bind the click handler if you cannot upgrade past 10.5.4 yet. WooCommerce 10.5.4 ships a fix, but until your release window allows it, you can patch the event delegation client-side. Drop this in a small theme JS file enqueued on cart and checkout pages:

document.addEventListener('DOMContentLoaded', () => {
  const observer = new MutationObserver(() => {
    document.querySelectorAll(
      '.wc-block-components-quantity-selector__button:not([data-qc-bound])'
    ).forEach((btn) => {
      btn.dataset.qcBound = '1';
      btn.addEventListener('click', (e) => {
        e.stopPropagation();
        const input = btn.parentElement.querySelector('input[type="number"]');
        if (!input) return;
        const isPlus = btn.classList.contains(
          'wc-block-components-quantity-selector__button--plus'
        );
        const next = Number(input.value) + (isPlus ? 1 : -1);
        if (next < 1) return;
        input.value = String(next);
        input.dispatchEvent(new Event('input', { bubbles: true }));
        input.dispatchEvent(new Event('change', { bubbles: true }));
      }, { passive: false });
    });
  });
  observer.observe(document.body, { childList: true, subtree: true });
});

The MutationObserver wrapper handles the cart re-rendering after each quantity change, and the explicit input and change dispatch is what the React controlled input needs to update WooCommerce's Store API.

Step 3: Disable the inputmode hijack on touch devices. Long term, removing inputmode="numeric" from the stepper input on touch devices stops the number pad race. Hook into the block render filter:

add_filter( 'render_block_woocommerce/cart-line-items-block', function ( $block_content ) {
    if ( wp_is_mobile() ) {
        $block_content = str_replace(
            'inputmode="numeric"',
            'inputmode="none" readonly',
            $block_content
        );
    }
    return $block_content;
}, 10, 1 );

readonly plus inputmode="none" keeps the input value visible but blocks the keyboard, so users have to use the plus and minus buttons. Less flexible, but no race condition. Pair with Step 1 and the buttons respond cleanly on every device I have tested.

Step 4: Verify with a real device. Lighthouse mobile emulation will not catch this because emulation does not synthesise the same pointer event sequence as iOS. Use Safari Web Inspector connected to a real iPhone, or BrowserStack live mode. The WooCommerce Cart and Checkout Blocks documentation covers the customisation surface if you need deeper hooks into the block lifecycle.

The Lesson

The Cart block quantity stepper bug on mobile is a CSS touch-action regression combined with React 18.3's pointer event reset. Force touch-action: manipulation on the stepper, optionally re-bind clicks until you can update to 10.5.4, and always test on a real device when you ship a cart change. Lighthouse cannot replicate WebKit's pointer behaviour, so synthetic tests will pass while real users silently fail to add quantity.

If your store's mobile conversion has slipped after a WooCommerce update and you need a stabilisation pass, that is the kind of work I do — see my services. For another Cart Block issue I covered, look at WooCommerce coupon not applying in checkout block.

Back to blogStart a project