methuselah
methuselah

Reputation: 13216

Tailwind - keep header and left/right sidebar sticky on scroll

How do I keep my header, left/right sidebar sticky on scroll (on desktop, not mobile)?

It doesn't seem to be working with the fixed or sticky class, I've posted an example here: https://play.tailwindcss.com/Bj68nUJj1C.

<!-- Background color split screen for large screens -->
<div class="fixed top-0 left-0 h-full w-1/2 bg-white" aria-hidden="true"></div>
<div class="fixed top-0 right-0 h-full w-1/2 bg-gray-50" aria-hidden="true"></div>
<div class="relative flex min-h-screen flex-col">
  <!-- Navbar -->
  <nav class="flex-shrink-0 bg-indigo-600">
    <div class="mx-auto max-w-7xl px-2 sm:px-4 lg:px-8">
      <div class="relative flex h-16 items-center justify-between">
        <!-- Logo section -->
        <div class="flex items-center px-2 lg:px-0 xl:w-64">
          <div class="flex-shrink-0">
            <img class="h-8 w-auto" src="https://tailwindui.com/img/logos/workflow-mark.svg?color=indigo&shade=300" alt="Workflow" />
          </div>
        </div>

        <!-- Search section -->
        <div class="flex flex-1 justify-center lg:justify-end">
          <div class="w-full px-2 lg:px-6">
            <label for="search" class="sr-only">Search projects</label>
            <div class="relative text-indigo-200 focus-within:text-gray-400">
              <div class="pointer-events-none absolute inset-y-0 left-0 flex items-center pl-3">
                <!-- Heroicon name: mini/magnifying-glass -->
                <svg class="h-5 w-5" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
                  <path fill-rule="evenodd" d="M9 3.5a5.5 5.5 0 100 11 5.5 5.5 0 000-11zM2 9a7 7 0 1112.452 4.391l3.328 3.329a.75.75 0 11-1.06 1.06l-3.329-3.328A7 7 0 012 9z" clip-rule="evenodd" />
                </svg>
              </div>
              <input id="search" name="search" class="block w-full rounded-md border border-transparent bg-indigo-400 bg-opacity-25 py-2 pl-10 pr-3 leading-5 text-indigo-100 placeholder-indigo-200 focus:bg-white focus:text-gray-900 focus:placeholder-gray-400 focus:outline-none focus:ring-0 sm:text-sm" placeholder="Search projects" type="search" />
            </div>
          </div>
        </div>
        <div class="flex lg:hidden">
          <!-- Mobile menu button -->
          <button type="button" class="inline-flex items-center justify-center rounded-md bg-indigo-600 p-2 text-indigo-400 hover:bg-indigo-600 hover:text-white focus:outline-none focus:ring-2 focus:ring-white focus:ring-offset-2 focus:ring-offset-indigo-600" aria-controls="mobile-menu" aria-expanded="false">
            <span class="sr-only">Open main menu</span>
            <!--
              Icon when menu is closed.

              Heroicon name: outline/bars-3-center-left

              Menu open: "hidden", Menu closed: "block"
            -->
            <svg class="block h-6 w-6" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true">
              <path stroke-linecap="round" stroke-linejoin="round" d="M3.75 6.75h16.5M3.75 12H12m-8.25 5.25h16.5" />
            </svg>
            <!--
              Icon when menu is open.

              Heroicon name: outline/x-mark

              Menu open: "block", Menu closed: "hidden"
            -->
            <svg class="hidden h-6 w-6" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true">
              <path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12" />
            </svg>
          </button>
        </div>
        <!-- Links section -->
        <div class="hidden lg:block lg:w-80">
          <div class="flex items-center justify-end">
            <div class="flex">
              <a href="#" class="rounded-md px-3 py-2 text-sm font-medium text-indigo-200 hover:text-white">Documentation</a>
              <a href="#" class="rounded-md px-3 py-2 text-sm font-medium text-indigo-200 hover:text-white">Support</a>
            </div>
            <!-- Profile dropdown -->
            <div class="relative ml-4 flex-shrink-0">
              <div>
                <button type="button" class="flex rounded-full bg-indigo-700 text-sm text-white focus:outline-none focus:ring-2 focus:ring-white focus:ring-offset-2 focus:ring-offset-indigo-700" id="user-menu-button" aria-expanded="false" aria-haspopup="true">
                  <span class="sr-only">Open user menu</span>
                  <img class="h-8 w-8 rounded-full" src="https://images.unsplash.com/photo-1517365830460-955ce3ccd263?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=256&h=256&q=80" alt="" />
                </button>
              </div>

              <!--
                Dropdown menu, show/hide based on menu state.

                Entering: "transition ease-out duration-100"
                  From: "transform opacity-0 scale-95"
                  To: "transform opacity-100 scale-100"
                Leaving: "transition ease-in duration-75"
                  From: "transform opacity-100 scale-100"
                  To: "transform opacity-0 scale-95"
              -->
              <div class="absolute right-0 z-10 mt-2 w-48 origin-top-right rounded-md bg-white py-1 shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none" role="menu" aria-orientation="vertical" aria-labelledby="user-menu-button" tabindex="-1">
                <!-- Active: "bg-gray-100", Not Active: "" -->
                <a href="#" class="block px-4 py-2 text-sm text-gray-700" role="menuitem" tabindex="-1" id="user-menu-item-0">View Profile</a>
                <a href="#" class="block px-4 py-2 text-sm text-gray-700" role="menuitem" tabindex="-1" id="user-menu-item-1">Settings</a>
                <a href="#" class="block px-4 py-2 text-sm text-gray-700" role="menuitem" tabindex="-1" id="user-menu-item-2">Logout</a>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </nav>

  <!-- 3 column wrapper -->
  <div class="mx-auto w-full max-w-7xl flex-grow lg:flex xl:px-8">
    <!-- Left sidebar & main wrapper -->
    <div class="min-w-0 flex-1 bg-white xl:flex">
      <div class="border-b border-gray-200 bg-white xl:w-64 xl:flex-shrink-0 xl:border-b-0 xl:border-r xl:border-gray-200">
        <div class="h-full py-6 pl-4 pr-6 sm:pl-6 lg:pl-8 xl:pl-0">
          <!-- Start left column area -->
          <div class="relative h-full" style="min-height: 12rem">
            <div class="absolute inset-0 rounded-lg border-2 border-dashed border-gray-200"></div>
          </div>
          <!-- End left column area -->
        </div>
      </div>

      <div class="bg-white lg:min-w-0 lg:flex-1">
        <div class="h-full py-6 px-4 sm:px-6 lg:px-8">
          <!-- Start main area-->
          <div class="relative h-full" style="min-height: 36rem">
            <div class="absolute inset-0 rounded-lg border-2 border-dashed border-gray-200"></div>
          </div>
          <!-- End main area -->
        </div>
      </div>
    </div>

    <div class="bg-gray-50 pr-4 sm:pr-6 lg:flex-shrink-0 lg:border-l lg:border-gray-200 lg:pr-8 xl:pr-0">
      <div class="h-full py-6 pl-6 lg:w-80">
        <!-- Start right column area -->
        <div class="relative h-full" style="min-height: 16rem">
          <div class="absolute inset-0 rounded-lg border-2 border-dashed border-gray-200"></div>
        </div>
        <!-- End right column area -->
      </div>
    </div>
  </div>
