Dropdown Component

Dropdown Component: The Dropdown component creates toggleable dropdown menus that can be used for navigation, select boxes, context menus, and more. It supports various positions, animations, and can contain any type of content including forms, lists, and media.

Live Examples

1. Basic Dropdowns

Example Preview

Dropdown Title

This dropdown appears on click and can contain any content.

2. Navigation Dropdowns

Example Preview

3. Form Select Dropdowns

Example Preview

4. Advanced Dropdown Features

Example Preview

Interactive Content

This dropdown contains interactive elements that remain functional.



Controlled by JavaScript

5. Multi-level Dropdowns

Example Preview

Dropdown Classes & Attributes Reference

Core Attributes

AttributeDescriptionValuesUsage
uk-dropdownInitializes dropdown componentOptions object or emptyuk-dropdown="pos: bottom-left"
uk-navbarInitializes navbar component-uk-navbar
posDropdown position relative to triggerbottom-left, bottom-center, bottom-right, top-left, top-center, top-right, left-center, right-centeruk-dropdown="pos: bottom-center"
modeTrigger modehover, clickuk-dropdown="mode: click"
delay-showDelay before showing (ms)Numberdelay-show: 500
delay-hideDelay before hiding (ms)Numberdelay-hide: 200
offsetOffset from trigger (px)Numberoffset: 10
animationAnimation typeuk-animation-fade, uk-animation-scale-up, etc.animation: uk-animation-scale-up
durationAnimation duration (ms)Numberduration: 300
boundaryBoundary element selectorCSS selectorboundary: .container
boundary-alignAlign dropdown within boundarytrue, falseboundary-align: true
stretchStretch dropdown to match widthx, ystretch: x

Dropdown Classes

ClassDescriptionUsage
.uk-dropdownBase dropdown container<div class="uk-dropdown">
.uk-navbar-dropdownNavbar dropdown container<div class="uk-navbar-dropdown">
.uk-dropdown-navDropdown navigation list<ul class="uk-nav uk-dropdown-nav">
.uk-navbar-dropdown-navNavbar dropdown navigation list<ul class="uk-nav uk-navbar-dropdown-nav">
.uk-navbar-dropdown-width-22-column navbar dropdownuk-navbar-dropdown uk-navbar-dropdown-width-2
.uk-navbar-dropdown-width-33-column navbar dropdownuk-navbar-dropdown uk-navbar-dropdown-width-3
.uk-navbar-dropdown-width-44-column navbar dropdownuk-navbar-dropdown uk-navbar-dropdown-width-4
.uk-navbar-dropdown-gridGrid layout for navbar dropdown<div class="uk-navbar-dropdown-grid">
.uk-dropdown-scrollableScrollable dropdown content<div class="uk-dropdown-scrollable">
.uk-dropdown-rightRight-aligned sub-dropdown<div class="uk-dropdown uk-dropdown-right">

Navbar Classes

ClassDescriptionUsage
.uk-navbar-containerNavbar container<nav class="uk-navbar-container">
.uk-navbarBase navbar classuk-navbar-container uk-navbar
.uk-navbar-navNavbar navigation list<ul class="uk-navbar-nav">
.uk-navbar-leftLeft-aligned navbar section<div class="uk-navbar-left">
.uk-navbar-rightRight-aligned navbar section<div class="uk-navbar-right">
.uk-navbar-centerCenter-aligned navbar section<div class="uk-navbar-center">
.uk-navbar-itemNavbar item<a class="uk-navbar-item">
.uk-navbar-toggleNavbar toggle button<a class="uk-navbar-toggle">

JavaScript API & Interactive Features

Dropdown JavaScript Methods & Events

// Dropdown component initialization
const dropdown = UIkit.dropdown(element, {
  pos: 'bottom-left',           // Position
  mode: 'hover',               // Trigger mode
  delayShow: 0,                // Delay before showing
  delayHide: 800,              // Delay before hiding
  animation: 'uk-animation-fade', // Animation
  duration: 200,               // Animation duration
  offset: 0,                   // Offset from trigger
  toggle: true,                // Toggle on click
  boundary: window,            // Boundary element
  boundaryAlign: false,        // Align within boundary
  flip: true,                  // Flip if out of viewport
  clsDrop: 'uk-drop',          // Drop class
  clsDropShow: 'uk-open'       // Show class
});

