Checkbox Shared Partial

Follow the Installation section first!
This component requires additional setup (dependencies, gems, controllers, partials, or libraries) before using these shared partials. Please complete the Installation section on this page first.

1. Copy shared partial files

Download all 1 shared partial files as a ZIP file.

Download all files (ZIP)

After downloading, unzip and copy the checkbox/ folder to your app/views/shared/components/ directory.

Copy these files to your app/views/shared/components/checkbox/ directory:

2. Usage example

<!-- Basic checkbox -->
<%= render "shared/components/checkbox/checkbox",
  label: "I agree to the terms and conditions" %>

<!-- Checkbox with name for form submission -->
<%= render "shared/components/checkbox/checkbox",
  label: "Subscribe to newsletter",
  name: "user[newsletter]",
  checked: true %>

<!-- Checkbox with custom id -->
<%= render "shared/components/checkbox/checkbox",
  label: "Remember me",
  name: "remember_me",
  id: "remember-me-checkbox" %>

<!-- Disabled checkbox -->
<%= render "shared/components/checkbox/checkbox",
  label: "Disabled option",
  disabled: true %>

<!-- Disabled and checked -->
<%= render "shared/components/checkbox/checkbox",
  label: "Disabled checked option",
  checked: true,
  disabled: true %>

<!-- Required checkbox -->
<%= render "shared/components/checkbox/checkbox",
  label: "Accept privacy policy",
  name: "accept_privacy",
  required: true %>

<!-- With description -->
<%= render "shared/components/checkbox/checkbox",
  label: "Advanced Analytics",
  name: "features[analytics]",
  description: "Get detailed insights about your users and their behavior" %>

<!-- With description (checked) -->
<%= render "shared/components/checkbox/checkbox",
  label: "Push Notifications",
  name: "features[notifications]",
  description: "Send real-time notifications to keep users engaged",
  checked: true %>

<!-- With error message -->
<%= render "shared/components/checkbox/checkbox",
  label: "Accept terms",
  name: "accept_terms",
  error: "You must accept the terms to continue" %>

<!-- Small size -->
<%= render "shared/components/checkbox/checkbox",
  label: "Small checkbox",
  size: "sm" %>

<!-- Large size -->
<%= render "shared/components/checkbox/checkbox",
  label: "Large checkbox",
  size: "lg" %>

<!-- Small with description -->
<%= render "shared/components/checkbox/checkbox",
  label: "Compact option",
  description: "A smaller checkbox with description",
  size: "sm" %>

<!-- Large with description -->
<%= render "shared/components/checkbox/checkbox",
  label: "Prominent option",
  description: "A larger checkbox for emphasis",
  size: "lg" %>

<!-- With custom wrapper classes -->
<%= render "shared/components/checkbox/checkbox",
  label: "Custom styled",
  classes: "p-4 bg-neutral-50 dark:bg-neutral-800 rounded-lg" %>

<!-- With custom input classes -->
<%= render "shared/components/checkbox/checkbox",
  label: "Custom input",
  input_classes: "text-blue-600 focus:ring-blue-500" %>

<!-- All options combined -->
<%= render "shared/components/checkbox/checkbox",
  label: "Full featured checkbox",
  name: "full_featured",
  id: "full-featured-checkbox",
  value: "yes",
  description: "This checkbox demonstrates all available options",
  size: "md",
  required: true %>

Rendered usage example

Get detailed insights about your users and their behavior

Send real-time notifications to keep users engaged

You must accept the terms to continue

A smaller checkbox with description

A larger checkbox for emphasis

This checkbox demonstrates all available options

Checkbox ViewComponent

Follow the Installation section first!
This component requires additional setup (gems, controllers, partials, or libraries) before using this ViewComponent. Please complete the Installation section on this page first.

1. Ensure the gem is installed

gem "view_component", "~> 4.2"

2. Copy component files

Download all 2 component files as a ZIP file.

Download all files (ZIP)

After downloading, unzip and copy the checkbox/ folder to your app/components/ directory.

Copy these files to your app/components/checkbox/ directory:

3. Usage example

<!-- Basic checkbox -->
<%= render Checkbox::Component.new(
  label: "I agree to the terms and conditions"
) %>

<!-- Checkbox with name for form submission -->
<%= render Checkbox::Component.new(
  label: "Subscribe to newsletter",
  name: "user[newsletter]",
  checked: true
) %>

<!-- Checkbox with custom id -->
<%= render Checkbox::Component.new(
  label: "Remember me",
  name: "remember_me",
  id: "remember-me-checkbox"
) %>

<!-- Disabled checkbox -->
<%= render Checkbox::Component.new(
  label: "Disabled option",
  disabled: true
) %>

<!-- Disabled and checked -->
<%= render Checkbox::Component.new(
  label: "Disabled checked option",
  checked: true,
  disabled: true
) %>

<!-- Required checkbox -->
<%= render Checkbox::Component.new(
  label: "Accept privacy policy",
  name: "accept_privacy",
  required: true
) %>

<!-- With description -->
<%= render Checkbox::Component.new(
  label: "Advanced Analytics",
  name: "features[analytics]",
  description: "Get detailed insights about your users and their behavior"
) %>

