Tailwind CSS Academy · Lektion

Dropdown-menu-komponent

Opret en positioneret dropdown-menu, der vises under en udløserknap, med absolute-positionering, skygge og afrundede hjørner.

Lektion 3 af 413 trin

Dropdown-menu-komponent er en gratis Tailwind CSS Academy-lektion på CoddyKit. Dette er lektion 3 af 4. Du kan læse hele lektionen gratis nedenfor — og derefter øve dig praktisk i browseren med en indbygget kodeeditor og en AI-vejleder, der er tilgængelig døgnet rundt. Den er en del af læringsforløbet i Tailwind CSS Academy, og dine fremskridt synkroniseres på tværs af nettet og CoddyKit-appen. Tailwind CSS Academy-kurset indeholder 4 lektioner i alt.

Hvad er en rullemenu

En rullemenu er et panel med valgmuligheder, der vises under (eller ved siden af) et udløsende element, når det aktiveres. I modsætning til et indbygget <select> kan en tilpasset rullemenu indeholde ikoner, beskrivelser, mærkater, skillelinjer og andet HTML-indhold.

Den største udfordring ved rullemenuer er placeringen: Panelet skal vises direkte under udløseren og forblive inden for visningsområdet. Tailwinds placeringsværktøjer kombineret med en smule JavaScript gør dette muligt uden et eksternt bibliotek.

Struktur for udløserknappen

Rullemenuens udløser er normalt en knap, der viser den aktuelt valgte mulighed eller en handlingsetiket. Pak udløseren og rullemenuens panel sammen i en relative-container, så panelet placerer sig i forhold til udløseren.

Udløserknappen bruger inline-flex items-center gap-2 til at justere en etiket og et chevronikon. Chevronikonet kan rotere med rotate-180, når rullemenuen er åben, for at angive tilstanden.

<div class="relative inline-block">
  <button
    id="dd-trigger"
    onclick="toggleDropdown()"
    class="inline-flex items-center gap-2 px-4 py-2 text-sm font-medium
           text-gray-700 bg-white border border-gray-300 rounded-lg
           hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-blue-500">
    Options
    <svg id="dd-chevron" class="w-4 h-4 transition-transform duration-200"
         fill="none" viewBox="0 0 24 24" stroke="currentColor">
      <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/>
    </svg>
  </button>
</div>

Placering af rullemenuens panel

Rullemenuens panel bruger absolute top-full left-0 mt-1 til at placere sig direkte under udløserknappen. top-full placerer panelets top ved den relative forælders nederste kant, og mt-1 tilføjer et lille mellemrum på 4 px mellem udløseren og panelet.

Tilføj min-w-48 w-56 for at give panelet en passende minimumsbredde uanset udløserens størrelse. Hvis rullemenuen kan blive skåret af ved højre kant, skal du bruge right-0 i stedet for left-0 for at justere den efter udløserens højre kant.

<div
  id="dropdown"
  class="absolute top-full left-0 mt-1 z-50
         w-56 bg-white border border-gray-200 rounded-xl shadow-lg
         hidden">
  <!-- menu items -->
</div>

Elementer i rullemenuen

Hvert menuelement er et anker eller en knap i fuld bredde med flex items-center gap-3 w-full px-4 py-2 text-sm text-gray-700 hover:bg-gray-100, så det får et behageligt område ved markøroverførsel. Det første element bruger rounded-t-xl, og det sidste bruger rounded-b-xl for at begrænse markørfremhævninger til panelets afrundede hjørner.

Alternativt kan du tilføje rounded-xl til hvert element separat med en indvendig margen på 4 px fra panelets indre udfyldning for at skabe en svævende fremhævningseffekt.

<div class="py-1">
  <a href="/profile"
     class="flex items-center gap-3 px-4 py-2 text-sm text-gray-700 hover:bg-gray-100">
    <svg class="w-4 h-4 text-gray-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
      <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z"/>
    </svg>
    View Profile
  </a>
  <a href="/settings"
     class="flex items-center gap-3 px-4 py-2 text-sm text-gray-700 hover:bg-gray-100">
    <svg class="w-4 h-4 text-gray-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
      <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z"/>
      <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"/>
    </svg>
    Settings
  </a>
</div>

Skillelinjer og sektionsgrupper

