Skip to main content Skip to docs navigation

Buttons

Use Bootstrap’s custom button styles for actions in forms, dialogs, and more with support for multiple sizes, states, and more.

Base class

Buttons have a standard .btn class that sets up basic styles such as padding and content alignment, along with fallback visual styles for basic accessibility. Change this class to another button class to apply different visual styles for a specific button variant and theme.

HTML
<button type="button" class="btn">Base class</button>

The .btn class is intended to be a starting point for your own custom button styles, while our provided button variants used in conjunction with our button variants, or to serve as a basis for your own custom styles.

Playground

Bootstrap includes several button variants, each serving its own semantic purpose, with a few extras thrown in for more control. Combined with our utilities, you have a very powerful set of defaults to choose from.

HTML
<button type="button" class="btn btn-solid theme-primary" data-button-type="text">Button</button>
<button type="button" class="btn btn-solid theme-primary" data-button-type="left-icon">
  <svg class="bi me-1" width="16" height="16" aria-hidden="true">
    <use href="#arrow-left" />
  </svg>
  Left icon
</button>
<button type="button" class="btn btn-solid theme-primary" data-button-type="right-icon">
  Right icon
  <svg class="bi ms-1" width="16" height="16" aria-hidden="true">
    <use href="#arrow-right" />
  </svg>
</button>
<button type="button" class="btn btn-solid btn-icon theme-primary" data-button-type="icon-only" aria-label="Icon only">
  <svg class="bi" width="16" height="16" aria-hidden="true">
    <use href="#plus-lg" />
  </svg>
</button>

Variants

Compare all button variants and styles at once:

HTML
<button type="button" class="btn-solid theme-primary">Primary</button>
<button type="button" class="btn-outline theme-primary">Primary</button>
<button type="button" class="btn-subtle theme-primary">Primary</button>
<button type="button" class="btn-text theme-primary">Primary</button>
<button type="button" class="btn-solid theme-accent">Accent</button>
<button type="button" class="btn-outline theme-accent">Accent</button>
<button type="button" class="btn-subtle theme-accent">Accent</button>
<button type="button" class="btn-text theme-accent">Accent</button>
<button type="button" class="btn-solid theme-success">Success</button>
<button type="button" class="btn-outline theme-success">Success</button>
<button type="button" class="btn-subtle theme-success">Success</button>
<button type="button" class="btn-text theme-success">Success</button>
<button type="button" class="btn-solid theme-danger">Danger</button>
<button type="button" class="btn-outline theme-danger">Danger</button>
<button type="button" class="btn-subtle theme-danger">Danger</button>
<button type="button" class="btn-text theme-danger">Danger</button>
<button type="button" class="btn-solid theme-warning">Warning</button>
<button type="button" class="btn-outline theme-warning">Warning</button>
<button type="button" class="btn-subtle theme-warning">Warning</button>
<button type="button" class="btn-text theme-warning">Warning</button>
<button type="button" class="btn-solid theme-info">Info</button>
<button type="button" class="btn-outline theme-info">Info</button>
<button type="button" class="btn-subtle theme-info">Info</button>
<button type="button" class="btn-text theme-info">Info</button>
<button type="button" class="btn-solid theme-inverse">Inverse</button>
<button type="button" class="btn-outline theme-inverse">Inverse</button>
<button type="button" class="btn-subtle theme-inverse">Inverse</button>
<button type="button" class="btn-text theme-inverse">Inverse</button>
<button type="button" class="btn-solid theme-secondary">Secondary</button>
<button type="button" class="btn-outline theme-secondary">Secondary</button>
<button type="button" class="btn-subtle theme-secondary">Secondary</button>
<button type="button" class="btn-text theme-secondary">Secondary</button>
Accessibility Tip: Using color to convey meaning

Using color to add meaning only provides a visual indication, which will not be conveyed to users of assistive technologies like screen readers. Please ensure the meaning is obvious from the content itself (e.g., the visible text with a sufficient color contrast) or is included through alternative means, such as additional text hidden with the .visually-hidden class.