<!-- With description (checked) -->
<%= render Checkbox::Component.new(
  label: "Push Notifications",
  name: "features[notifications]",
  description: "Send real-time notifications to keep users engaged",
  checked: true
) %>

<!-- With error message -->
<%= render Checkbox::Component.new(
  label: "Accept terms",
  name: "accept_terms",
  error: "You must accept the terms to continue"
) %>

<!-- Small size -->
<%= render Checkbox::Component.new(
  label: "Small checkbox",
  size: :sm
) %>

<!-- Large size -->
<%= render Checkbox::Component.new(
  label: "Large checkbox",
  size: :lg
) %>

<!-- Small with description -->
<%= render Checkbox::Component.new(
  label: "Compact option",
  description: "A smaller checkbox with description",
  size: :sm
) %>

<!-- Large with description -->
<%= render Checkbox::Component.new(
  label: "Prominent option",
  description: "A larger checkbox for emphasis",
  size: :lg
) %>

<!-- With custom wrapper classes -->
<%= render Checkbox::Component.new(
  label: "Custom styled",
  classes: "p-4 bg-neutral-50 dark:bg-neutral-800 rounded-lg"
) %>

<!-- With custom input classes -->
<%= render Checkbox::Component.new(
  label: "Custom input",
  input_classes: "text-blue-600 focus:ring-blue-500"
) %>

<!-- All options combined -->
<%= render Checkbox::Component.new(
  label: "Full featured checkbox",
  name: "full_featured",
  id: "full-featured-checkbox",
  value: "yes",
  description: "This checkbox demonstrates all available options",
  size: :md,
  required: true
) %>

Rendered usage example

Get detailed insights about your users and their behavior

Send real-time notifications to keep users engaged

You must accept the terms to continue

A smaller checkbox with description

A larger checkbox for emphasis

This checkbox demonstrates all available options

Checkbox Rails Components

Flexible checkbox components for forms, feature selection, and multi-choice options. Built with Tailwind CSS and styled to match your Rails application.

Installation

1. Custom CSS

Checkbox styling is included in the following forms CSS:

/* Forms */

label,
.label {
  @apply text-sm font-medium text-neutral-700 dark:text-neutral-100;
}

.form-input[disabled] {
  @apply cursor-not-allowed bg-neutral-200;
}

/* Custom search input clear button styling */
input[type="search"]::-webkit-search-cancel-button {
  -webkit-appearance: none;
  appearance: none;
  height: 16px;
  width: 16px;
  cursor: pointer;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cg fill='%236b7280'%3E%3Cpath d='m2.25,10.5c-.192,0-.384-.073-.53-.22-.293-.293-.293-.768,0-1.061L9.22,1.72c.293-.293.768-.293,1.061,0s.293.768,0,1.061l-7.5,7.5c-.146.146-.338.22-.53.22Z' stroke-width='0'%3E%3C/path%3E%3Cpath d='m9.75,10.5c-.192,0-.384-.073-.53-.22L1.72,2.78c-.293-.293-.293-.768,0-1.061s.768-.293,1.061,0l7.5,7.5c.293.293.293.768,0,1.061-.146.146-.338.22-.53.22Z' stroke-width='0'%3E%3C/path%3E%3C/g%3E%3C/svg%3E");
  background-size: 12px 12px;
  background-repeat: no-repeat;
  background-position: center;
}

input[type="search"]::-webkit-search-cancel-button:hover {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cg fill='%23374151'%3E%3Cpath d='m2.25,10.5c-.192,0-.384-.073-.53-.22-.293-.293-.293-.768,0-1.061L9.22,1.72c.293-.293.768-.293,1.061,0s.293.768,0,1.061l-7.5,7.5c-.146.146-.338.22-.53.22Z' stroke-width='0'%3E%3C/path%3E%3Cpath d='m9.75,10.5c-.192,0-.384-.073-.53-.22L1.72,2.78c-.293-.293-.293-.768,0-1.061s.768-.293,1.061,0l7.5,7.5c.293.293.293.768,0,1.061-.146.146-.338.22-.53.22Z' stroke-width='0'%3E%3C/path%3E%3C/g%3E%3C/svg%3E");
}

.dark input[type="search"]::-webkit-search-cancel-button {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cg fill='%23d1d5db'%3E%3Cpath d='m2.25,10.5c-.192,0-.384-.073-.53-.22-.293-.293-.293-.768,0-1.061L9.22,1.72c.293-.293.768-.293,1.061,0s.293.768,0,1.061l-7.5,7.5c-.146.146-.338.22-.53.22Z' stroke-width='0'%3E%3C/path%3E%3Cpath d='m9.75,10.5c-.192,0-.384-.073-.53-.22L1.72,2.78c-.293-.293-.293-.768,0-1.061s.768-.293,1.061,0l7.5,7.5c.293.293.293.768,0,1.061-.146.146-.338.22-.53.22Z' stroke-width='0'%3E%3C/path%3E%3C/g%3E%3C/svg%3E");
}