// Navbar initialization
const navbar = UIkit.navbar(element, {
  align: 'left',               // Alignment
  mode: 'click',               // Trigger mode
  delayShow: 0,                // Delay before showing
  delayHide: 800,              // Delay before hiding
  boundary: window,            // Boundary element
  offset: 0,                   // Offset
  dropbar: false,              // Enable dropbar
  dropbarMode: 'slide'         // Dropbar animation
});

// Dropdown methods
dropdown.show();                // Show the dropdown
dropdown.hide();                // Hide the dropdown
dropdown.toggle();              // Toggle show/hide

// Dropdown events
dropdownElement.addEventListener('show', function(event) {
  console.log('Dropdown showing:', event.detail);
});

dropdownElement.addEventListener('shown', function(event) {
  console.log('Dropdown shown:', event.detail);
});

dropdownElement.addEventListener('hide', function(event) {
  console.log('Dropdown hiding:', event.detail);
});

dropdownElement.addEventListener('hidden', function(event) {
  console.log('Dropdown hidden:', event.detail);
});

// Dynamic dropdown management
const dropdownManager = {
  dropdowns: [],
  
  initDropdown: function(dropdownId, options = {}) {
    const dropdownElement = document.getElementById(dropdownId);
    if (!dropdownElement) return null;
    
    const dropdown = UIkit.dropdown(dropdownElement, options);
    this.dropdowns.push({ id: dropdownId, element: dropdownElement, instance: dropdown });
    
    return dropdown;
  },
  
  showDropdown: function(dropdownId) {
    const dropdown = this.dropdowns.find(d => d.id === dropdownId);
    if (dropdown) {
      dropdown.instance.show();
    }
  },
  
  hideDropdown: function(dropdownId) {
    const dropdown = this.dropdowns.find(d => d.id === dropdownId);
    if (dropdown) {
      dropdown.instance.hide();
    }
  },
  
  toggleDropdown: function(dropdownId) {
    const dropdown = this.dropdowns.find(d => d.id === dropdownId);
    if (dropdown) {
      dropdown.instance.toggle();
    }
  },
  
  updateDropdownContent: function(dropdownId, content) {
    const dropdown = this.dropdowns.find(d => d.id === dropdownId);
    if (dropdown) {
      dropdown.element.innerHTML = content;
    }
  },
  
  destroyDropdown: function(dropdownId) {
    const index = this.dropdowns.findIndex(d => d.id === dropdownId);
    if (index > -1) {
      const dropdown = this.dropdowns[index];
      dropdown.instance.$destroy();
      this.dropdowns.splice(index, 1);
    }
  }
};

// Initialize dropdowns
dropdownManager.initDropdown('userMenu', { 
  pos: 'bottom-justify', 
  mode: 'click' 
});

dropdownManager.initDropdown('notifications', {
  pos: 'bottom-right',
  mode: 'click',
  animation: 'uk-animation-slide-top-small'
});

// Example: Show dropdown on button click
document.getElementById('showMenuBtn').addEventListener('click', function() {
  dropdownManager.showDropdown('userMenu');
});

// Example: Update dropdown content dynamically
document.getElementById('updateContentBtn').addEventListener('click', function() {
  const newContent = `
    <div class="uk-card uk-card-body uk-card-default">
      <h3>Updated Content</h3>
      <p>This content was updated dynamically.</p>
    </div>
  `;
  dropdownManager.updateDropdownContent('userMenu', newContent);
});

// Navbar management
const navbarManager = {
  navbars: [],
  
  initNavbar: function(navbarId, options = {}) {
    const navbarElement = document.getElementById(navbarId);
    if (!navbarElement) return null;
    
    const navbar = UIkit.navbar(navbarElement, options);
    this.navbars.push({ id: navbarId, element: navbarElement, instance: navbar });
    
    return navbar;
  },
  
  toggleNavbar: function(navbarId) {
    const navbar = this.navbars.find(n => n.id === navbarId);
    if (navbar) {
      // UIKit doesn't have direct toggle method for navbar
      const isActive = navbar.element.classList.contains('uk-open');
      if (isActive) {
        UIkit.drop(navbar.element.querySelector('.uk-navbar-dropdown')).hide();
      } else {
        UIkit.drop(navbar.element.querySelector('.uk-navbar-dropdown')).show();
      }
    }
  }
};