Use the .btn-link class to create a button that looks like a link.

HTML
<button type="button" class="btn btn-link">Link</button>

Link buttons can also be styled with the theme colors.

HTML
<button type="button" class="btn btn-link theme-primary">Primary</button>
<button type="button" class="btn btn-link theme-accent">Accent</button>
<button type="button" class="btn btn-link theme-success">Success</button>
<button type="button" class="btn btn-link theme-danger">Danger</button>
<button type="button" class="btn btn-link theme-warning">Warning</button>
<button type="button" class="btn btn-link theme-info">Info</button>
<button type="button" class="btn btn-link theme-inverse">Inverse</button>
<button type="button" class="btn btn-link theme-secondary">Secondary</button>

Styled buttons

Add visual depth to solid buttons with gradients and shadows using the .btn-styled modifier class. This provides a more three-dimensional appearance that can be customized further with CSS variables.

HTML
<button class="btn-solid btn-styled theme-primary">Primary</button>
<button class="btn-solid btn-styled theme-accent">Accent</button>
<button class="btn-solid btn-styled theme-success">Success</button>
<button class="btn-solid btn-styled theme-danger">Danger</button>
<button class="btn-solid btn-styled theme-warning">Warning</button>
<button class="btn-solid btn-styled theme-info">Info</button>
<button class="btn-solid btn-styled theme-inverse">Inverse</button>
<button class="btn-solid btn-styled theme-secondary">Secondary</button>

The gradient and shadow can be customized via CSS variables:

