How to Build an Expanding Card Gallery with Tailwind CSS & Alpine.js

In this article, I will show you how to create a stunning Expanding Card Gallery with Tailwind CSS & Alpine.js. You’re going to love how it looks — and you’ll definitely learn something new about Alpine.js along the way.

Introduction

Looking to create an eye-catching image gallery with smooth transitions and responsive design? In this tutorial, we’ll show you how to build a beautiful expanding card gallery using Tailwind CSS and Alpine.js—without writing complex JavaScript.

This method is perfect for landing pages, portfolios, or any project where you want a sleek, interactive card layout that works on both desktop and mobile devices.

Technologies Used

  • Tailwind CSS – For utility-first styling and responsiveness
  • Flowbite – Optional UI kit based on Tailwind (included in case you want to add buttons or modals later)
  • Alpine.js – A lightweight JavaScript framework for reactive behavior
  • Pixabay – Used for image links.
  • Responsive layout with fluid resizing
  • Smooth transition animations
  • Click to expand and focus on a specific card
  • Only the selected card title is visible
  • Optimized for mobile and desktop

How It Works

This gallery consists of multiple image cards placed in a horizontal flex container. Using Alpine.js, we track which card is selected and adjust the flex-grow property dynamically. The selected card expands, while others shrink to a minimal width.


Demo / Expanding Card Gallery with Tailwind CSS & Alpine.js

Note: For the best experience, try opening this in a new tab — the full UI might not display properly inside an iframe.

https://niyander.com/projects/components/expanding-cards.html


Full HTML Code Example

<!doctype html>
<html lang="en" class="scroll-smooth">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Expanding Cards with Alpine.js</title>
    <script src="https://cdn.tailwindcss.com"></script>
    <script src="https://unpkg.com/alpinejs" defer></script>
    <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/flowbite.min.css" rel="stylesheet"/>
    <link href="https://fonts.cdnfonts.com/css/google-sans" rel="stylesheet">
    <style>
      * {
        font-family: 'Product Sans Light', sans-serif;
      }
      .rounded-5xl {
        border-radius: 4rem;
      }
    </style>
  </head>
  <body class="bg-gray-900">
    <div class="container m-auto h-screen p-5">
      <h1 class="text-center mt-4 mb-2 text-3xl text-white">Expanding Cards with Alpine.js</h1>
      <p class="text-center mb-10 text-lg text-white">
        A responsive expanding card gallery using Tailwind CSS and Alpine.js with smooth transitions and a focus effect.
      </p>

      <!-- Alpine.js Component -->
      <div 
        class="flex items-center justify-center"
        x-data="{
          selected: 0,
          cards: [
            { title: 'Girl In Garden', image: 'https://cdn.pixabay.com/photo/2021/07/26/01/47/woman-6493189_1280.jpg' },
            { title: 'Couple', image: 'https://cdn.pixabay.com/photo/2019/06/25/04/01/wedding-4297343_1280.jpg' },
            { title: 'Boat Night', image: 'https://cdn.pixabay.com/photo/2024/12/09/16/22/boat-9255590_1280.jpg' },
            { title: 'Beautiful Girl', image: 'https://cdn.pixabay.com/photo/2020/07/30/10/29/woman-5450043_1280.jpg' },
            { title: 'Love', image: 'https://cdn.pixabay.com/photo/2019/11/10/11/13/couple-4615557_1280.jpg' }
          ]
        }"
      >
        <div class="flex w-[90vw] overflow-hidden transition-all duration-700 ease-in-out">
          <!-- Cards -->
          <template x-for="(card, index) in cards" :key="index">
            <div
              class="card relative h-[70vh] m-2 rounded-5xl bg-cover bg-center bg-no-repeat cursor-pointer transition-[flex] duration-700 ease-in-out flex items-end p-5 text-white"
              :class="selected === index ? 'flex-[5]' : 'flex-[0.5] hidden md:flex md:flex-[0.5]'"
              :style="`background-image: url(${card.image})`"
              @click="selected = index"
              x-show="index < 3 || (index >= 3 && window.innerWidth >= 768)"
            >
              <h3
                class="text-xl transition-opacity duration-300 ease-in delay-400 mb-6 ms-6"
                :class="selected === index ? 'opacity-100' : 'opacity-0'"
                x-text="card.title"
              ></h3>
            </div>
          </template>
        </div>
      </div>
    </div>
  </body>
</html>

You can also read these articleHow to Create a Countdown Timer with Alpine.js

Conclusion

With just Tailwind CSS and Alpine.js, you can build powerful, responsive, and interactive UI components—like this expanding card gallery—without the need for complex frameworks or writing mountains of JavaScript. This lightweight, elegant solution gives you full control over interactivity while keeping your codebase clean and maintainable.

Whether you’re a beginner exploring frontend development or a seasoned developer looking for fast, reliable ways to build engaging interfaces, this approach is incredibly flexible. You can easily extend it to include features like modals, dynamic data loading, swipe gestures, or even integrate with APIs to pull in live content.

Give it a try in your next project—and make your galleries pop!

Leave a Reply

Your email address will not be published. Required fields are marked *