// Initialize navbar
navbarManager.initNavbar('mainNavbar', {
  align: 'center',
  mode: 'hover'
});

// Dropdown positioning helper
const dropdownPositioning = {
  calculatePosition: function(triggerElement, dropdownElement, position = 'bottom-left') {
    const triggerRect = triggerElement.getBoundingClientRect();
    const dropdownRect = dropdownElement.getBoundingClientRect();
    const viewportWidth = window.innerWidth;
    const viewportHeight = window.innerHeight;
    
    let top, left;
    
    switch(position) {
      case 'bottom-left':
        top = triggerRect.bottom;
        left = triggerRect.left;
        break;
      case 'bottom-center':
        top = triggerRect.bottom;
        left = triggerRect.left + (triggerRect.width - dropdownRect.width) / 2;
        break;
      case 'bottom-right':
        top = triggerRect.bottom;
        left = triggerRect.right - dropdownRect.width;
        break;
      case 'top-left':
        top = triggerRect.top - dropdownRect.height;
        left = triggerRect.left;
        break;
      case 'top-center':
        top = triggerRect.top - dropdownRect.height;
        left = triggerRect.left + (triggerRect.width - dropdownRect.width) / 2;
        break;
      case 'top-right':
        top = triggerRect.top - dropdownRect.height;
        left = triggerRect.right - dropdownRect.width;
        break;
      case 'left-center':
        top = triggerRect.top + (triggerRect.height - dropdownRect.height) / 2;
        left = triggerRect.left - dropdownRect.width;
        break;
      case 'right-center':
        top = triggerRect.top + (triggerRect.height - dropdownRect.height) / 2;
        left = triggerRect.right;
        break;
    }
    
    // Adjust if out of viewport
    if (left < 0) left = 0;
    if (left + dropdownRect.width > viewportWidth) {
      left = viewportWidth - dropdownRect.width;
    }
    if (top < 0) top = 0;
    if (top + dropdownRect.height > viewportHeight) {
      top = viewportHeight - dropdownRect.height;
    }
    
    return { top, left };
  },
  
  repositionDropdown: function(dropdownId) {
    const dropdown = dropdownManager.dropdowns.find(d => d.id === dropdownId);
    if (!dropdown) return;
    
    const trigger = document.querySelector(`[aria-controls="${dropdownId}"]`);
    if (!trigger) return;
    
    const position = dropdown.instance.pos || 'bottom-left';
    const coords = this.calculatePosition(trigger, dropdown.element, position);
    
    dropdown.element.style.position = 'fixed';
    dropdown.element.style.top = `${coords.top}px`;
    dropdown.element.style.left = ``${coords.left}px`;
    dropdown.element.style.zIndex = '1040';
  }
};

// Reposition dropdowns on window resize
window.addEventListener('resize', function() {
  dropdownManager.dropdowns.forEach(dropdown => {
    if (dropdown.instance.isActive()) {
      dropdownPositioning.repositionDropdown(dropdown.id);
    }
  });
});

// Keyboard navigation for dropdowns
const dropdownNavigation = {
  currentIndex: -1,
  currentDropdown: null,
  
  init: function(dropdownId) {
    const dropdown = document.getElementById(dropdownId);
    if (!dropdown) return;
    
    const items = dropdown.querySelectorAll('.uk-dropdown-nav li > a');
    
    dropdown.addEventListener('keydown', (e) => {
      switch(e.key) {
        case 'ArrowDown':
          e.preventDefault();
          this.navigateNext(items);
          break;
        case 'ArrowUp':
          e.preventDefault();
          this.navigatePrevious(items);
          break;
        case 'Enter':
          if (this.currentIndex > -1) {
            items[this.currentIndex].click();
          }
          break;
        case 'Escape':
          UIkit.dropdown(dropdown).hide();
          break;
      }
    });
    
    items.forEach((item, index) => {
      item.addEventListener('focus', () => {
        this.currentIndex = index;
      });
      
      item.addEventListener('mouseenter', () => {
        this.currentIndex = index;
        items.forEach(i => i.classList.remove('uk-active'));
        item.classList.add('uk-active');
      });
    });
  },
  
  navigateNext: function(items) {
    if (items.length === 0) return;
    
    this.currentIndex = (this.currentIndex + 1) % items.length;
    items[this.currentIndex].focus();
    items.forEach(i => i.classList.remove('uk-active'));
    items[this.currentIndex].classList.add('uk-active');
  },
  
  navigatePrevious: function(items) {
    if (items.length === 0) return;
    
    this.currentIndex = (this.currentIndex - 1 + items.length) % items.length;
    items[this.currentIndex].focus();
    items.forEach(i => i.classList.remove('uk-active'));
    items[this.currentIndex].classList.add('uk-active');
  }
};

// Initialize dropdown navigation
document.addEventListener('DOMContentLoaded', function() {
  dropdownNavigation.init('userDropdown');
  dropdownNavigation.init('settingsDropdown');
});

// Dropdown with AJAX content loading
const ajaxDropdown = {
  loadContent: function(dropdownId, url) {
    const dropdown = dropdownManager.dropdowns.find(d => d.id === dropdownId);
    if (!dropdown) return;
    
    // Show loading state
    dropdown.element.innerHTML = `
      <div class="uk-card uk-card-body uk-card-default">
        <div class="uk-text-center">
          <div uk-spinner></div>
          <p class="uk-margin-small-top">Loading...</p>
        </div>
      </div>
    `;
    
    // Fetch content
    fetch(url)
      .then(response => response.text())
      .then(html => {
        dropdown.element.innerHTML = html;
        UIkit.update(dropdown.element);
      })
      .catch(error => {
        dropdown.element.innerHTML = `
          <div class="uk-card uk-card-body uk-card-default">
            <div class="uk-alert-danger" uk-alert>
              <p>Failed to load content. Please try again.</p>
            </div>
          </div>
        `;
      });
  }
};

// Example usage
document.getElementById('loadUserDataBtn').addEventListener('click', function() {
  ajaxDropdown.loadContent('userMenu', '/api/user-data');
});

// Dropdown with form submission
const dropdownFormHandler = {
  init: function(dropdownId, formSelector) {
    const dropdown = dropdownManager.dropdowns.find(d => d.id === dropdownId);
    if (!dropdown) return;
    
    const form = dropdown.element.querySelector(formSelector);
    if (!form) return;
    
    form.addEventListener('submit', function(e) {
      e.preventDefault();
      
      const formData = new FormData(form);
      const submitBtn = form.querySelector('[type="submit"]');
      const originalText = submitBtn.textContent;
      
      // Show loading state
      submitBtn.disabled = true;
      submitBtn.innerHTML = `
        <span uk-spinner="ratio: 0.5"></span>
        Processing...
      `;
      
      // Simulate API call
      setTimeout(() => {
        // Reset form
        form.reset();
        submitBtn.disabled = false;
        submitBtn.textContent = originalText;
        
        // Show success message
        const successMsg = `
          <div class="uk-alert-success" uk-alert>
            <a class="uk-alert-close" uk-close></a>
            <p>Form submitted successfully!</p>
          </div>
        `;
        dropdown.element.insertAdjacentHTML('afterbegin', successMsg);
        
        // Hide dropdown after delay
        setTimeout(() => {
          dropdown.instance.hide();
        }, 2000);
      }, 1500);
    });
  }
};

// Initialize form handler
dropdownFormHandler.init('contactFormDropdown', '#contactForm');
Best Practices for Dropdown Components:
  • Always provide keyboard navigation for dropdowns (Arrow keys, Enter, Escape)
  • Ensure proper focus management when dropdown opens/closes
  • Use semantic HTML structure with appropriate ARIA attributes (aria-expanded, aria-haspopup)
  • Implement proper screen reader support
  • Add sufficient contrast between dropdown background and text
  • Use appropriate positioning based on available screen space
  • Implement boundary checking to prevent dropdowns from appearing off-screen
  • Add smooth animations for better user experience
  • Use appropriate trigger modes (hover vs click) based on context and device
  • Provide clear visual feedback when dropdowns are interactive
  • Implement touch-friendly sizes for mobile devices
  • Use lazy loading for content-heavy dropdowns
  • Add proper error states for failed content loading
  • Implement proper z-index stacking context
  • Test with various input methods (mouse, keyboard, touch)
  • Consider implementing prefers-reduced-motion for animations
  • Add close buttons for modal-like dropdowns on mobile
  • Ensure dropdowns are accessible via keyboard tab navigation
  • Use descriptive labels for screen reader users
  • Implement proper focus trapping within dropdowns when needed