Skillelinjer adskiller grupper af relaterede elementer i en rullemenu. Brug et <hr class='border-t border-gray-100 my-1'>-element mellem grupperne. Alternativt kan du tilføje en lille sektionsoverskrift over hver gruppe ved hjælp af px-4 py-1 text-xs font-semibold uppercase tracking-wider text-gray-400.

Gruppér farlige handlinger (som log af eller sletning) nederst under en skillelinje, og farv dem røde, så det straks er tydeligt, at de er destruktive.

<div class="py-1">
  <!-- Main section -->
  <a href="/profile" class="flex items-center gap-3 px-4 py-2 text-sm text-gray-700 hover:bg-gray-100">View Profile</a>
  <a href="/settings" class="flex items-center gap-3 px-4 py-2 text-sm text-gray-700 hover:bg-gray-100">Settings</a>
  <!-- Divider -->
  <hr class="border-t border-gray-100 my-1" />
  <!-- Danger section -->
  <button class="flex items-center gap-3 w-full px-4 py-2 text-sm text-red-600 hover:bg-red-50">
    <svg class="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
      <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 16l4-4m0 0l-4-4m4 4H7m6 4v1a3 3 0 01-3 3H6a3 3 0 01-3-3V7a3 3 0 013-3h4a3 3 0 013 3v1"/>
    </svg>
    Sign Out
  </button>
</div>

Skiftelogik og lukning ved klik udenfor

Rullemenuens skiftelogik viser og skjuler panelet. Endnu vigtigere er det, at den skal lukkes, når brugeren klikker uden for rullemenuen. Tilføj en klikhåndtering til dokumentet, som kontrollerer, om klikmålet ikke befinder sig i rullemenuens container.

Brug contains() til at kontrollere, om klikket fandt sted i rullemenuens omsluttende element. Hvis ikke, skal du skjule rullemenuen og rotere chevronikonet tilbage.

<script>
  const wrapper = document.getElementById('dd-wrapper');
  const panel = document.getElementById('dropdown');
  const chevron = document.getElementById('dd-chevron');

  function toggleDropdown() {
    panel.classList.toggle('hidden');
    chevron.classList.toggle('rotate-180');
  }

  // Close when clicking outside
  document.addEventListener('click', (e) => {
    if (!wrapper.contains(e.target)) {
      panel.classList.add('hidden');
      chevron.classList.remove('rotate-180');
    }
  });

  // Close on Escape key
  document.addEventListener('keydown', (e) => {
    if (e.key === 'Escape') {
      panel.classList.add('hidden');
      chevron.classList.remove('rotate-180');
    }
  });
</script>

Rullemenu med indtoningsanimation

Tilføj en indgangsanimation med indtoning og skalering til rullemenuens panel ved at bruge samme teknik som til modalvinduet: overgang fra scale-95 opacity-0 til scale-100 opacity-100 med transition-all duration-150 origin-top.

Værktøjet origin-top angiver transformationsoriginet til panelets top, så det skaleres ud fra udløseren og får animationen til at føles forbundet med den knap, der åbnede det.

<div
  id="dropdown"
  class="absolute top-full left-0 mt-1 z-50
         w-56 bg-white border border-gray-200 rounded-xl shadow-lg
         transition-all duration-150 origin-top
         scale-95 opacity-0 pointer-events-none">
  <!-- items -->
</div>

<script>
  function openDropdown() {
    const d = document.getElementById('dropdown');
    d.classList.remove('scale-95', 'opacity-0', 'pointer-events-none');
    d.classList.add('scale-100', 'opacity-100', 'pointer-events-auto');
  }
  function closeDropdown() {
    const d = document.getElementById('dropdown');
    d.classList.remove('scale-100', 'opacity-100', 'pointer-events-auto');
    d.classList.add('scale-95', 'opacity-0', 'pointer-events-none');
  }
</script>

Højrejusteret rullemenu

Når en rullemenuudløser er tæt på skærmens højre kant (f.eks. en brugeravatar øverst til højre i en navigationslinje), skal panelet justeres efter udløserens højre kant for at undgå, at det flyder ud over skærmen. Brug right-0 i stedet for left-0 på panelet.

Dette er en vigtig detalje, som begyndere ofte overser — en venstrejusteret rullemenu ved en udløser i højre side vil være delvist eller helt uden for skærmen på mobilenheder.

