Button Group

Button groups are powerful UI components that combine multiple related buttons into a single, cohesive unit. They're perfect for creating toolbars, navigation sets, or any interface where multiple actions need to be visually connected. Button groups improve user experience by organizing related actions, reducing visual clutter, and providing clear interaction patterns for common tasks.

Basic Examples

Create a basic button group using the .btn-group class to wrap a series of buttons. Each button maintains its individual styling while appearing as part of a unified set. Add the role="group" attribute and an appropriate aria-label to enhance accessibility. Remixicon icons enhance visual appeal and improve button recognition.

Standard Button Group
Loading...

Use the .active class to highlight the currently selected button, and enhance accessibility with aria-current="page". This visual feedback helps users understand their current context within the interface and indicates which option is currently selected or active.

Active State Button Group
Loading...

Mixed Styles

In a button group, buttons can be styled with different contextual color classes to represent distinct actions or statuses. This approach helps users quickly identify the purpose and importance of each button based on color semantics. For example, red typically indicates destructive actions, yellow for caution, and green for confirmation.

Mixed Style Button Group
Loading...

Outlined Styles

Button groups with outlined buttons use the .btn-outline-* classes to create a more subtle appearance with transparent backgrounds and colored borders. Outlined button groups are ideal for secondary actions, less prominent toolbars, or interfaces where you want to reduce visual weight while maintaining functionality.

Outlined Button Group
Loading...

Checkbox and Radio Buttons

Transform checkboxes and radio inputs into toggle buttons within a button group to create intuitive selection interfaces. Use the .btn-check class to hide the default input appearance while maintaining functionality. Checkbox button groups allow multiple selections (like formatting options), while radio button groups enforce single selection (like alignment options).

Checkbox Button Group
Loading...
Radio Button Group
Loading...

Button Toolbar

Combine multiple button groups into a comprehensive toolbar using the .btn-toolbar class. Button toolbars organize related actions into logical groups, similar to application toolbars in desktop software. Add role="toolbar" and aria-label attributes to improve accessibility, and use margin utilities like .me-2 to create proper spacing between button groups.

Button Toolbar Example
Loading...

Button toolbars can be enhanced with input groups to create complex control interfaces. Use .justify-content-between to create space between groups, or combine with other flex utilities to achieve custom layouts. These examples demonstrate browser-like navigation controls and media player interfaces.

Button Toolbar with Input Groups
Loading...

Size Variations

Adjust button group sizes using the .btn-group-xl, .btn-group-lg, .btn-group-sm, and .btn-group-xs classes. Size variations help create visual hierarchy and adapt button groups to different interface contexts. Larger button groups work well for primary actions, while smaller sizes are suitable for compact toolbars or dense interfaces.

Button Group Size Variations
Loading...

Nested Dropdowns

Create more complex button groups by nesting dropdown menus within them. This pattern is useful for interfaces with primary actions displayed as buttons and secondary actions hidden in a dropdown menu. The dropdown toggle button should be wrapped in its own .btn-group to maintain proper styling and behavior.

Button Group with Nested Dropdown
Loading...

Vertical Variations

Create vertical button stacks using the .btn-group-vertical class instead of .btn-group. Vertical button groups are ideal for side navigation, action panels, or interfaces where vertical space is more available than horizontal space. They maintain all the functionality of standard button groups but with a vertical orientation.

Vertical Button Group
Loading...

Vertical button groups can also include dropdowns for more complex navigation structures. Note that for dropdowns at the bottom of a vertical group, use the .dropup class to ensure the menu opens in the correct direction.

Vertical Button Group with Dropdowns
Loading...

Radio buttons can also be arranged vertically, creating intuitive option selectors for settings or preferences that are better displayed in a vertical layout.

Vertical Radio Button Group
Loading...

Interactive Button Groups

Create dynamic button groups that respond to user interactions with state management, real-time updates, and advanced functionality. These examples demonstrate button groups with JavaScript integration for complex user interfaces and interactive applications.

Interactive Button Groups
Loading...

Specialized Use Cases

Industry-specific button group implementations for specialized applications like content editors, media players, design tools, and data management interfaces. These examples show how button groups can be tailored for specific workflows and professional applications.

Specialized Button Groups
Loading...

Advanced Patterns & Layouts

Complex button group patterns that combine multiple concepts, including responsive layouts, conditional visibility, state synchronization, and integration with other UI components. These patterns are useful for sophisticated applications with complex user interaction requirements.

Advanced Button Group Patterns
Loading...

Developer Tips & Best Practices

Pro Tips for Button Groups

  • State Management: Use data attributes or JavaScript to maintain button states across interactions
  • Performance: Implement event delegation for large button groups to reduce memory usage
  • Responsive Design: Consider stacking button groups vertically on mobile devices
  • Loading States: Show loading indicators in buttons during async operations
  • Keyboard Navigation: Implement arrow key navigation for better accessibility
  • Icon Consistency: Maintain consistent icon styles and sizes across all buttons

Common Pitfalls to Avoid

  • Don't use too many buttons in a single group - it becomes overwhelming for users
  • Avoid mixing different button styles within the same group unless there's a clear purpose
  • Don't forget to handle keyboard navigation and focus management properly
  • Never use button groups for navigation that should be handled by proper link elements
  • Don't make button groups too small on touch devices - ensure adequate touch targets
  • Avoid using button groups for single actions - they're meant for related actions

