Collapsible Sidebar Layout

A common layout for SaaS applications, featuring a responsive sidebar that is collapsible on desktop and slides out on mobile.

HTML Code

This layout example is a full-page component. Copy the HTML below into your project. It requires Alpine.js for interactivity. You should also ensure your html and body tags have class="h-full".

HTML
<!-- This example requires Alpine.js to function. -->
<!-- <script src="//unpkg.com/alpinejs" defer></script> -->

<div x-data="{ sidebarOpen: window.innerWidth >= 1024, sidebarCollapsed: false }" 
     @resize.window="sidebarOpen = window.innerWidth >= 1024"
     class="min-h-screen bg-slate-100 font-sans text-slate-800">
    
    <!-- Mobile Sidebar -->
    <div x-show="sidebarOpen && window.innerWidth < 1024" 
         x-transition:enter="transition ease-in-out duration-300" 
         x-transition:enter-start="-translate-x-full" 
         x-transition:enter-end="translate-x-0" 
         x-transition:leave="transition ease-in-out duration-300" 
         x-transition:leave-start="translate-x-0" 
         x-transition:leave-end="-translate-x-full" 
         class="fixed inset-y-0 left-0 z-40 w-64 bg-slate-800 shadow-lg lg:hidden"
         @click.away="sidebarOpen = false"
         style="display: none;">
        <!-- Sidebar content -->
        <div class="flex h-full flex-col">
            <!-- Logo -->
            <div class="flex h-16 shrink-0 items-center px-4 bg-slate-900">
                <h1 class="text-2xl font-bold font-display text-white">YourApp</h1>
            </div>
            <!-- Navigation -->
            <nav class="flex-1 space-y-2 px-2 py-4">
                <a href="#" class="flex items-center gap-3 rounded-md bg-primary-700 px-3 py-2 text-sm font-semibold text-white">
                    <svg class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6"></path></svg>
                    Dashboard
                </a>
                <a href="#" class="flex items-center gap-3 rounded-md px-3 py-2 text-sm font-medium text-slate-300 hover:bg-slate-700 hover:text-white">
                    <svg class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4.354a4 4 0 110 5.292M15 21H3v-1a6 6 0 0112 0v1zm0 0h6v-1a6 6 0 00-9-5.197M15 21a6 6 0 00-9-5.197m0 0A5.995 5.995 0 0112 12.75a5.995 5.995 0 01-3 5.197z"></path></svg>
                    Team
                </a>
                <a href="#" class="flex items-center gap-3 rounded-md px-3 py-2 text-sm font-medium text-slate-300 hover:bg-slate-700 hover:text-white">
                    <svg class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 7v10a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2h-6l-2-2H5a2 2 0 00-2 2z"></path></svg>
                    Projects
                </a>
            </nav>
        </div>
    </div>
    <!-- Mobile sidebar overlay -->
    <div x-show="sidebarOpen && window.innerWidth < 1024" x-transition:enter="ease-in-out duration-300" x-transition:enter-start="opacity-0" x-transition:enter-end="opacity-100" x-transition:leave="ease-in-out duration-300" x-transition:leave-start="opacity-100" x-transition:leave-end="opacity-0" class="fixed inset-0 bg-slate-900/50 z-30 lg:hidden" style="display: none;"></div>

    <!-- Desktop Sidebar -->
    <div :class="{'w-64': !sidebarCollapsed, 'w-20': sidebarCollapsed}" class="hidden lg:fixed lg:inset-y-0 lg:flex lg:flex-col transition-all duration-300 bg-slate-800 z-20">
        <!-- Sidebar content -->
        <div class="flex h-full flex-col">
            <!-- Logo -->
            <div class="flex h-16 shrink-0 items-center justify-between px-4 bg-slate-900">
                <h1 x-show="!sidebarCollapsed" x-transition:enter="transition-opacity ease-linear duration-300" x-transition:enter-start="opacity-0" x-transition:enter-end="opacity-100" class="text-2xl font-bold font-display text-white">YourApp</h1>
                <button @click="sidebarCollapsed = !sidebarCollapsed" class="text-slate-400 hover:text-white">
                    <svg class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
                      <path stroke-linecap="round" stroke-linejoin="round" d="M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25h16.5" />
                    </svg>
                </button>
            </div>
            <!-- Navigation -->
            <nav class="flex-1 space-y-2 px-2 py-4">
                <a href="#" class="flex items-center gap-3 rounded-md bg-primary-700 px-3 py-2 text-sm font-semibold text-white" :class="{'justify-center': sidebarCollapsed}">
                    <svg class="h-5 w-5 shrink-0" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6"></path></svg>
                    <span x-show="!sidebarCollapsed" x-transition>Dashboard</span>
                </a>
                <a href="#" class="flex items-center gap-3 rounded-md px-3 py-2 text-sm font-medium text-slate-300 hover:bg-slate-700 hover:text-white" :class="{'justify-center': sidebarCollapsed}">
                    <svg class="h-5 w-5 shrink-0" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4.354a4 4 0 110 5.292M15 21H3v-1a6 6 0 0112 0v1zm0 0h6v-1a6 6 0 00-9-5.197M15 21a6 6 0 00-9-5.197m0 0A5.995 5.995 0 0112 12.75a5.995 5.995 0 01-3 5.197z"></path></svg>
                    <span x-show="!sidebarCollapsed" x-transition>Team</span>
                </a>
                <a href="#" class="flex items-center gap-3 rounded-md px-3 py-2 text-sm font-medium text-slate-300 hover:bg-slate-700 hover:text-white" :class="{'justify-center': sidebarCollapsed}">
                    <svg class="h-5 w-5 shrink-0" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 7v10a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2h-6l-2-2H5a2 2 0 00-2 2z"></path></svg>
                    <span x-show="!sidebarCollapsed" x-transition>Projects</span>
                </a>
            </nav>
        </div>
    </div>

    <!-- Main Content Area -->
    <div :class="{'lg:pl-64': !sidebarCollapsed, 'lg:pl-20': sidebarCollapsed}" class="flex flex-col flex-1 transition-all duration-300">
        <!-- Header -->
        <header class="sticky top-0 z-10 flex h-16 shrink-0 items-center gap-x-4 border-b border-slate-200 bg-white px-4 shadow-sm sm:px-6">
            <!-- Hamburger button for mobile -->
            <button @click="sidebarOpen = true" type="button" class="-m-2.5 p-2.5 text-slate-700 lg:hidden">
                <span class="sr-only">Open sidebar</span>
                <svg class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
                  <path stroke-linecap="round" stroke-linejoin="round" d="M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25h16.5" />
                </svg>
            </button>
            <div class="flex-1 text-sm font-semibold leading-6 text-slate-900">Dashboard</div>
        </header>

        <!-- Page Content -->
        <main class="flex-1 p-4 sm:p-6 lg:p-8">
            <div class="h-96 rounded-lg border-2 border-dashed border-slate-300 flex items-center justify-center">
                 <span class="text-slate-500">Your page content here</span>
            </div>
        </main>
    </div>
</div>