<div class="relative inline-block">
  <!-- Right-side trigger (e.g., user avatar) -->
  <button onclick="toggleDropdown()" class="w-8 h-8 rounded-full bg-blue-600 text-white text-sm font-bold">JD</button>
  <!-- Panel aligned to right edge of trigger -->
  <div
    id="dropdown"
    class="hidden absolute top-full right-0 mt-1 z-50
           w-56 bg-white border border-gray-200 rounded-xl shadow-lg py-1">
    <div class="px-4 py-2 border-b border-gray-100">
      <p class="text-sm font-semibold text-gray-900">Jane Doe</p>
      <p class="text-xs text-gray-500">jane@example.com</p>
    </div>
    <a href="/profile" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100">Profile</a>
    <a href="/settings" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100">Settings</a>
    <hr class="border-t border-gray-100 my-1" />
    <button class="block w-full text-left px-4 py-2 text-sm text-red-600 hover:bg-red-50">Sign Out</button>
  </div>
</div>

Rullemenu med afkrydsninger for aktive elementer

En valgrullemenu viser et afkrydsningsmærke ud for den aktuelt valgte mulighed. Brug flex items-center justify-between på hvert element for at placere afkrydsningsmærket til højre, eller flex items-center gap-3 for at placere det til venstre før etiketten.

Farv det aktive element med text-blue-600 font-semibold, og vis et farvet afkrydsningsikon. Inaktive elementer bruger standarden text-gray-700.

<div class="py-1">
  <!-- Active item -->
  <button class="flex items-center justify-between w-full px-4 py-2 text-sm font-semibold text-blue-600 hover:bg-blue-50">
    English
    <svg class="w-4 h-4" fill="currentColor" viewBox="0 0 20 20">
      <path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd"/>
    </svg>
  </button>
  <!-- Inactive items -->
  <button class="block w-full text-left px-4 py-2 text-sm text-gray-700 hover:bg-gray-100">French</button>
  <button class="block w-full text-left px-4 py-2 text-sm text-gray-700 hover:bg-gray-100">German</button>
  <button class="block w-full text-left px-4 py-2 text-sm text-gray-700 hover:bg-gray-100">Japanese</button>
</div>

Kontekstmenu som rullemenu

En kontekstmenu vises ved højreklik eller på placeringen af en knap med tre prikker for at tilbyde kontekstafhængige handlinger for et bestemt element (f.eks. en fil, række eller et kort). Placér den ved de koordinater, hvor der blev klikket, ved hjælp af absolute-placering og JavaScript.

Ved mønsteret med tre prikker (den mest almindelige tilgang) skal du placere en relative-container på elementet og en knap med tre prikker ved top-2 right-2. Rullemenuens panel vises under eller ved siden af knappen.

<div class="relative">
  <!-- Item row -->
  <div class="flex items-center justify-between p-4 bg-white rounded-lg border border-gray-200">
    <span class="text-sm font-medium text-gray-900">Project Alpha.zip</span>
    <!-- Three-dot button -->
    <div class="relative">
      <button onclick="toggleCtx()" class="p-1 text-gray-400 hover:text-gray-600 hover:bg-gray-100 rounded-md">
        <svg class="w-4 h-4" fill="currentColor" viewBox="0 0 20 20">
          <path d="M10 6a2 2 0 110-4 2 2 0 010 4zM10 12a2 2 0 110-4 2 2 0 010 4zM10 18a2 2 0 110-4 2 2 0 010 4z"/>
        </svg>
      </button>
      <div id="ctx-menu" class="hidden absolute top-full right-0 mt-1 z-50 w-40 bg-white border border-gray-200 rounded-xl shadow-lg py-1">
        <button class="block w-full text-left px-4 py-2 text-sm text-gray-700 hover:bg-gray-100">Rename</button>
        <button class="block w-full text-left px-4 py-2 text-sm text-gray-700 hover:bg-gray-100">Download</button>
        <hr class="border-t border-gray-100 my-1" />
        <button class="block w-full text-left px-4 py-2 text-sm text-red-600 hover:bg-red-50">Delete</button>
      </div>
    </div>
  </div>
</div>

Indlejret rullemenu (undermenu)

