Sticky Checkout Summary with CSS: The Cart Overview That Scrolls Along
AI generated
{ }
@
CSS · Checkout · position sticky · Magento 2
Sticky Checkout Summary with CSS
The cart overview that reliably scrolls along

A sticky checkout summary sounds like a single CSS line, yet position sticky regularly breaks in checkout due to overflow containers, wrong height calculations and stacking context traps. With dvh units, a clean scroll container and the right grid structure, the cart overview stays reliably visible while the user scrolls through the checkout steps.

16 min read position sticky · dvh · Scroll Container Magento 2 Checkout · Hyva

1. Why a sticky checkout summary matters in checkout

In a multi step checkout with shipping address, payment method and order overview, users easily lose track of the total and cart contents while scrolling. A sticky checkout summary keeps exactly this information visible while the main area with the form fields keeps scrolling normally. That reduces cart abandonment, because users do not have to scroll back up to check whether a discount code was applied correctly or how high the shipping cost turns out to be.

In practice, however, a sticky checkout summary is one of the most common places where position: sticky seemingly fails for no reason. That is rarely caused by sticky itself, but almost always by the surrounding layout structure, by overflow properties on a parent element, or by wrongly calculated heights on mobile devices. The sections below systematically walk through what makes a sticky checkout summary reliable, and what regularly breaks it in practice.

2. Using position sticky correctly

The basic principle of a sticky checkout summary is simple: position: sticky together with a top value lets the element scroll normally in document flow until it reaches the defined position, then holds it there as long as the parent container still has visible room. Unlike position: fixed, the element does not stick to the screen permanently, it respects the boundaries of its container, which is essential for a checkout summary so it does not float past the footer.

Important for a correctly working sticky checkout summary: the top value must match the height of any sticky header present, otherwise the summary partially disappears behind the header. An additional max-height value combined with overflow-y: auto on the summary itself prevents a very long cart list with many line items from overflowing the viewport so the order button at the bottom becomes unreachable.


/* Basic sticky checkout summary — respects a sticky header above it */
.checkout-summary {
  position: sticky;
  top: 5rem; /* matches the height of the sticky header */
  align-self: start; /* prevents grid stretching from breaking sticky */
  max-height: calc(100dvh - 6rem);
  overflow-y: auto;
}

3. The most common bug: overflow on an ancestor

By far the most common reason a sticky checkout summary does not work is an ancestor element with overflow: hidden, overflow: auto or overflow: scroll that is not itself the scroll container the user actually moves. Sticky positioning always refers to the nearest scrolling ancestor, and as soon as any element in between opens its own overflow context, the sticky calculation breaks, without any error appearing in the browser.

In Magento checkout templates this often happens unintentionally when a card layout wrapper uses overflow-hidden for rounded corners. The fix for a working sticky checkout summary is to solve rounded corners with border-radius alone instead of overflow: hidden, or to place the overflow container so it does not sit between the sticky element and the actual scroll container.


<!-- WRONG: overflow-hidden wrapper between grid and sticky element breaks sticky -->
<div class="grid grid-cols-3 gap-8">
  <main class="col-span-2">...</main>
  <div class="overflow-hidden rounded-2xl"> <!-- breaks sticky child below -->
    <aside class="checkout-summary sticky top-20">...</aside>
  </div>
</div>

<!-- RIGHT: rounded corners via border-radius only, no overflow-hidden ancestor -->
<div class="grid grid-cols-3 gap-8">
  <main class="col-span-2">...</main>
  <aside class="checkout-summary sticky top-20 rounded-2xl border border-gray-200">...</aside>
</div>

4. Height calculation with dvh instead of vh

On mobile devices the browser's dynamic address bar changes the actually available height while the user scrolls. The classic vh unit is calculated from the largest possible viewport height and causes, in a sticky checkout summary, max-height: 100vh to reserve more room than is actually visible once the address bar appears. The result: the bottom edge of the summary, including the order button, gets cut off.

The dvh unit, for dynamic viewport height, solves this problem because it adapts live to the actually visible height, whether the address bar is shown or hidden. For a sticky checkout summary, calc(100dvh - Nrem) is therefore the more reliable expression than 100vh, especially on iOS Safari, where the difference between smallest and largest viewport height can amount to several dozen pixels.


/* dvh adapts to the actually visible viewport, not the largest possible one */
.checkout-summary {
  /* WRONG on mobile: 100vh assumes the browser chrome is always collapsed */
  /* max-height: calc(100vh - 6rem); */

  /* RIGHT: dvh tracks the real visible height as the address bar shows/hides */
  max-height: calc(100dvh - 6rem);
}

/* svh as a safe fallback for the smallest possible viewport, e.g. sticky CTA */
.checkout-cta-bar {
  bottom: calc(100svh - 100dvh);
}

5. Grid layout for checkout and sticky sidebar

For a sticky checkout summary, the choice of surrounding layout is decisive. CSS Grid with two columns, for example grid-cols-3 with the main area spanning two columns and the summary in the third, works reliably as long as align-items: start is set. Without this attribute, grid containers stretch their children to the full row height by default, which prevents the sticky element from moving within its grid area, because it already occupies the full height.

Flexbox as an alternative also works for a sticky checkout summary, but needs the same caution: align-items: flex-start on the flex container prevents the sidebar from being stretched to the height of the main area. Without this setting the sticky element simply has no room to move, because it is as tall as the entire container from the start.

Problem Cause Fix CSS Property
Sticky does not move at all overflow-hidden on an ancestor Remove the overflow container overflow: visible
Summary hidden behind header top value too small Match top to header height top: 5rem
Button cut off at the bottom 100vh on mobile devices Use dvh instead of vh 100dvh
Sidebar stretched to full height Grid stretches children by default Set align-items: start align-self: start