JavaScript Integration Example

Here's a comprehensive button group manager for dynamic applications:

class ButtonGroupManager {
  constructor(containerId) {
    this.container = document.getElementById(containerId);
    this.activeButtons = new Set();
    this.callbacks = new Map();
    this.init();
  }

  init() {
    this.container.addEventListener('click', this.handleClick.bind(this));
    this.container.addEventListener('keydown', this.handleKeydown.bind(this));
  }

  // Handle button clicks with state management
  handleClick(event) {
    const button = event.target.closest('button');
    if (!button) return;

    const groupElement = button.closest('.btn-group, .btn-group-vertical');
    const groupType = groupElement.dataset.groupType || 'single';
    const buttonId = button.dataset.buttonId;

    this.updateButtonState(button, groupElement, groupType);
    this.executeCallback(buttonId, button);
  }

  // Update button states based on group type
  updateButtonState(button, group, type) {
    const buttons = group.querySelectorAll('button');

    switch (type) {
      case 'single':
        // Single selection - deactivate others
        buttons.forEach(btn => {
          btn.classList.remove('active');
          btn.setAttribute('aria-pressed', 'false');
        });
        button.classList.add('active');
        button.setAttribute('aria-pressed', 'true');
        break;

      case 'multiple':
        // Multiple selection - toggle current
        const isActive = button.classList.contains('active');
        button.classList.toggle('active');
        button.setAttribute('aria-pressed', (!isActive).toString());
        break;

      case 'toggle':
        // Toggle group - all on or all off
        const allActive = Array.from(buttons).every(btn =>
          btn.classList.contains('active')
        );
        buttons.forEach(btn => {
          btn.classList.toggle('active', !allActive);
          btn.setAttribute('aria-pressed', (!allActive).toString());
        });
        break;
    }
  }

  // Keyboard navigation support
  handleKeydown(event) {
    const button = event.target;
    if (!button.matches('button')) return;

    const group = button.closest('.btn-group, .btn-group-vertical');
    const buttons = Array.from(group.querySelectorAll('button'));
    const currentIndex = buttons.indexOf(button);
    const isVertical = group.classList.contains('btn-group-vertical');

    let nextIndex = currentIndex;

    switch (event.key) {
      case 'ArrowLeft':
      case 'ArrowUp':
        if ((event.key === 'ArrowLeft' && !isVertical) ||
            (event.key === 'ArrowUp' && isVertical)) {
          nextIndex = currentIndex > 0 ? currentIndex - 1 : buttons.length - 1;
          event.preventDefault();
        }
        break;

      case 'ArrowRight':
      case 'ArrowDown':
        if ((event.key === 'ArrowRight' && !isVertical) ||
            (event.key === 'ArrowDown' && isVertical)) {
          nextIndex = currentIndex < buttons.length - 1 ? currentIndex + 1 : 0;
          event.preventDefault();
        }
        break;

      case 'Home':
        nextIndex = 0;
        event.preventDefault();
        break;

      case 'End':
        nextIndex = buttons.length - 1;
        event.preventDefault();
        break;
    }

    if (nextIndex !== currentIndex) {
      buttons[nextIndex].focus();
    }
  }

  // Register callback for button actions
  onButtonAction(buttonId, callback) {
    this.callbacks.set(buttonId, callback);
  }

  // Execute registered callback
  executeCallback(buttonId, button) {
    const callback = this.callbacks.get(buttonId);
    if (callback) {
      callback(button, this.getGroupState(button));
    }
  }

  // Get current state of button group
  getGroupState(button) {
    const group = button.closest('.btn-group, .btn-group-vertical');
    const buttons = group.querySelectorAll('button');
    const activeButtons = group.querySelectorAll('button.active');

    return {
      totalButtons: buttons.length,
      activeCount: activeButtons.length,
      activeButtons: Array.from(activeButtons).map(btn => btn.dataset.buttonId),
      groupType: group.dataset.groupType || 'single'
    };
  }

  // Programmatically set button state
  setButtonState(buttonId, active = true) {
    const button = this.container.querySelector(`[data-button-id="${buttonId}"]`);
    if (button) {
      button.classList.toggle('active', active);
      button.setAttribute('aria-pressed', active.toString());
    }
  }

  // Add loading state to button
  setButtonLoading(buttonId, loading = true) {
    const button = this.container.querySelector(`[data-button-id="${buttonId}"]`);
    if (button) {
      if (loading) {
        button.disabled = true;
        button.innerHTML = '<i class="ri-loader-4-line me-1"></i>Loading...';
      } else {
        button.disabled = false;
        // Restore original content - you'd store this separately
      }
    }
  }
}

Accessibility Considerations

Ensure button groups are accessible to all users by following these best practices:

  • Use role="group" on button groups to indicate their relationship
  • Add descriptive aria-label attributes to explain the button group's purpose
  • Mark active states with aria-current="page" or aria-pressed="true"
  • Ensure sufficient color contrast between button text and backgrounds
  • Provide visible focus indicators for keyboard navigation
  • Include descriptive text or aria-labels for icon-only buttons

On this page


Copyright © 2025 Your Company. All rights reserved.

Version 1.0.8