En indlejret undermenu vises til højre for et overordnet menupunkt, når du holder markøren over det eller klikker på det. Brug group relative på det overordnede menupunkt og group-hover:block absolute left-full top-0 på undermenuens panel for at placere det ved siden af det overordnede menupunkt.

Tilføj et højrepegende chevronikon på det overordnede menupunkt for at vise, at det har en undermenu. Begræns indlejrede menuer til ét niveau — menuer i to niveauer er allerede komplekse, og tre niveauer er sjældent berettigede.

<div class="py-1 relative">
  <a href="/" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100">Profile</a>
  <!-- Parent with submenu -->
  <div class="group relative">
    <button class="flex items-center justify-between w-full px-4 py-2 text-sm text-gray-700 hover:bg-gray-100">
      Export
      <svg class="w-4 h-4 text-gray-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
        <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"/>
      </svg>
    </button>
    <!-- Submenu -->
    <div class="hidden group-hover:block absolute left-full top-0 ml-1 w-40 bg-white border border-gray-200 rounded-xl shadow-lg py-1 z-50">
      <button class="block w-full text-left px-4 py-2 text-sm text-gray-700 hover:bg-gray-100">As PDF</button>
      <button class="block w-full text-left px-4 py-2 text-sm text-gray-700 hover:bg-gray-100">As CSV</button>
      <button class="block w-full text-left px-4 py-2 text-sm text-gray-700 hover:bg-gray-100">As Excel</button>
    </div>
  </div>
</div>

Hurtigt tjek

Test din forståelse af begreberne i Tailwind CSS Mastery fra denne lektion.

Opsummering af lektionen

I denne lektion har du lært, at placering af rullemenuer bruger relative på omslaget og absolute top-full left-0 mt-1 på panelet; justering mod højre bruger right-0 i stedet for left-0 for at forhindre overløb ved udløsere i højre side; og lukning ved klik udenfor kræver en kliklytter på dokumentet, som kontrollerer contains() for at registrere klik uden for omslagselementet. Næste trin er at gøre modaler og rullemenuer fuldt tilgængelige.

Gratis at komme i gang

Lær HTML med en AI-underviser — gratis

Skriv og kør rigtig kode i din browser, få øjeblikkelig hjælp fra en AI-underviser døgnet rundt, og fortsæt, hvor du slap, på web eller i appen.

Kurser
30
Lektioner
120

Ofte stillede spørgsmål

Er lektionen “Dropdown-menu-komponent” gratis?

Ja — hele teksten til “Dropdown-menu-komponent” kan læses gratis her på nettet. Hvis du vil øve dig interaktivt med en indbygget kodeeditor og en AI-vejleder døgnet rundt og få adgang til resten af Tailwind CSS Academy-kurset, skal du opgradere til CoddyKit PRO. Tailwind CSS Academy-kurset indeholder 4 lektioner i alt.

Hvad lærer jeg i “Dropdown-menu-komponent”?

Opret en positioneret dropdown-menu, der vises under en udløserknap, med absolute-positionering, skygge og afrundede hjørner. Du øver dig i Tailwind CSS Academy med praktisk kode, som du kører direkte i browseren, og en AI-vejleder døgnet rundt besvarer dine spørgsmål, mens du arbejder dig gennem lektionen.

Skal jeg have erfaring for at begynde på Tailwind CSS Academy?

Der kræves ingen tidligere erfaring. Tailwind CSS Academy på CoddyKit er tilrettelagt for både begyndere og øvede, så du kan starte her eller fra begyndelsen og lære i dit eget tempo. Dette er lektion 3 af 4.

Hvor lang tid tager lektionen “Dropdown-menu-komponent”?

De fleste CoddyKit-lektioner tager cirka 5–10 minutter. Hver lektion er kort og interaktiv, så du gør løbende fremskridt og kan fortsætte, hvor du slap – på både web og app.

Kan jeg skrive og køre kode i denne Tailwind CSS Academy-lektion?

Ja. Alle Tailwind CSS Academy-lektioner har en indbygget kodeeditor, så du kan skrive og køre rigtig kode direkte i din browser og få øjeblikkelig feedback fra AI – uden lokal opsætning.

Alle lektioner i dette kursus

  1. Struktur for modaldialoger
  2. Animation af åbning og lukning af modal
  3. Dropdown-menu-komponent
  4. Tilgængelige modaler og dropdowns
← Tilbage til Tailwind CSS Academy