I have three expandable vertically stacked cards positioned in a flex layout below a fixed sticky header.
Requirements:
It would be nice to have scroll snap feature, so that scroll snaps to the top of each card (or gap above it) while scrolling.
What I tried:
I have set the overflow-y-auto, snap-y and snap-mandatory classes on parent card container and snap-center/snap-start on child cards. However, scroll snap doesn't work.
What am I doing wrong? Am I missing something?
Below is my code for the described example.
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script><div class="min-h-screen"><!-- Header --><div class="p-4 flex gap-2 bg-black h-[64px] sticky top-0 z-10"></div><!-- Flex container --><div class="group flex flex-col gap-4 py-4 overflow-y-auto snap-y snap-mandatory"><div class="card overflow-hidden transition-all duration-300 bg-red-300 snap-center h-[calc((100vh-64px-4*1rem)/3)] [&[opened]]:h-[calc(100vh-64px-2*1rem)] overflow-hidden"><div class="p-4 flex flex-col h-full"><div class="font-bold">Card 1</div><div class="mt-2 flex-1 overflow-auto"><table class="w-full border-collapse"><tbody><tr><td class="border p-2">Row 1</td></tr><tr><td class="border p-2">Row 2</td></tr><tr><td class="border p-2">Row 3</td></tr><tr><td class="border p-2">Row 4</td></tr><tr><td class="border p-2">Row 5</td></tr><tr><td class="border p-2">Row 6</td></tr><tr><td class="border p-2">Row 7</td></tr><tr><td class="border p-2">Row 8</td></tr><tr><td class="border p-2">Row 9</td></tr><tr><td class="border p-2">Row 10</td></tr><tr><td class="border p-2">Row 11</td></tr><tr><td class="border p-2">Row 12</td></tr><tr><td class="border p-2">Row 13</td></tr><tr><td class="border p-2">Row 14</td></tr><tr><td class="border p-2">Row 15</td></tr></tbody></table></div><button class="mt-2 px-3 py-1 bg-gray-200 rounded self-end" onclick="toggleCard(0, this)"> View more</button></div></div><div class="card overflow-hidden transition-all duration-300 bg-green-300 snap-center h-[calc((100vh-64px-4*1rem)/3)] [&[opened]]:h-[calc(100vh-64px-2*1rem)] overflow-hidden"><div class="p-4 flex flex-col h-full"><div class="font-bold">Card 2</div><div class="mt-2 flex-1 overflow-auto"><table class="w-full border-collapse"><tbody><tr><td class="border p-2">Row 1</td></tr><tr><td class="border p-2">Row 2</td></tr><tr><td class="border p-2">Row 3</td></tr><tr><td class="border p-2">Row 4</td></tr><tr><td class="border p-2">Row 5</td></tr><tr><td class="border p-2">Row 6</td></tr><tr><td class="border p-2">Row 7</td></tr><tr><td class="border p-2">Row 8</td></tr><tr><td class="border p-2">Row 9</td></tr><tr><td class="border p-2">Row 10</td></tr><tr><td class="border p-2">Row 11</td></tr><tr><td class="border p-2">Row 12</td></tr><tr><td class="border p-2">Row 13</td></tr><tr><td class="border p-2">Row 14</td></tr><tr><td class="border p-2">Row 15</td></tr></tbody></table></div><button class="mt-2 px-3 py-1 bg-gray-200 rounded self-end" onclick="toggleCard(1, this)"> View more</button></div></div><div class="card overflow-hidden transition-all duration-300 bg-blue-300 snap-center h-[calc((100vh-64px-4*1rem)/3)] [&[opened]]:h-[calc(100vh-64px-2*1rem)] overflow-hidden"><div class="p-4 flex flex-col h-full"><div class="font-bold">Card 3</div><div class="mt-2 flex-1 overflow-auto"><table class="w-full border-collapse"><tbody><tr><td class="border p-2">Row 1</td></tr><tr><td class="border p-2">Row 2</td></tr><tr><td class="border p-2">Row 3</td></tr><tr><td class="border p-2">Row 4</td></tr><tr><td class="border p-2">Row 5</td></tr><tr><td class="border p-2">Row 6</td></tr><tr><td class="border p-2">Row 7</td></tr><tr><td class="border p-2">Row 8</td></tr><tr><td class="border p-2">Row 9</td></tr><tr><td class="border p-2">Row 10</td></tr><tr><td class="border p-2">Row 11</td></tr><tr><td class="border p-2">Row 12</td></tr><tr><td class="border p-2">Row 13</td></tr><tr><td class="border p-2">Row 14</td></tr><tr><td class="border p-2">Row 15</td></tr></tbody></table></div><button class="mt-2 px-3 py-1 bg-gray-200 rounded self-end" onclick="toggleCard(2, this)"> View more</button></div></div></div></div>const cards = document.querySelectorAll('.card');function toggleCard(index, btn) { const card = cards[index]; const isOpen = card.hasAttribute('opened'); if (isOpen) { card.removeAttribute('opened'); btn.textContent = 'View more'; } else { card.setAttribute('opened', ''); btn.textContent = 'View less'; }}