.dark input[type="search"]::-webkit-search-cancel-button:hover {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cg fill='%23f3f4f6'%3E%3Cpath d='m2.25,10.5c-.192,0-.384-.073-.53-.22-.293-.293-.293-.768,0-1.061L9.22,1.72c.293-.293.768-.293,1.061,0s.293.768,0,1.061l-7.5,7.5c-.146.146-.338.22-.53.22Z' stroke-width='0'%3E%3C/path%3E%3Cpath d='m9.75,10.5c-.192,0-.384-.073-.53-.22L1.72,2.78c-.293-.293-.293-.768,0-1.061s.768-.293,1.061,0l7.5,7.5c.293.293.293.768,0,1.061-.146.146-.338.22-.53.22Z' stroke-width='0'%3E%3C/path%3E%3C/g%3E%3C/svg%3E");
}

/* non-input elements (like the Stripe card form) can be styled to look like an input */
div.form-control {
  -webkit-appearance: none;
  -moz-appearance: none;
  appearance: none;
  background-color: #fff;
  border-width: 1px;
  padding-top: 0.5rem;
  padding-right: 0.75rem;
  padding-bottom: 0.5rem;
  padding-left: 0.75rem;
  font-size: 1rem;
  line-height: 1.5rem;
}

.form-control {
  @apply block w-full rounded-lg bg-white border-0 px-3 py-2 text-base/6 text-neutral-900 shadow-xs ring-1 ring-neutral-300 outline-hidden ring-inset placeholder:text-neutral-500 focus:ring-2 focus:ring-neutral-600 dark:bg-neutral-700 dark:text-white dark:placeholder-neutral-300 dark:ring-neutral-600 dark:focus:ring-neutral-500;
}

@media (min-width: 640px) {
  .form-control {
    font-size: 0.875rem; /* text-sm equivalent (14px) for larger screens */
  }
}

.form-control[disabled] {
  @apply cursor-not-allowed bg-neutral-100 dark:bg-neutral-600;
}

.form-control.error {
  @apply border-red-400 ring-red-300 focus:ring-red-500 dark:border-red-600 dark:ring-red-500;
}

select:not([multiple]) {
  @apply w-full appearance-none rounded-lg border-0 bg-white px-3 py-2 text-base/6 text-neutral-900 shadow-xs ring-1 ring-neutral-300 outline-hidden ring-inset focus:ring-2 focus:ring-neutral-600;

  /* Custom dropdown arrow */
  background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%23737373' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3e%3c/svg%3e");
  background-position: right 0.75rem center;
  background-repeat: no-repeat;
  background-size: 1.25em 1.25em;
  padding-right: 2.5rem;
}

@media (min-width: 640px) {
  select:not([multiple]) {
    font-size: 0.875rem; /* text-sm equivalent (14px) for larger screens */
  }
}

/* Dark mode styling for single select */
.dark {
  select:not([multiple]) {
    @apply dark:bg-neutral-700 dark:text-white dark:ring-neutral-600 dark:focus:ring-neutral-500;
    background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%23A1A1AA' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3e%3c/svg%3e");
  }
}

select:not([multiple])[disabled] {
  @apply cursor-not-allowed bg-neutral-100 opacity-75 ring-neutral-200 dark:bg-neutral-600 dark:ring-neutral-500;
}

select[multiple] {
  @apply w-full rounded-lg rounded-r-none border-0 bg-white px-3 py-2.5 text-base/6 text-neutral-900 shadow-xs outline-1 -outline-offset-1 outline-neutral-300 focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-neutral-600 dark:outline-neutral-600;
  min-height: 120px;
}

select[multiple] option {
  @apply rounded-md;
}

@media (min-width: 640px) {
  select[multiple] {
    font-size: 0.875rem; /* text-sm equivalent (14px) for larger screens */
  }
}

/* Dark mode styling for multiple select */
.dark {
  select[multiple] {
    @apply dark:bg-neutral-700 dark:text-white dark:ring-neutral-600 dark:focus:ring-neutral-500;
  }
}

select[multiple][disabled] {
  @apply cursor-not-allowed bg-neutral-100 opacity-75 ring-neutral-200 dark:bg-neutral-600 dark:ring-neutral-500;
}

option {
  @apply bg-white px-3 py-2 text-sm text-neutral-900 dark:bg-neutral-700 dark:text-neutral-100;
}

option:checked {
  @apply bg-neutral-100 dark:bg-neutral-600;
}

option:hover {
  @apply bg-neutral-50 dark:bg-neutral-600;
}

.caret {
  @apply pointer-events-none absolute inset-y-0 right-0 flex items-center px-2 text-neutral-800;
}

[type="checkbox"] {
  @apply size-4 cursor-pointer appearance-none rounded-sm border border-neutral-300 bg-white checked:border-neutral-700 checked:bg-neutral-700 focus:outline-2 focus:outline-offset-2 focus:outline-neutral-600 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-neutral-600 disabled:border-neutral-300 disabled:bg-neutral-100 disabled:checked:bg-neutral-100 dark:border-white/20 dark:bg-neutral-800 dark:checked:border-white/20 dark:checked:bg-neutral-900 dark:focus:outline-neutral-200 dark:focus-visible:outline-neutral-200 dark:disabled:border-neutral-500 dark:disabled:bg-neutral-400 dark:disabled:checked:bg-neutral-500 forced-colors:appearance-auto;
}

