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
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
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.