Start with a native button and a clear action. Utility classes style it; they do not supply a name, disabled behavior or a click handler.

Version and setup

These examples are compiled with Tailwind CSS 3.3.2. Copy document includes the required CSS, so that document runs without a Tailwind installation. To use the utility classes in a project, follow the versioned setup guide.

This site customizes its spacing scale: p-10 is 10px here, while standard Tailwind 3 uses 2.5rem. The examples below use unaffected spacing keys or explicit arbitrary values. Check your project configuration before assuming a utility’s size. Tailwind 4 has a different setup; use its official installation guide for a new version-4 project.

A working action

Count button activationsLink

Tailwind CSS 3.3.2; the CSS tab includes the compiled styles.

HTML

<button
  type="button"
  class="px-4 py-3 font-semibold text-white bg-blue-700 rounded hover:bg-blue-800 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2"
>
  Add one
</button>
<p class="mt-4" role="status">Count: <output>0</output></p>
<script>
  let count = 0; document.querySelector("button").addEventListener("click", () => { document.querySelector("output").value = String(++count); });
</script>

CSS

*,
::before,
::after {
  box-sizing: border-box;
  border: 0 solid #e5e7eb;
}
h1,
h2,
h3,
h4,
h5,
h6,
p,
figure,
blockquote,
dl,
dd {
  margin: 0;
}
h1,
h2,
h3,
h4,
h5,
h6 {
  font-size: inherit;
  font-weight: inherit;
}
button,
input,
select,
textarea {
  font: inherit;
  color: inherit;
}
button {
  background: none;
}
img,
svg,
video {
  display: block;
  max-width: 100%;
}
img,
video {
  height: auto;
}
a {
  color: inherit;
  text-decoration: inherit;
}
ol,
ul,
menu {
  list-style: none;
  margin: 0;
  padding: 0;
}
.mt-4 {
  margin-top: 1rem;
}
.rounded {
  border-radius: 0.25rem;
}
.bg-blue-700 {
  --tw-bg-opacity: 1;
  background-color: rgb(29 78 216 / var(--tw-bg-opacity));
}
.px-4 {
  padding-left: 1rem;
  padding-right: 1rem;
}
.py-3 {
  padding-top: 0.75rem;
  padding-bottom: 0.75rem;
}
.font-semibold {
  font-weight: 600;
}
.text-white {
  --tw-text-opacity: 1;
  color: rgb(255 255 255 / var(--tw-text-opacity));
}
.hover\:bg-blue-800:hover {
  --tw-bg-opacity: 1;
  background-color: rgb(30 64 175 / var(--tw-bg-opacity));
}
.focus-visible\:outline:focus-visible {
  outline-style: solid;
}
.focus-visible\:outline-2:focus-visible {
  outline-width: 2px;
}
.focus-visible\:outline-offset-2:focus-visible {
  outline-offset: 2px;
}

Edit HTML or CSS to update the preview as you type. Copy code snippet copies the selected tab. Preview spacing and font defaults are not included.

Tab to the button and press Space or Enter. The count changes, and the focus outline stays visible. px-4 and py-3 add horizontal and vertical padding; the darker blue keeps white text readable.

An actual disabled state

Compare enabled and disabled controlsLink

Tailwind CSS 3.3.2; the CSS tab includes the compiled styles.

HTML

<button
  type="button"
  disabled
  class="px-4 py-3 text-white bg-blue-700 rounded opacity-60 cursor-not-allowed"
>
  Save unavailable
</button>
<p class="mt-4">Complete the required fields before saving.</p>

CSS

*,
::before,
::after {
  box-sizing: border-box;
  border: 0 solid #e5e7eb;
}
h1,
h2,
h3,
h4,
h5,
h6,
p,
figure,
blockquote,
dl,
dd {
  margin: 0;
}
h1,
h2,
h3,
h4,
h5,
h6 {
  font-size: inherit;
  font-weight: inherit;
}
button,
input,
select,
textarea {
  font: inherit;
  color: inherit;
}
button {
  background: none;
}
img,
svg,
video {
  display: block;
  max-width: 100%;
}
img,
video {
  height: auto;
}
a {
  color: inherit;
  text-decoration: inherit;
}
ol,
ul,
menu {
  list-style: none;
  margin: 0;
  padding: 0;
}
.mt-4 {
  margin-top: 1rem;
}
.cursor-not-allowed {
  cursor: not-allowed;
}
.rounded {
  border-radius: 0.25rem;
}
.bg-blue-700 {
  --tw-bg-opacity: 1;
  background-color: rgb(29 78 216 / var(--tw-bg-opacity));
}
.px-4 {
  padding-left: 1rem;
  padding-right: 1rem;
}
.py-3 {
  padding-top: 0.75rem;
  padding-bottom: 0.75rem;
}
.text-white {
  --tw-text-opacity: 1;
  color: rgb(255 255 255 / var(--tw-text-opacity));
}
.opacity-60 {
  opacity: 0.6;
}

Edit HTML or CSS to update the preview as you type. Copy code snippet copies the selected tab. Preview spacing and font defaults are not included.

The HTML disabled attribute prevents activation. Opacity and a cursor merely describe appearance; by themselves they do not disable a button. Explain why the action is unavailable in ordinary text.

Choose the right element

Use a link for navigation and a button for an action. Include type="button" when the control must not submit an enclosing form. An icon-only control needs an accessible name. See the native button lesson for those semantics.

Sources

Reference 1 Reference 2 Reference 3 provide the technical details and current compatibility information.