[type="checkbox"]:checked {
  @apply text-white dark:text-neutral-800;
  background-image: url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M12.207 4.793a1 1 0 010 1.414l-5 5a1 1 0 01-1.414 0l-2-2a1 1 0 011.414-1.414L6.5 9.086l4.293-4.293a1 1 0 011.414 0z'/%3e%3c/svg%3e");
  background-size: 100% 100%;
  background-position: center;
  background-repeat: no-repeat;
}

[type="checkbox"]:indeterminate {
  @apply border-neutral-400 bg-neutral-500 dark:border-white/20 dark:bg-neutral-700;
  background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3e%3cg fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' %3e%3cline x1='10.75' y1='6' x2='1.25' y2='6'%3e%3c/line%3e%3c/g%3e%3c/svg%3e");
  background-size: 75% 75%;
  background-position: center;
  background-repeat: no-repeat;
}

[type="checkbox"]:disabled {
  @apply cursor-not-allowed border-neutral-300 bg-neutral-200 text-neutral-400 opacity-75 hover:text-neutral-300 dark:border-neutral-600 dark:bg-neutral-700 dark:text-neutral-300 dark:hover:text-neutral-500;
}

[type="checkbox"]:disabled:checked {
  @apply border-neutral-300 bg-neutral-200 dark:border-neutral-600 dark:bg-neutral-600;
}

/* Anchor indicator for shift-click range selection */
[type="checkbox"].checkbox-anchor {
  outline: 2px dashed currentColor;
  outline-offset: 2px;
  @apply outline-neutral-600 dark:outline-neutral-200;
}

[type="radio"] {
  @apply size-4 cursor-pointer appearance-none rounded-full border border-neutral-300 bg-white checked:border-neutral-700 checked:bg-neutral-700 focus:outline-2 focus:outline-offset-2 focus:outline-neutral-600 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-neutral-600 disabled:border-neutral-300 disabled:bg-neutral-100 disabled:checked:bg-neutral-100 dark:border-white/20 dark:bg-neutral-800 dark:checked:border-white/20 dark:checked:bg-neutral-900 dark:focus:outline-neutral-200 dark:focus-visible:outline-neutral-200 dark:disabled:border-neutral-500 dark:disabled:bg-neutral-400 dark:disabled:checked:bg-neutral-500 forced-colors:appearance-auto;
}

[type="radio"]:checked {
  @apply text-white dark:text-neutral-800;
  background-image: url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3ccircle cx='8' cy='8' r='3'/%3e%3c/svg%3e");
  background-size: 100% 100%;
  background-position: center;
  background-repeat: no-repeat;
}

[type="radio"]:disabled {
  @apply cursor-not-allowed border-neutral-300 bg-neutral-300 text-neutral-400 opacity-75 hover:text-neutral-300 dark:border-neutral-600 dark:bg-neutral-700 dark:text-neutral-300 dark:hover:text-neutral-500;
}

[type="radio"]:disabled:checked {
  @apply border-neutral-300 dark:border-neutral-600 dark:bg-neutral-600;
}

/* Datalist styling */
input[list] {
  -webkit-appearance: none;
  -moz-appearance: none;
  appearance: none;
}

/* Replace default datalist arrow in WebKit browsers */
input[list].replace-default-datalist-arrow::-webkit-calendar-picker-indicator {
  display: none !important;
  -webkit-appearance: none !important;
}

input[list].replace-default-datalist-arrow {
  padding-right: 2.5rem;
  background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%23737373' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3e%3c/svg%3e");
  background-position: right 0.75rem center;
  background-repeat: no-repeat;
  background-size: 1.25em 1.25em;
}

/* Dark mode datalist arrow */
.dark {
  input[list].replace-default-datalist-arrow {
    background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%23A1A1AA' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3e%3c/svg%3e");
  }
}

Examples

Basic Checkbox

Simple checkbox inputs with labels, including checked and disabled states.

