##### Amara Evans

amara@example.com

Pro

### Upgrade to Pro

Get access to all features

- Advanced Analytics
- Team Collaboration
- API Access

Upgrade Now
Upgrade to Pro
Log Out

# 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...
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...
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...
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...
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...
Checkbox Button Group
Loading...
Radio 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 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...
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...
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...
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 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...
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...
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...
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...
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...
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

`ESC`

###### Quick Links

###### Dashboard

Analytics Overview

###### Profile

View your profile

###### Settings

Manage preferences

###### Help Center

Get support

###### Recent Searches

Analytics Dashboard User Settings Email Templates