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 schemefont-semibold— Medium-bold text weightpy-2 px-4— Vertical and horizontal paddingrounded-lg— Rounded cornershover:bg-indigo-700— Darker on hoverfocus: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-spincreates 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.