<div class="space-y-4">
  <div class="flex items-center gap-2.5">
    <input type="checkbox" id="checkbox-1" name="options" value="option1" class="size-4 rounded border-neutral-300 text-neutral-900 focus:ring-neutral-500 focus:ring-offset-0 dark:border-neutral-600 dark:bg-neutral-800 dark:text-neutral-100 dark:focus:ring-neutral-400 dark:checked:bg-neutral-600 dark:checked:border-neutral-500">
    <label for="checkbox-1" class="text-sm font-medium text-neutral-700 dark:text-neutral-300">
      I agree to the terms and conditions
    </label>
  </div>

  <div class="flex items-center gap-2.5">
    <input type="checkbox" id="checkbox-2" name="options" value="option2" checked class="size-4 rounded border-neutral-300 text-neutral-900 focus:ring-neutral-500 focus:ring-offset-0 dark:border-neutral-600 dark:bg-neutral-800 dark:text-neutral-100 dark:focus:ring-neutral-400 dark:checked:bg-neutral-600 dark:checked:border-neutral-500">
    <label for="checkbox-2" class="text-sm font-medium text-neutral-700 dark:text-neutral-300">
      Subscribe to newsletter
    </label>
  </div>

  <div class="flex items-center gap-2.5">
    <input type="checkbox" id="checkbox-3" name="options" value="option3" disabled class="size-4 rounded border-neutral-300 text-neutral-900 focus:ring-neutral-500 focus:ring-offset-0 dark:border-neutral-600 dark:bg-neutral-800 dark:text-neutral-100 dark:focus:ring-neutral-400 dark:checked:bg-neutral-600 dark:checked:border-neutral-500 disabled:cursor-not-allowed disabled:opacity-50">
    <label for="checkbox-3" class="text-sm font-medium text-neutral-400 dark:text-neutral-500 cursor-not-allowed opacity-50">
      Disabled option
    </label>
  </div>
</div>

Checkbox with Descriptions

Checkboxes with additional descriptive text, perfect for feature selection or settings.

Get detailed insights about your users and their behavior

Send real-time notifications to keep users engaged

Integrate with your existing tools and workflows

<div class="space-y-4 max-w-md">
  <div class="flex items-start gap-2.5">
    <input type="checkbox" id="checkbox-desc-1" name="features" value="analytics" class="mt-0.5 size-4 shrink-0 rounded border-neutral-300 text-neutral-900 focus:ring-neutral-500 focus:ring-offset-0 dark:border-neutral-600 dark:bg-neutral-800 dark:text-neutral-100 dark:focus:ring-neutral-400 dark:checked:bg-neutral-600 dark:checked:border-neutral-500">
    <div class="min-w-0 flex-1 flex flex-col gap-0.5 leading-snug">
      <label for="checkbox-desc-1" class="text-sm leading-snug font-medium text-neutral-700 dark:text-neutral-300">
        Advanced Analytics
      </label>
      <p class="text-xs leading-normal text-neutral-500 dark:text-neutral-400">
        Get detailed insights about your users and their behavior
      </p>
    </div>
  </div>

  <div class="flex items-start gap-2.5">
    <input type="checkbox" id="checkbox-desc-2" name="features" value="notifications" checked class="mt-0.5 size-4 shrink-0 rounded border-neutral-300 text-neutral-900 focus:ring-neutral-500 focus:ring-offset-0 dark:border-neutral-600 dark:bg-neutral-800 dark:text-neutral-100 dark:focus:ring-neutral-400 dark:checked:bg-neutral-600 dark:checked:border-neutral-500">
    <div class="min-w-0 flex-1 flex flex-col gap-0.5 leading-snug">
      <label for="checkbox-desc-2" class="text-sm leading-snug font-medium text-neutral-700 dark:text-neutral-300">
        Push Notifications
      </label>
      <p class="text-xs leading-normal text-neutral-500 dark:text-neutral-400">
        Send real-time notifications to keep users engaged
      </p>
    </div>
  </div>

  <div class="flex items-start gap-2.5">
    <input type="checkbox" id="checkbox-desc-3" name="features" value="api" class="mt-0.5 size-4 shrink-0 rounded border-neutral-300 text-neutral-900 focus:ring-neutral-500 focus:ring-offset-0 dark:border-neutral-600 dark:bg-neutral-800 dark:text-neutral-100 dark:focus:ring-neutral-400 dark:checked:bg-neutral-600 dark:checked:border-neutral-500">
    <div class="min-w-0 flex-1 flex flex-col gap-0.5 leading-snug">
      <label for="checkbox-desc-3" class="text-sm leading-snug font-medium text-neutral-700 dark:text-neutral-300">
        API Access
      </label>
      <p class="text-xs leading-normal text-neutral-500 dark:text-neutral-400">
        Integrate with your existing tools and workflows
      </p>
    </div>
  </div>
</div>

Checkbox Cards

Card-style checkboxes for pricing plans or feature selection with enhanced visual hierarchy.

