Episode 13 of 19

Buttons

Build a complete button system with Tailwind CSS. Learn primary, secondary, outline, ghost, and icon button styles with sizes, loading states, groups, and disabled styles.

Building Buttons

Buttons are fundamental UI elements. In Tailwind, there is no .btn class built in — you compose buttons from utility classes, giving you full control over every aspect of the design.

Basic Button

<button class="bg-indigo-600 text-white font-semibold py-2 px-4 rounded-lg hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2">
  Click Me
</button>

Let us break down the key utilities:

  • bg-indigo-600 + text-white — Primary color scheme
  • font-semibold — Medium-bold text weight
  • py-2 px-4 — Vertical and horizontal padding
  • rounded-lg — Rounded corners
  • hover:bg-indigo-700 — Darker on hover
  • focus:ring-2 — Accessibility focus ring

Button Variants

Primary

<button class="bg-indigo-600 text-white font-semibold py-2.5 px-5 rounded-lg hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 transition-colors">
  Primary Button
</button>

Secondary

<button class="bg-gray-100 text-gray-800 font-semibold py-2.5 px-5 rounded-lg hover:bg-gray-200 focus:outline-none focus:ring-2 focus:ring-gray-400 focus:ring-offset-2 transition-colors">
  Secondary Button
</button>

Outline

<button class="border-2 border-indigo-600 text-indigo-600 font-semibold py-2.5 px-5 rounded-lg hover:bg-indigo-600 hover:text-white focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 transition-colors">
  Outline Button
</button>

Ghost

<button class="text-indigo-600 font-semibold py-2.5 px-5 rounded-lg hover:bg-indigo-50 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 transition-colors">
  Ghost Button
</button>

Danger

<button class="bg-red-600 text-white font-semibold py-2.5 px-5 rounded-lg hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-red-500 focus:ring-offset-2 transition-colors">
  Delete
</button>

Button Sizes

<!-- Extra Small -->
<button class="bg-indigo-600 text-white text-xs font-semibold py-1 px-2.5 rounded">
  XS Button
</button>

<!-- Small -->
<button class="bg-indigo-600 text-white text-sm font-semibold py-1.5 px-3 rounded-md">
  Small Button
</button>

<!-- Medium (default) -->
<button class="bg-indigo-600 text-white text-sm font-semibold py-2.5 px-5 rounded-lg">
  Medium Button
</button>

<!-- Large -->
<button class="bg-indigo-600 text-white text-base font-semibold py-3 px-6 rounded-lg">
  Large Button
</button>

<!-- Full Width -->
<button class="bg-indigo-600 text-white text-base font-semibold py-3 px-6 rounded-lg w-full">
  Full Width Button
</button>

Disabled State

<button disabled class="bg-indigo-600 text-white font-semibold py-2.5 px-5 rounded-lg disabled:opacity-50 disabled:cursor-not-allowed">
  Disabled Button
</button>

The disabled: prefix applies styles only when the button has the disabled attribute. opacity-50 makes it look faded and cursor-not-allowed shows a blocked cursor.

Loading State

<button class="bg-indigo-600 text-white font-semibold py-2.5 px-5 rounded-lg inline-flex items-center" disabled>
  <svg class="animate-spin -ml-1 mr-2 h-4 w-4 text-white" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
    <circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
    <path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"></path>
  </svg>
  Processing...
</button>

animate-spin adds a continuous rotation animation to the spinner SVG.

Icon Buttons

<!-- Icon + Text -->
<button class="bg-indigo-600 text-white font-semibold py-2.5 px-5 rounded-lg inline-flex items-center gap-2 hover:bg-indigo-700 transition-colors">
  <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
    <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4"></path>
  </svg>
  Add Item
</button>

<!-- Icon Only (square) -->
<button class="bg-gray-100 text-gray-700 p-2.5 rounded-lg hover:bg-gray-200 transition-colors">
  <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
    <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16m-7 6h7"></path>
  </svg>
</button>

<!-- Icon Only (circular) -->
<button class="bg-indigo-600 text-white p-3 rounded-full hover:bg-indigo-700 transition-colors">
  <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
    <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4"></path>
  </svg>
</button>

Button Groups

<div class="inline-flex rounded-lg shadow-sm">
  <button class="bg-white text-gray-700 font-medium py-2 px-4 rounded-l-lg border border-gray-300 hover:bg-gray-50">
    Previous
  </button>
  <button class="bg-white text-gray-700 font-medium py-2 px-4 border-t border-b border-gray-300 hover:bg-gray-50">
    Current
  </button>
  <button class="bg-white text-gray-700 font-medium py-2 px-4 rounded-r-lg border border-gray-300 hover:bg-gray-50">
    Next
  </button>
</div>

The first button gets rounded-l-lg (left corners), the last gets rounded-r-lg (right corners), and middle buttons have no side rounding.

Practical Example — Button Toolbar

<div class="flex flex-wrap items-center gap-3 p-6 bg-gray-50">
  <button class="bg-indigo-600 text-white font-semibold py-2.5 px-5 rounded-lg hover:bg-indigo-700 transition-colors">
    Save Changes
  </button>
  <button class="bg-white text-gray-700 font-semibold py-2.5 px-5 rounded-lg border border-gray-300 hover:bg-gray-50 transition-colors">
    Cancel
  </button>
  <button class="text-red-600 font-semibold py-2.5 px-5 rounded-lg hover:bg-red-50 transition-colors ml-auto">
    Delete Item
  </button>
</div>

Recap

  • Tailwind buttons are composed from background, text, padding, rounded, and hover/focus utilities.
  • Create variants (primary, outline, ghost, danger) by swapping color utilities.
  • Control size with padding and text-size classes.
  • disabled: prefix handles disabled states; animate-spin creates loading spinners.
  • Button groups use selective border-radius on first and last children.

Next, we will learn how to add icons to our Tailwind projects.

Web DevelopmentTailwind CSSCSSComponentsButtons