Navigation✨ Premium

Dropdown Reveal

Pure CSS dropdown: opacity, visibility, and translateY(-10px) all animate on container hover — chevron included, zero JavaScript.

CSSDropdown

You'll get access to the interactive demo with a free account.

This effect is part of Effect.Labs — 811 vanilla effects, some free, some premium. Navigation has 36 effects, including 4 free. Explore the category →

3 usage examples

Desktop navigation — Product category sub-menu — Dropdown Reveal example 1

① Desktop navigation — Product category sub-menu

WhenMain navigation bar of a multi-section site: a menu item exposes its subcategories on hover.
WhyThe subtle fade + slide reinforces visual hierarchy without drawing attention away from the page; the chevron signals open/closed state.
Settingstransition: .2s (nav responsiveness), --bg-card: #1a1a2e, --radius-lg: 0.5rem (squarer corners), 4–6 items.
Dashboard — Sort and filter selector — Dropdown Reveal example 2

② Dashboard — Sort and filter selector

WhenData list with a floating sort selector (name, date, activity) at the top right of the table.
WhyThe subtle animation does not disturb data reading; translateY gives clear visual feedback without adding layout space.
Settingsmin-width: 220px (longer labels), --border: rgba(255,255,255,0.14), transition: .15s (maximum responsiveness).
App header — User account menu — Dropdown Reveal example 3

③ App header — User account menu

WhenAvatar or username at the top right of an interface, exposing quick actions: profile, settings, sign out.
WhyThe slide from the trigger introduces the menu without flash; CSS vars make it easy to align icons and labels cleanly.
Settingstop: calc(100% + 12px), --radius-lg: 1rem (modern style), right: 0 to align the panel to the right, 4–5 items.

How it works

Hovering .dropdown-container transitions three CSS properties simultaneously on .dropdown-menu via transition: .3s: opacity (0 → 1), visibility (hidden → visible), and transform: translateY(-10px → 0). The selector .dropdown-container:hover .dropdown-menu drives the whole interaction from the parent element — no JavaScript involved.

The opacity + visibility pair is intentional: display:none cancels CSS transitions entirely. opacity:0 alone hides the element visually but keeps click areas active. visibility:hidden removes the element from interactions and accepts a transition — it waits until opacity reaches 0 before hiding, preserving the close animation.

The SVG chevron inside .dropdown-trigger has its own transition rule (transition: transform .3s). The rule .dropdown-container:hover .dropdown-trigger svg { transform: rotate(180deg) } rotates it at the same moment the panel opens — one parent hover synchronizes both animations.

Eight CSS variables on :root centralize the theme: --bg-card (trigger and menu background), --border (outline), --space-2/3/4 (padding scale), and --radius-sm/md/lg (border-radius scale). Changing a variable propagates across the whole component.

Accessibility

  • prefers-reduced-motion absent — the code includes no @media (prefers-reduced-motion: reduce) query. Transitions fire regardless of the OS preference. Minimal fix: @media (prefers-reduced-motion: reduce) { .dropdown-menu, .dropdown-trigger svg { transition: none; } }.
  • <div> trigger is not focusable — the trigger is a <div>, not a <button>; without additional JS it is not reachable by keyboard (Tab, Enter, Space).
  • No ARIA attributes — the code contains no aria-expanded, aria-haspopup, role="menu", or role="menuitem".
  • Hover-only — the menu opens on CSS :hover only; it does not open via keyboard or touch without a click handler added in JS.
  • Text contrast — white #ffffff on --bg-card: #12121a, ratio ≈ 19.3:1, WCAG AAA compliant.

Browser compatibility

Uses only opacity, visibility, transform, and transition — universal CSS properties since IE 10. Zero JavaScript, zero dependencies.

Chrome 50+✓ Full
Firefox 55+✓ Full
Safari 10+✓ Full
Edge 15+✓ Full
Mobile iOS✓ CSS OK, hover needs JS
Android Chrome✓ CSS OK, hover needs JS

If CSS transitions are not supported, the menu appears and hides instantly on hover — functional behavior without animation.

The code

HTML structure to paste into your page (CSS + JS available with a premium account):

index.html — structure
<div class="dropdown-container">
  <div class="dropdown-trigger">
    Label
    <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
      <path d="M6 9l6 6 6-6"></path>
    </svg>
  </div>
  <div class="dropdown-menu">
    <div class="dropdown-item">Item 1</div>
    <div class="dropdown-item">Item 2</div>
    <div class="dropdown-item">Item 3</div>
  </div>
</div>
🔒 Unlock the full code — from €2.99 the first month

Full HTML + CSS + JS, copy-paste ready — with hundreds of premium effects.

Customize

Options passed to the API or data-* attributes:

Option / propertyDefaultEffect
--bg-card #12121a Background of the trigger and dropdown menu. Set to #ffffff for a light theme.
--border rgba(255,255,255,0.08) Border color of trigger and menu. Increase opacity for a more visible outline.
--radius-lg 0.75rem Border-radius of the dropdown panel (.dropdown-menu).
--radius-md 0.5rem Border-radius of the trigger (.dropdown-trigger).
transition (.dropdown-menu) .3s Animation duration for all three properties (opacity, visibility, transform). .15s = snappy, .5s = silky.
translateY (.dropdown-menu closed) -10px Vertical offset at start. -20px = pronounced slide, 0 = pure fade with no movement.
hover color (.dropdown-item) rgba(99,102,241,.1) Item hover background. Replace with your accent color.
min-width (.dropdown-menu) 180px Minimum panel width. Increase for longer labels.
top (.dropdown-menu) calc(100% + 8px) Vertical gap between the trigger and the dropdown panel.

FAQ

Yes — opening, closing, and chevron rotation rely entirely on CSS :hover. There is no JS in the code. Copy the HTML and CSS into any project — framework included.
Replace <div class="dropdown-trigger"> with a <button>, handle keydown in JS (Enter/Space to open, Escape to close), and add aria-expanded on the button plus role="menu" and role="menuitem" on the items. The effect CSS does not need to change — drive a .open class alongside the :hover rule.
CSS :hover is unreliable on touch. Add a click listener on .dropdown-trigger that toggles a .open class on .dropdown-container, then in CSS: .dropdown-container.open .dropdown-menu { opacity:1; visibility:visible; transform:translateY(0); }. The existing transition: .3s applies without modification.