Choose your add-ons
<fieldset class="space-y-3 max-w-sm w-full">
  <legend class="sr-only">Choose your add-ons</legend>

  <label for="plan-startup" class="py-3 px-4 flex items-start gap-3 font-medium bg-white text-neutral-800 rounded-xl cursor-pointer ring-1 ring-neutral-200 has-[:checked]:ring-2 has-[:checked]:ring-neutral-400 dark:bg-neutral-700/50 dark:text-neutral-200 dark:ring-neutral-700 dark:has-[:checked]:ring-neutral-400 has-[:checked]:bg-neutral-100 has-[:checked]:text-neutral-900 dark:has-[:checked]:bg-neutral-600/60 dark:has-[:checked]:text-white">
    <input type="checkbox" id="plan-startup" name="plans" value="startup" class="mt-0.5 size-4 shrink-0 rounded border-neutral-300 text-neutral-900 focus:ring-neutral-500 focus:ring-offset-0 dark:border-neutral-600 dark:bg-neutral-800 dark:text-neutral-100 dark:focus:ring-neutral-400 dark:checked:bg-neutral-600 dark:checked:border-neutral-500">
    <div class="min-w-0 flex-1">
      <div class="flex items-start justify-between gap-3">
        <div class="flex flex-col gap-1">
          <h3 class="text-sm font-semibold text-neutral-900 dark:text-neutral-100">Add-on 1</h3>
          <p class="text-xs text-neutral-500 dark:text-neutral-400">$39 / month</p>
        </div>
        <span class="text-sm font-medium text-neutral-900 dark:text-neutral-100">$468 / year</span>
      </div>
    </div>
  </label>

  <label for="plan-pro" class="py-3 px-4 flex items-start gap-3 font-medium bg-white text-neutral-800 rounded-xl cursor-pointer ring-1 ring-neutral-200 has-[:checked]:ring-2 has-[:checked]:ring-neutral-400 dark:bg-neutral-700/50 dark:text-neutral-200 dark:ring-neutral-700 dark:has-[:checked]:ring-neutral-400 has-[:checked]:bg-neutral-100 has-[:checked]:text-neutral-900 dark:has-[:checked]:bg-neutral-600/60 dark:has-[:checked]:text-white">
    <input type="checkbox" id="plan-pro" name="plans" value="pro" class="mt-0.5 size-4 shrink-0 rounded border-neutral-300 text-neutral-900 focus:ring-neutral-500 focus:ring-offset-0 dark:border-neutral-600 dark:bg-neutral-800 dark:text-neutral-100 dark:focus:ring-neutral-400 dark:checked:bg-neutral-600 dark:checked:border-neutral-500" checked>
    <div class="min-w-0 flex-1">
      <div class="flex items-start justify-between gap-3">
        <div class="flex flex-col gap-1">
          <h3 class="text-sm font-semibold text-neutral-900 dark:text-neutral-100">Add-on 2</h3>
          <p class="text-xs text-neutral-500 dark:text-neutral-400">$69 / month</p>
        </div>
        <span class="text-sm font-medium text-neutral-900 dark:text-neutral-100">$828 / year</span>
      </div>
    </div>
  </label>

  <label for="plan-enterprise" class="py-3 px-4 flex items-start gap-3 font-medium bg-white text-neutral-800 rounded-xl cursor-pointer ring-1 ring-neutral-200 has-[:checked]:ring-2 has-[:checked]:ring-neutral-400 dark:bg-neutral-700/50 dark:text-neutral-200 dark:ring-neutral-700 dark:has-[:checked]:ring-neutral-400 has-[:checked]:bg-neutral-100 has-[:checked]:text-neutral-900 dark:has-[:checked]:bg-neutral-600/60 dark:has-[:checked]:text-white">
    <input type="checkbox" id="plan-enterprise" name="plans" value="enterprise" class="mt-0.5 size-4 shrink-0 rounded border-neutral-300 text-neutral-900 focus:ring-neutral-500 focus:ring-offset-0 dark:border-neutral-600 dark:bg-neutral-800 dark:text-neutral-100 dark:focus:ring-neutral-400 dark:checked:bg-neutral-600 dark:checked:border-neutral-500">
    <div class="min-w-0 flex-1">
      <div class="flex items-start justify-between gap-3">
        <div class="flex flex-col gap-1">
          <h3 class="text-sm font-semibold text-neutral-900 dark:text-neutral-100">Add-on 3</h3>
          <p class="text-xs text-neutral-500 dark:text-neutral-400">$129 / month</p>
        </div>
        <span class="text-sm font-medium text-neutral-900 dark:text-neutral-100">$1,548 / year</span>
      </div>
    </div>
  </label>
</fieldset>

Custom Checkboxes

Custom checkbox layout with a custom icon. This can for example be used for filters

