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.
Table of Contents
- 1. Why a sticky checkout summary matters in checkout
- 2. Using position sticky correctly
- 3. The most common bug: overflow on an ancestor
- 4. Height calculation with dvh instead of vh
- 5. Grid layout for checkout and sticky sidebar
- 6. Stacking context and z-index in checkout
- 7. Mobile behavior: sticky only from tablet width
- 8. Working with Alpine.js on total updates
- 9. Sticky strategies compared
- 10. Summary
- 11. FAQ
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.