6. Stacking context and z-index in checkout

A checkout usually contains several elements competing for the same screen layer: a sticky header, a cookie banner, a modal for address suggestions and the sticky checkout summary itself. Without deliberate z-index planning, the summary visually ends up behind the header, or a dropdown menu disappears behind the summary even though it should actually sit above it.

The reliable solution is a documented z-index scale in which every layer gets a fixed range, for example header at 50, summary at 40, dropdown overlays at 60 and modals at 100. For the sticky checkout summary, a moderate value like z-index: 10 is usually enough, as long as it sits below modals but above the normal content flow. It matters that position: sticky itself already opens a new stacking context, which can lead to surprises with nested sticky elements.

7. Mobile behavior: sticky only from tablet width

On narrow mobile devices, a permanently visible sticky checkout summary is often counterproductive, because it takes valuable vertical space away from the form fields. Common practice is to show the summary on mobile as a collapsible bar at the bottom of the screen that only shows the total and expands to the full overview on click, while position: sticky only becomes active from a Tailwind breakpoint like lg:sticky.

This split elegantly uses Tailwind utility prefixes: static lg:sticky lg:top-20 ensures the summary stays in normal flow on small screens while becoming a classic sticky checkout summary from desktop width upward. For the mobile variant, a small Alpine.js component handles expanding and collapsing the compact bar, without touching the underlying CSS logic of the desktop version.

8. Working with Alpine.js on total updates

As soon as the user enters a discount code or switches shipping method, the sticky checkout summary must update without causing a layout jump that briefly breaks the sticky position. If the summary's height changes due to a new row like an additional discount entry, the available scroll height can briefly shift, which can cause visible jank if no transition property is set.

A smooth transition on max-height together with Alpine.js, which only updates the number values via x-text without re-rendering the structure itself, keeps the sticky checkout summary visually calm. It matters that Alpine here only swaps data and does not create new DOM nodes, because newly created elements can reset the browser's sticky state.

9. Sticky strategies compared

Besides position: sticky, there are other approaches to implementing a sticky checkout summary, each with its own trade offs in effort and reliability. A pure JavaScript based sticky polyfill that manually toggles position via a scroll listener was common before position: sticky had broad browser support, but today it causes unnecessary overhead and visible jank on every scroll event, because the main thread stays constantly busy.

position: fixed as an alternative solves the jank problem but completely ignores the boundaries of the parent container and has to calculate the collision with the footer manually via JavaScript, which in practice is more error prone than the native sticky checkout summary with position: sticky. The native solution wins in almost every case, because modern browsers calculate it without a scroll listener and without layout thrashing.

Approach Performance Respects Container Bounds Recommendation
position: sticky No scroll listener needed Yes, automatically Always the first choice
position: fixed + JS Extra calculation required No, needs manual handling Only for very special edge cases
Scroll listener polyfill Jank on every scroll event Only with a lot of extra code Outdated, no longer needed
Static without sticky No cost Trivial Worse visibility of the total

Mironsoft

Checkout optimization for Magento 2 and Hyva

Sticky summary that actually works in checkout?

We analyze existing checkout layouts for overflow traps, wrong height calculation and stacking conflicts, and build a sticky checkout summary that reliably scrolls along on every device.

Sticky Diagnosis

Identifying overflow ancestors and stacking context conflicts

Responsive Implementation

Mobile bar and desktop sidebar from one shared foundation

Conversion Focus

Reducing checkout abandonment through better visibility of the total

10. Summary

A working sticky checkout summary is rarely a pure styling problem, it is mostly a question of the layout structure around it. position: sticky itself works reliably, but breaks on overflow properties on an ancestor, on a missing align-self: start in a grid or flex container, and on the wrong viewport unit on mobile devices. dvh instead of vh, a clean scroll container inside the summary and a documented z-index scale solve the most common practical problems.

For small screens, a compact, collapsible variant is worth it instead of the full sticky checkout summary, so the limited space is not blocked by the summary. Whoever addresses these points systematically ends up with a checkout summary that scrolls along on every device without sticky bugs and gives the user orientation throughout the entire checkout process.

Sticky Checkout Summary with CSS — The Essentials at a Glance

Overflow Traps

No overflow: hidden between the sticky element and the actual scroll container.

dvh over vh

calc(100dvh - Nrem) adapts to the real visible height on mobile devices.

align-self: start

Prevents grid or flex from stretching the sidebar to full height and blocking sticky.

Mobile Special Case

Compact collapsible bar instead of the full sidebar on small screens.

11. FAQ: Sticky Checkout Summary with CSS

1Why does sticky not work?
Usually overflow on an ancestor that is not the actual scroll container.
2Why does it disappear behind the header?
top value is smaller than the header height, both need to match.
3Why is the button cut off?
100vh ignores the dynamic address bar, dvh instead of vh fixes it.
4Why does the sidebar not move?
Grid or flex stretches children by default, align-self: start gives room to move.
5Should mobile be sticky too?
Usually not, a compact collapsible bar is more space efficient.
6What z-index does it need?
A moderate value like 10, below modals but above normal content.
7What if the summary gets too long?
max-height and overflow-y auto create a dedicated scroll container.
8Grid or flexbox for the sidebar?
Both work, the key is setting align-items or align-self to start.
9Does Alpine.js cause jank?
Only with DOM recreation instead of x-text updates, a transition helps too.
10Compatible with cookie banners?
Yes, as long as both have a documented z-index layer.