<fieldset class="flex w-full max-w-md flex-wrap gap-2">
  <!-- Checkbox -->
  <label for="option-1" class="relative py-2 px-2.5 flex items-center font-medium bg-white text-neutral-800 rounded-xl cursor-pointer ring-1 ring-neutral-200 has-[:checked]:ring-2 has-[:checked]:ring-neutral-400 dark:bg-neutral-700/50 dark:text-neutral-200 dark:ring-neutral-700 dark:has-[:checked]:ring-neutral-400 has-[:checked]:bg-neutral-100 has-[:checked]:text-neutral-900 dark:has-[:checked]:bg-neutral-600/60 dark:has-[:checked]:text-white">
    <input type="checkbox" id="option-1" class="peer hidden" name="options" />
    <span class="flex size-0 shrink-0 items-center justify-center rounded-full bg-neutral-700 text-transparent transition-all duration-200 peer-checked:me-1.5 peer-checked:size-4 peer-checked:text-white dark:bg-neutral-50 dark:peer-checked:text-neutral-800">
      <svg xmlns="http://www.w3.org/2000/svg" class="size-2.5 shrink-0" width="12" height="12" viewBox="0 0 12 12"><g fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.8" stroke="currentColor"><path d="m1.75,6c1.047,1.048,1.803,2.153,2.461,3.579,1.524-3.076,3.659-5.397,6.039-7.158"></path></g></svg>
    </span>
    <span class="block"> Option 1 </span>
  </label>
  <!-- End Checkbox -->

  <!-- Checkbox -->
  <label for="option-2" class="relative py-2 px-2.5 flex items-center font-medium bg-white text-neutral-800 rounded-xl cursor-pointer ring-1 ring-neutral-200 has-[:checked]:ring-2 has-[:checked]:ring-neutral-400 dark:bg-neutral-700/50 dark:text-neutral-200 dark:ring-neutral-700 dark:has-[:checked]:ring-neutral-400 has-[:checked]:bg-neutral-100 has-[:checked]:text-neutral-900 dark:has-[:checked]:bg-neutral-600/60 dark:has-[:checked]:text-white">
    <input type="checkbox" id="option-2" class="peer hidden" name="options" />
    <span class="flex size-0 shrink-0 items-center justify-center rounded-full bg-neutral-700 text-transparent transition-all duration-200 peer-checked:me-1.5 peer-checked:size-4 peer-checked:text-white dark:bg-neutral-50 dark:peer-checked:text-neutral-800">
      <svg xmlns="http://www.w3.org/2000/svg" class="size-2.5 shrink-0" width="12" height="12" viewBox="0 0 12 12"><g fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.8" stroke="currentColor"><path d="m1.75,6c1.047,1.048,1.803,2.153,2.461,3.579,1.524-3.076,3.659-5.397,6.039-7.158"></path></g></svg>
    </span>
    <span class="block"> Option 2 </span>
  </label>
  <!-- End Checkbox -->

  <!-- Checkbox -->
  <label for="option-3" class="relative py-2 px-2.5 flex items-center font-medium bg-white text-neutral-800 rounded-xl cursor-pointer ring-1 ring-neutral-200 has-[:checked]:ring-2 has-[:checked]:ring-neutral-400 dark:bg-neutral-700/50 dark:text-neutral-200 dark:ring-neutral-700 dark:has-[:checked]:ring-neutral-400 has-[:checked]:bg-neutral-100 has-[:checked]:text-neutral-900 dark:has-[:checked]:bg-neutral-600/60 dark:has-[:checked]:text-white">
    <input type="checkbox" id="option-3" class="peer hidden" name="options" />
    <span class="flex size-0 shrink-0 items-center justify-center rounded-full bg-neutral-700 text-transparent transition-all duration-200 peer-checked:me-1.5 peer-checked:size-4 peer-checked:text-white dark:bg-neutral-50 dark:peer-checked:text-neutral-800">
      <svg xmlns="http://www.w3.org/2000/svg" class="size-2.5 shrink-0" width="12" height="12" viewBox="0 0 12 12"><g fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.8" stroke="currentColor"><path d="m1.75,6c1.047,1.048,1.803,2.153,2.461,3.579,1.524-3.076,3.659-5.397,6.039-7.158"></path></g></svg>
    </span>
    <span class="block"> Option 3 </span>
  </label>
  <!-- End Checkbox -->

  <!-- Checkbox -->
  <label for="option-4" class="relative py-2 px-2.5 flex items-center font-medium bg-white text-neutral-800 rounded-xl cursor-pointer ring-1 ring-neutral-200 has-[:checked]:ring-2 has-[:checked]:ring-neutral-400 dark:bg-neutral-700/50 dark:text-neutral-200 dark:ring-neutral-700 dark:has-[:checked]:ring-neutral-400 has-[:checked]:bg-neutral-100 has-[:checked]:text-neutral-900 dark:has-[:checked]:bg-neutral-600/60 dark:has-[:checked]:text-white">
    <input type="checkbox" id="option-4" class="peer hidden" name="options" />
    <span class="flex size-0 shrink-0 items-center justify-center rounded-full bg-neutral-700 text-transparent transition-all duration-200 peer-checked:me-1.5 peer-checked:size-4 peer-checked:text-white dark:bg-neutral-50 dark:peer-checked:text-neutral-800">
      <svg xmlns="http://www.w3.org/2000/svg" class="size-2.5 shrink-0" width="12" height="12" viewBox="0 0 12 12"><g fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.8" stroke="currentColor"><path d="m1.75,6c1.047,1.048,1.803,2.153,2.461,3.579,1.524-3.076,3.659-5.397,6.039-7.158"></path></g></svg>
    </span>
    <span class="block"> Option 4 </span>
  </label>
  <!-- End Checkbox -->

  <!-- Checkbox -->
  <label for="option-5" class="relative py-2 px-2.5 flex items-center font-medium bg-white text-neutral-800 rounded-xl cursor-pointer ring-1 ring-neutral-200 has-[:checked]:ring-2 has-[:checked]:ring-neutral-400 dark:bg-neutral-700/50 dark:text-neutral-200 dark:ring-neutral-700 dark:has-[:checked]:ring-neutral-400 has-[:checked]:bg-neutral-100 has-[:checked]:text-neutral-900 dark:has-[:checked]:bg-neutral-600/60 dark:has-[:checked]:text-white">
    <input type="checkbox" id="option-5" class="peer hidden" name="options" />
    <span class="flex size-0 shrink-0 items-center justify-center rounded-full bg-neutral-700 text-transparent transition-all duration-200 peer-checked:me-1.5 peer-checked:size-4 peer-checked:text-white dark:bg-neutral-50 dark:peer-checked:text-neutral-800">
      <svg xmlns="http://www.w3.org/2000/svg" class="size-2.5 shrink-0" width="12" height="12" viewBox="0 0 12 12"><g fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.8" stroke="currentColor"><path d="m1.75,6c1.047,1.048,1.803,2.153,2.461,3.579,1.524-3.076,3.659-5.397,6.039-7.158"></path></g></svg>
    </span>
    <span class="block"> Option 5 </span>
  </label>
  <!-- End Checkbox -->

  <!-- Checkbox -->
  <label for="option-6" class="relative py-2 px-2.5 flex items-center font-medium bg-white text-neutral-800 rounded-xl cursor-pointer ring-1 ring-neutral-200 has-[:checked]:ring-2 has-[:checked]:ring-neutral-400 dark:bg-neutral-700/50 dark:text-neutral-200 dark:ring-neutral-700 dark:has-[:checked]:ring-neutral-400 has-[:checked]:bg-neutral-100 has-[:checked]:text-neutral-900 dark:has-[:checked]:bg-neutral-600/60 dark:has-[:checked]:text-white">
    <input type="checkbox" id="option-6" class="peer hidden" name="options" />
    <span class="flex size-0 shrink-0 items-center justify-center rounded-full bg-neutral-700 text-transparent transition-all duration-200 peer-checked:me-1.5 peer-checked:size-4 peer-checked:text-white dark:bg-neutral-50 dark:peer-checked:text-neutral-800">
      <svg xmlns="http://www.w3.org/2000/svg" class="size-2.5 shrink-0" width="12" height="12" viewBox="0 0 12 12"><g fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.8" stroke="currentColor"><path d="m1.75,6c1.047,1.048,1.803,2.153,2.461,3.579,1.524-3.076,3.659-5.397,6.039-7.158"></path></g></svg>
    </span>
    <span class="block"> Option 6 </span>
  </label>
  <!-- End Checkbox -->

  <!-- Checkbox -->
  <label for="option-7" class="relative py-2 px-2.5 flex items-center font-medium bg-white text-neutral-800 rounded-xl cursor-pointer ring-1 ring-neutral-200 has-[:checked]:ring-2 has-[:checked]:ring-neutral-400 dark:bg-neutral-700/50 dark:text-neutral-200 dark:ring-neutral-700 dark:has-[:checked]:ring-neutral-400 has-[:checked]:bg-neutral-100 has-[:checked]:text-neutral-900 dark:has-[:checked]:bg-neutral-600/60 dark:has-[:checked]:text-white">
    <input type="checkbox" id="option-7" class="peer hidden" name="options" />
    <span class="flex size-0 shrink-0 items-center justify-center rounded-full bg-neutral-700 text-transparent transition-all duration-200 peer-checked:me-1.5 peer-checked:size-4 peer-checked:text-white dark:bg-neutral-50 dark:peer-checked:text-neutral-800">
      <svg xmlns="http://www.w3.org/2000/svg" class="size-2.5 shrink-0" width="12" height="12" viewBox="0 0 12 12"><g fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.8" stroke="currentColor"><path d="m1.75,6c1.047,1.048,1.803,2.153,2.461,3.579,1.524-3.076,3.659-5.397,6.039-7.158"></path></g></svg>
    </span>
    <span class="block"> Option 7 </span>
  </label>
  <!-- End Checkbox -->

  <!-- Checkbox -->
  <label for="option-8" class="relative py-2 px-2.5 flex items-center font-medium bg-white text-neutral-800 rounded-xl cursor-pointer ring-1 ring-neutral-200 has-[:checked]:ring-2 has-[:checked]:ring-neutral-400 dark:bg-neutral-700/50 dark:text-neutral-200 dark:ring-neutral-700 dark:has-[:checked]:ring-neutral-400 has-[:checked]:bg-neutral-100 has-[:checked]:text-neutral-900 dark:has-[:checked]:bg-neutral-600/60 dark:has-[:checked]:text-white">
    <input type="checkbox" id="option-8" class="peer hidden" name="options" />
    <span class="flex size-0 shrink-0 items-center justify-center rounded-full bg-neutral-700 text-transparent transition-all duration-200 peer-checked:me-1.5 peer-checked:size-4 peer-checked:text-white dark:bg-neutral-50 dark:peer-checked:text-neutral-800">
      <svg xmlns="http://www.w3.org/2000/svg" class="size-2.5 shrink-0" width="12" height="12" viewBox="0 0 12 12"><g fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.8" stroke="currentColor"><path d="m1.75,6c1.047,1.048,1.803,2.153,2.461,3.579,1.524-3.076,3.659-5.397,6.039-7.158"></path></g></svg>
    </span>
    <span class="block"> Option 8 </span>
  </label>
  <!-- End Checkbox -->
</fieldset>

Table of contents

Powered by

Get notified when new components come out