VariableDescription
--bs-btn-gradient-startTop of gradient (default: rgb(255 255 255 / 12.5%))
--bs-btn-gradient-endBottom of gradient (default: rgb(0 0 0 / 7.5%))
--bs-btn-border-mix-colorColor to mix with the button background (default: #000)
--bs-btn-border-mix-amountAmount of color to mix with the button background (default: 10%)
--bs-btn-border-hover-mix-amountAmount of color to mix with the button background on hover (default: 12.5%)
--bs-btn-border-active-mix-amountAmount of color to mix with the button background on active (default: 20%)
--bs-btn-shadowResting state shadow
--bs-btn-active-shadowPressed/active state shadow

Button tags

The .btn classes are designed to be used with the <button> element. However, you can also use these classes on <a> or <input> elements (though some browsers may apply a slightly different rendering).

When using button classes on <a> elements that are used to trigger in-page functionality (like collapsing content), rather than linking to new pages or sections within the current page, these links should be given a role="button" to appropriately convey their purpose to assistive technologies such as screen readers.

Link
HTML
<a class="btn-solid theme-primary" href="#" role="button">Link</a>
<button class="btn-solid theme-primary" type="submit">Button</button>
<input class="btn-solid theme-primary" type="button" value="Input">
<input class="btn-solid theme-primary" type="submit" value="Submit">
<input class="btn-solid theme-primary" type="reset" value="Reset">

Sizes

Fancy larger or smaller buttons? Add .btn-lg or .btn-sm for additional sizes.

HTML
<button type="button" class="btn-solid theme-primary btn-lg">Large button</button>
<button type="button" class="btn-solid theme-secondary btn-lg">Large button</button>
HTML
<button type="button" class="btn-solid theme-primary btn-sm">Small button</button>
<button type="button" class="btn-solid theme-secondary btn-sm">Small button</button>
HTML
<button type="button" class="btn-solid theme-primary btn-xs">Extra small button</button>
<button type="button" class="btn-solid theme-secondary btn-xs">Extra small button</button>

You can even roll your own custom sizing with CSS variables:

HTML
<button type="button" class="btn-solid theme-primary"
        style="--bs-btn-padding-y: .25rem; --bs-btn-padding-x: .5rem; --bs-btn-font-size: .75rem;">
  Custom button
</button>

Icon buttons

Use .btn-icon for square buttons that contain only an icon. This class sets aspect-ratio: 1 and removes padding, making the button perfectly square based on its min-height. Always include an aria-label attribute on icon-only buttons to ensure they are accessible to screen reader users.

HTML
<button type="button" class="btn-solid theme-primary btn-icon" aria-label="Confirm">
  <svg class="bi" width="16" height="16" fill="currentColor" aria-hidden="true"><use href="#check2"></use></svg>
</button>
<button type="button" class="btn-outline theme-secondary btn-icon" aria-label="Auto theme">
  <svg class="bi" width="16" height="16" fill="currentColor" aria-hidden="true"><use href="#circle-half"></use></svg>
</button>
<button type="button" class="btn-subtle theme-warning btn-icon" aria-label="Light theme">
  <svg class="bi" width="16" height="16" fill="currentColor" aria-hidden="true"><use href="#sun-fill"></use></svg>
</button>

Combine with size classes for different icon button sizes:

HTML
<button type="button" class="btn-solid theme-primary btn-icon btn-xs" aria-label="Confirm">
  <svg class="bi" width="12" height="12" fill="currentColor" aria-hidden="true"><use href="#check2"></use></svg>
</button>
<button type="button" class="btn-solid theme-primary btn-icon btn-sm" aria-label="Confirm">
  <svg class="bi" width="14" height="14" fill="currentColor" aria-hidden="true"><use href="#check2"></use></svg>
</button>
<button type="button" class="btn-solid theme-primary btn-icon" aria-label="Confirm">
  <svg class="bi" width="16" height="16" fill="currentColor" aria-hidden="true"><use href="#check2"></use></svg>
</button>
<button type="button" class="btn-solid theme-primary btn-icon btn-lg" aria-label="Confirm">
  <svg class="bi" width="20" height="20" fill="currentColor" aria-hidden="true"><use href="#check2"></use></svg>
</button>

Disabled state

Make buttons look inactive by adding the disabled boolean attribute to any <button> element. Disabled buttons have pointer-events: none, preventing hover and active states from triggering, and some additional styling to indicate the disabled state.

HTML
<button type="button" class="btn-solid theme-primary" disabled>Primary button</button>
<button type="button" class="btn-solid theme-secondary" disabled>Button</button>
<button type="button" class="btn-outline theme-primary" disabled>Primary button</button>
<button type="button" class="btn-outline theme-secondary" disabled>Button</button>

Disabled buttons using the <a> element behave a bit different. Use the .disabled class instead of the attribute on <a> elements to make them visually appear disabled. If you need to keep the href attribute, you may need additional HTML to fully disable the link functionality.

HTML
<a class="btn-solid theme-primary disabled" role="button" aria-disabled="true">Primary link</a>
<a class="btn-solid theme-secondary disabled" role="button" aria-disabled="true">Link</a>

If there's an href attribute, add tabindex="-1" and aria-disabled="true" to prevent keyboard focus and assistive technologies from interacting with the link.

HTML
<a href="#" class="btn-solid theme-primary disabled" tabindex="-1" role="button" aria-disabled="true">Primary link</a>
<a href="#" class="btn-solid theme-secondary disabled" tabindex="-1" role="button" aria-disabled="true">Link</a>

You may also want to use custom JavaScript to disable the link functionality altogether.

Block buttons

Use the .d-grid utility to create responsive stacks of full-width “block buttons”. Space them out with gap utilities.

HTML
<div class="d-grid gap-2">
  <button class="btn-solid theme-primary" type="button">Button</button>
  <button class="btn-solid theme-primary" type="button">Button</button>
</div>

Here we create a responsive variation, starting with vertically stacked buttons until the md breakpoint, where .d-md-block replaces the .d-grid class, thus nullifying the gap-2 utility. Resize your browser to see them change.

HTML
<div class="d-grid gap-2 d-md-block">
  <button class="btn-solid theme-primary" type="button">Button</button>
  <button class="btn-solid theme-primary" type="button">Button</button>
</div>

You can adjust the width of your block buttons with grid column width classes. For example, for a half-width “block button”, use .col-6. Center it horizontally with .mx-auto, too.

HTML
<div class="d-grid gap-2 col-6 mx-auto">
  <button class="btn-solid theme-primary" type="button">Button</button>
  <button class="btn-solid theme-primary" type="button">Button</button>
</div>

Additional utilities can be used to adjust the alignment of buttons when horizontal. Here we’ve taken our previous responsive example and added some flex utilities and a margin utility on the button to right-align the buttons when they’re no longer stacked.

HTML
<div class="d-grid gap-2 d-md-flex justify-content-md-end">
  <button class="btn-solid theme-primary me-md-2" type="button">Button</button>
  <button class="btn-solid theme-primary" type="button">Button</button>
</div>

Toggle buttons

Create button-like checkboxes and radio buttons by adding .btn-check to a <label> element with button classes, with a checkbox or radio input nested inside. The input is visually hidden while the label provides the button appearance. These toggle buttons can further be grouped in a button group if needed.

Visually, these toggle buttons are identical to our JavaScript toggle buttons, but are conveyed differently by assistive technologies. Checkbox toggles will be announced by screen readers as "checked"/"not checked"as they are checkboxes under the hood. The JavaScript toggle buttons are announced as "button"/"button pressed". It’s up to you to decide which approach makes more sense for your use case.

Checkboxes

Checkboxes can be checked, unchecked, or disabled. Checkbox-based toggle buttons only toggle a single button’s state.

HTML
<label class="btn-check btn-solid theme-primary">
  <input type="checkbox" checked autocomplete="off">
  Checked
</label>

<label class="btn-check btn-solid theme-primary">
  <input type="checkbox" autocomplete="off">
  Toggle
</label>

<label class="btn-check btn-solid theme-primary">
  <input type="checkbox" disabled autocomplete="off">
  Disabled
</label>

Radios

Radios can be checked, unchecked, or disabled. Use radio-based toggle buttons to toggle states between a set of buttons that include input elements with the same name attribute value.

HTML
<label class="btn-check btn-solid theme-primary">
  <input type="radio" name="options" autocomplete="off" checked>
  Checked
</label>

<label class="btn-check btn-solid theme-primary">
  <input type="radio" name="options" autocomplete="off">
  Toggle
</label>

<label class="btn-check btn-solid theme-primary">
  <input type="radio" name="options" disabled autocomplete="off">
  Disabled
</label>

<label class="btn-check btn-solid theme-primary">
  <input type="radio" name="options" autocomplete="off">
  Toggle
</label>

Button plugin

The button plugin allows you to create simple on/off toggle buttons.

Visually, these toggle buttons are identical to our input toggle buttons, but are conveyed differently by assistive technologies. Checkbox toggles will be announced by screen readers as "checked"/"not checked"as they are checkboxes under the hood. The JavaScript toggle buttons are announced as "button"/"button pressed". It’s up to you to decide which approach makes more sense for your use case.

Toggle states

Add data-bs-toggle="button" to toggle a button’s active state. If you’re pre-toggling a button, you must manually add the .active class and aria-pressed="true" to ensure that it is conveyed appropriately to assistive technologies.

HTML
<button type="button" class="btn-solid theme-primary" data-bs-toggle="button">Toggle button</button>
<button type="button" class="btn-solid theme-primary active" data-bs-toggle="button" aria-pressed="true">Active toggle button</button>
<button type="button" class="btn-solid theme-primary" disabled data-bs-toggle="button">Disabled toggle button</button>
HTML
<a href="#" class="btn-solid theme-primary" role="button" data-bs-toggle="button">Toggle link</a>
<a href="#" class="btn-solid theme-primary active" role="button" data-bs-toggle="button" aria-pressed="true">Active toggle link</a>
<a class="btn-solid theme-primary disabled" aria-disabled="true" role="button" data-bs-toggle="button">Disabled toggle link</a>

Methods

You can create a button instance with the button constructor, for example:

JavaScript
const bsButton = new bootstrap.Button('#myButton')
MethodDescription
disposeDestroys an element’s button. (Removes stored data on the DOM element)
getInstanceStatic method which allows you to get the button instance associated with a DOM element, you can use it like this: bootstrap.Button.getInstance(element).
getOrCreateInstanceStatic method which returns a button instance associated with a DOM element or creates a new one in case it wasn’t initialized. You can use it like this: bootstrap.Button.getOrCreateInstance(element).
toggleToggles push state. Gives the button the appearance that it has been activated.

For example, to toggle all buttons

JavaScript
document.querySelectorAll('.btn').forEach(buttonElement => {
  const button = bootstrap.Button.getOrCreateInstance(buttonElement)
  button.toggle()
})

CSS

Variables

Buttons use CSS variables for real-time customization. These are set on the base .btn class and inherited by all button variants.

SCSS
--btn-min-height: 2.25rem;
--btn-padding-x: #{$btn-padding-x};
--btn-padding-y: #{$btn-padding-y};
// --btn-font-family: #{$btn-font-family};
--btn-font-size: #{$btn-font-size};
--btn-font-weight: #{$btn-font-weight};
--btn-line-height: #{$btn-line-height};
--btn-color: #{$btn-color};
--btn-border-width: #{$btn-border-width};
--btn-border-color: transparent;
--btn-border-radius: #{$btn-border-radius};
--btn-hover-border-color: transparent;
--btn-disabled-opacity: #{$btn-disabled-opacity};

Each variant class (.btn-solid, .btn-outline, etc.) updates these variables based on the current theme color, allowing buttons to adapt automatically when used with .theme-* classes.

Sass variables

Base button styling uses these Sass variables for padding, typography, and sizing across all button variants.

SCSS
$btn-color:                   var(--fg-body);
$btn-padding-y:               .375rem;
$btn-padding-x:               .75rem;
$btn-font-size:               var(--font-size-base);
$btn-line-height:             var(--line-height-base);
$btn-white-space:             null; // Set to `nowrap` to prevent text wrapping

$btn-padding-y-xs:            .125rem;
$btn-padding-x-xs:            .375rem;
$btn-font-size-xs:            var(--font-size-xs);
$btn-line-height-xs:          1.125rem;

$btn-padding-y-sm:            .25rem;
$btn-padding-x-sm:            .5rem;
$btn-font-size-sm:            var(--font-size-sm);
$btn-line-height-sm:          1.125rem;

$btn-padding-y-lg:            .5rem;
$btn-padding-x-lg:            1rem;
$btn-font-size-lg:            var(--font-size-md);
$btn-line-height-lg:          1.25rem;

// Intentionally left for folks who want it
// $btn-padding-y-xl:            .75rem;
// $btn-padding-x-xl:            1.25rem;
// $btn-font-size-xl:            var(--font-size-lg);
// $btn-line-height-xl:          1.5rem;

$btn-border-width:            var(--border-width);

$btn-font-weight:             var(--font-weight-normal);
$btn-disabled-opacity:        .65;

$btn-link-color:              var(--link-color);
$btn-link-hover-color:        var(--link-hover-color);
$btn-link-disabled-color:     var(--fg-3);

// Allows for customizing button radius independently from global border radius
$btn-border-radius:           var(--border-radius);
$btn-border-radius-xs:        var(--border-radius-sm);
$btn-border-radius-sm:        var(--border-radius-sm);
$btn-border-radius-lg:        var(--border-radius-lg);
$btn-border-radius-xl:        var(--border-radius-lg);

$btn-transition:              color .15s ease-in-out, background-color .15s ease-in-out, border-color .15s ease-in-out, box-shadow .15s ease-in-out;

Sass maps

Variants map

Button variants are defined in the $button-variants Sass map. Each variant specifies which theme color tokens to use for its base, hover, and active states. The map uses token names (like "bg", "contrast", "border") that reference the current theme's color palette.

SCSS
$button-variants: (
  "solid": (
    "base": (
      "bg": "bg",
      "color": "contrast",
      "border-color": "bg"
    ),
    "hover": (
      "bg": "bg",
      "border-color": "bg",
      "color": "contrast"
    ),
    "active": (
      "bg": "bg",
      "border-color": "bg",
      "color": "contrast"
    )
  ),
  "outline": (
    "base": (
      "bg": "transparent",
      "color": "text",
      "border-color": "border"
    ),
    "hover": (
      "bg": "bg",
      "color": "contrast",
      "border-color": "bg"
    ),
    "active": (
      "bg": "bg",
      "color": "contrast",
      "border-color": "bg"
    )
  ),
  "subtle": (
    "base": (
      "bg": "bg-subtle",
      "color": "text",
      "border-color": "transparent"
    ),
    "hover": (
      "bg": ("bg-muted", "bg-subtle"),
      "color": "text-emphasis"
    ),
    "active": (
      "bg": "bg-subtle",
      "color": "text-emphasis"
    )
  ),
  "text": (
    "base": (
      "color": "text",
      "bg": "transparent",
      "border-color": "transparent"
    ),
    "hover": (
      "color": "text",
      "bg": "bg-subtle"
    ),
    "active": (
      "color": "text",
      "bg": "bg-subtle"
    )
  )
);

To add a custom variant, extend the map before importing Bootstrap’s buttons:

SCSS
@use "bootstrap/scss/buttons/button" with (
  $button-variants: (
    "solid": ( /* ... */ ),
    "outline": ( /* ... */ ),
    "subtle": ( /* ... */ ),
    "text": ( /* ... */ ),
    "ghost": (
      "base": (
        "bg": "transparent",
        "color": "text",
        "border-color": "transparent"
      ),
      "hover": (
        "bg": "bg-subtle",
        "color": "text-emphasis"
      ),
      "active": (
        "bg": "bg-subtle",
        "color": "text-emphasis"
      )
    )
  )
);

To remove a variant you don't need, use Sass's map.remove():

SCSS
@use "sass:map";

@use "bootstrap/scss/buttons/button" as *button* with (
  $button-variants: map.remove($button-variants, "text", "subtle")
);

Sizes map

Button sizes are defined in the $button-sizes map. Each size specifies padding, font size, line height, border radius, and minimum height. The loop generates .btn-xs, .btn-sm, and .btn-lg classes.

SCSS
$button-sizes: (
  "xs": (
    "padding-y": $btn-padding-y-xs,
    "padding-x": $btn-padding-x-xs,
    "font-size": $btn-font-size-xs,
    "line-height": $btn-line-height-xs,
    "border-radius": $btn-border-radius-xs,
    "min-height": 1.5rem
  ),
  "sm": (
    "padding-y": $btn-padding-y-sm,
    "padding-x": $btn-padding-x-sm,
    "font-size": $btn-font-size-sm,
    "line-height": $btn-line-height-sm,
    "border-radius": $btn-border-radius-sm,
    "min-height": 2rem
  ),
  "lg": (
    "padding-y": $btn-padding-y-lg,
    "padding-x": $btn-padding-x-lg,
    "font-size": $btn-font-size-lg,
    "line-height": $btn-line-height-lg,
    "border-radius": $btn-border-radius-lg,
    "min-height": 2.75rem
  ),
  // Commented out by default on purpose
  // "xl": (
  //   "padding-y": $btn-padding-y-xl,
  //   "padding-x": $btn-padding-x-xl,
  //   "font-size": $btn-font-size-xl,
  //   "line-height": $btn-line-height-xl,
  //   "border-radius": $btn-border-radius-xl,
  //   "min-height": 3.25rem
  // ),
);

To add or modify sizes, extend the map:

SCSS
@use "bootstrap/scss/buttons/button" with (
  $button-sizes: (
    "xs": ( /* ... */ ),
    "sm": ( /* ... */ ),
    "lg": ( /* ... */ ),
    "xl": (
      "padding-y": .75rem,
      "padding-x": 1.25rem,
      "font-size": var(--bs-font-size-lg),
      "line-height": 1.5rem,
      "border-radius": var(--bs-border-radius-lg),
      "min-height": 3.25rem
    )
  )
);

Sass loops

Variant loop

The variant loop iterates over $button-variants to generate each variant class. It sets CSS variables for base, hover, active, and disabled states using the theme color tokens defined in the map.

SCSS
@each $variant, $_ in $button-variants {
  .btn-#{$variant} {
    @each $property, $value in map.get($button-variants, $variant, "base") {
      @if $value == "transparent" {
        --btn-#{$property}: transparent;
      } @else {
        --btn-#{$property}: var(--theme-#{$value});
      }
    }

    @each $property, $value in map.get($button-variants, $variant, "active") {
      @if $value == "transparent" {
        --btn-active-#{$property}: transparent;
      } @else if $value == "bg-subtle" {
        --btn-active-#{$property}: var(--theme-#{$value});
      } @else {
        --btn-active-#{$property}: oklch(from var(--theme-#{$value}) calc(l * .9) calc(c * 1.15) h);
      }
    }
    @each $property, $value in map.get($button-variants, $variant, "base") {
      @if $value == "transparent" {
        --btn-disabled-#{$property}: transparent;
      } @else {
        --btn-disabled-#{$property}: var(--theme-#{$value});
      }
    }


    &:hover {
      @each $property, $value in map.get($button-variants, $variant, "hover") {
        @if $value == "transparent" {
          --btn-hover-#{$property}: transparent;
        } @else if meta.type-of($value) == "list" {
          $first-value: list.nth($value, 1);
          $second-value: list.nth($value, 2);
          --btn-hover-#{$property}: color-mix(in oklch, var(--theme-#{$first-value}) 50%, var(--theme-#{$second-value}));
        } @else if $value == "bg-subtle" {
          --btn-hover-#{$property}: var(--theme-#{$value});
        } @else {
          --btn-hover-#{$property}: oklch(from var(--theme-#{$value}) calc(l * .95) calc(c * 1.1) h);
        }
      }
    }

    &:focus-visible {
      outline-color: var(--theme-focus-ring);
    }

    &:active,
    &.active,
    &.btn-check:has(input:checked) {
      @each $property, $value in map.get($button-variants, $variant, "active") {
        @if $value == "transparent" {
          --btn-active-#{$property}: transparent;
        } @else if $value == "bg-subtle" {
          --btn-active-#{$property}: var(--theme-#{$value});
        } @else {
          --btn-active-#{$property}: oklch(from var(--theme-#{$value}) calc(l * .9) calc(c * 1.15) h);
        }
      }
    }

    // Disabled state for toggle buttons
    &:disabled,
    &.disabled,
    &.btn-check:has(input:disabled) {
      @each $property, $value in map.get($button-variants, $variant, "base") {
        @if $value == "transparent" {
          --btn-disabled-#{$property}: transparent;
        } @else {
          --btn-disabled-#{$property}: var(--theme-#{$value});
        }
      }
    }
  }
}

Size loop

The size loop iterates over $button-sizes to generate size modifier classes, setting the appropriate CSS variables for each size.

SCSS
@each $size, $properties in $button-sizes {
  .btn-#{$size} {
    --bs-btn-min-height: #{map.get($properties, "min-height")};
    --bs-btn-padding-y: #{map.get($properties, "padding-y")};
    --bs-btn-padding-x: #{map.get($properties, "padding-x")};
    --bs-btn-font-size: #{map.get($properties, "font-size")};
    --bs-btn-line-height: #{map.get($properties, "line-height")};
    --bs-btn-border-radius: #{map.get($properties, "border-radius")};
  }
}