</div>

Upvotes: 4

Views: 13192

Answers (2)

Anton
Anton

Reputation: 8538

You can try using grid instead of flex and change your layout a bit to achieve this.

<script src="https://cdn.tailwindcss.com"></script>

<div class="fixed top-0 left-0 h-full w-1/2 bg-white" aria-hidden="true"></div>
<div class="fixed top-0 right-0 h-full w-1/2 bg-gray-50" aria-hidden="true"></div>
<div class="relative grid grid-cols-[2rem_1fr_2rem] xl:grid-cols-[minmax(2rem,1fr)_16rem_minmax(200px,calc(80rem-32rem))_16rem_minmax(2rem,1fr)] lg:grid-cols-[2rem_minmax(200px,calc(100%-16rem))_16rem_2rem] min-h-screen">
  <!-- Navbar -->
  <nav class="min-h-[4rem] sticky top-0 z-10 col-[1/-1] row-[1] flex justify-center items-center bg-indigo-600 text-white">
    Nav
  </nav>

  <aside class="max-h-screen xl:sticky lg:static top-12 col-[2] row-[2] border-b border-gray-200 bg-white xl:border-b-0 xl:border-r xl:border-gray-200">
    <div class="h-full py-6 pl-4 pr-6 sm:pl-6 lg:pl-8 xl:pl-0">
      <!-- Start left column area -->
      <div class="relative h-full" style="min-height: 12rem">
        <div class="absolute inset-0 rounded-lg border-2 border-dashed border-gray-200 flex justify-center items-center">
          Aside
        </div>
      </div>
      <!-- End left column area -->
    </div>
  </aside>

  <main class="bg-white col-[2] row[3] xl:col-[3] xl:row-[2] min-h-[150vh]">
    <div class="h-full py-6 px-4 sm:px-6 lg:px-8">
      <!-- Start main area-->
      <div class="relative h-full" style="min-height: 36rem">
        <div class="absolute inset-0 rounded-lg border-2 border-dashed border-gray-200 flex justify-center items-center">
          Main
        </div>
      </div>
      <!-- End main area -->
    </div>
  </main>

  <aside class="max-h-screen sticky top-12 col-[2] row-[4] xl:col-[4] xl:row-[2] lg:col-[3] lg:row-[2/2_span] bg-gray-50 pr-4 sm:pr-6 lg:border-l lg:border-gray-200 lg:pr-8 xl:pr-0">
    <div class="h-full py-6 pl-6">
      <!-- Start right column area -->
      <div class="relative h-full" style="min-height: 16rem">
        <div class="absolute inset-0 rounded-lg border-2 border-dashed border-gray-200 flex justify-center items-center">
          Aside
        </div>
      </div>
      <!-- End right column area -->
    </div>
  </aside>
</div>

Upvotes: 3

L. Letovanec
L. Letovanec

Reputation: 615

You need to use top-X class together with sticky. For navbar sticky top-0 and for sidebar something like sticky top-20 should work.

Prefix it with corresponding breakpoint prefix to apply it only for bigger screens.

Upvotes: 7

Related Questions