How to a build custom checkbox in TailwindCSS

Let’s start with the basic one. Let's create a basic HTML input with the type checkbox and label element. I’ve added ID to in the input tag and for attributes in the label. Whenever I clicked the label, it will auto-select the input.

Final design

TailwindCSS is getting hype lately. It was a fresh CSS framework that really helps the developer to write a fast and maintainable CSS design.

Let me explain step by step how to make it works.

Create an input

Let’s start with the basic one. Let's create a basic HTML input with the type checkbox and label element. I’ve added ID to in the input tag and for attributes in the label. Whenever I clicked the label, it will auto-select the input.

<div class="p-4">
  <div class="flex items-center mr-4 mb-2">
	<input type="checkbox" id="A3-yes" name="A3-confirmation" value="yes" />
	<label for="A3-yes" class="select-none">Yes</label>
  </div>
</div>
I added some spacing to make it looks better.

Hide our input tag

Let’s hide our input tag since we’re gonna use a custom design for it. Let set the size for the input too. Although the input doesn't visible on the screen we still able to click it since it’s still render in the DOM.

<input type="checkbox" id="A3-yes" name="A3-confirmation" value="yes" class="opacity-0 absolute h-8 w-8" />


Create custom design

I want the design to have a bordered rectangle with a SVG icon inside it. Make sure to set the element size the same with the input tag as the previous step. We want the custom input to have the same position as our original input.

And set the SVG icon hidden as default. We want to show it, whenever the input is checked.

	<div class="bg-white border-2 rounded-md border-blue-400 w-8 h-8 flex flex-shrink-0 justify-center items-center mr-2 focus-within:border-blue-500">
	  <svg class="fill-current hidden w-3 h-3 text-blue-600 pointer-events-none" version="1.1" viewBox="0 0 17 12" xmlns="http://www.w3.org/2000/svg">
		<g fill="none" fill-rule="evenodd">
		  <g transform="translate(-9 -11)" fill="#1F73F1" fill-rule="nonzero">
			<path d="m25.576 11.414c0.56558 0.55188 0.56558 1.4439 0 1.9961l-9.404 9.176c-0.28213 0.27529-0.65247 0.41385-1.0228 0.41385-0.37034 0-0.74068-0.13855-1.0228-0.41385l-4.7019-4.588c-0.56584-0.55188-0.56584-1.4442 0-1.9961 0.56558-0.55214 1.4798-0.55214 2.0456 0l3.679 3.5899 8.3812-8.1779c0.56558-0.55214 1.4798-0.55214 2.0456 0z" />
		  </g>
		</g>
	  </svg>
	</div>

Checkbox Conditional

Let’s show the icon whenever the input is checked. We can handle it using CSS siblings. Lets put the element side by side. The final HTML output would be like this.

<div class="p-4">
  <div class="flex items-center mr-4 mb-2">
	<input type="checkbox" id="A3-yes" name="A3-confirmation" value="yes" class="opacity-0 absolute h-8 w-8" />
	<div class="bg-white border-2 rounded-md border-blue-400 w-8 h-8 flex flex-shrink-0 justify-center items-center mr-2 focus-within:border-blue-500">
	  <svg class="fill-current hidden w-3 h-3 text-blue-600 pointer-events-none" version="1.1" viewBox="0 0 17 12" xmlns="http://www.w3.org/2000/svg">
		<g fill="none" fill-rule="evenodd">
		  <g transform="translate(-9 -11)" fill="#1F73F1" fill-rule="nonzero">
			<path d="m25.576 11.414c0.56558 0.55188 0.56558 1.4439 0 1.9961l-9.404 9.176c-0.28213 0.27529-0.65247 0.41385-1.0228 0.41385-0.37034 0-0.74068-0.13855-1.0228-0.41385l-4.7019-4.588c-0.56584-0.55188-0.56584-1.4442 0-1.9961 0.56558-0.55214 1.4798-0.55214 2.0456 0l3.679 3.5899 8.3812-8.1779c0.56558-0.55214 1.4798-0.55214 2.0456 0z" />
		  </g>
		</g>
	  </svg>
	</div>
	<label for="A3-yes" class="select-none">Yes</label>
  </div>
</div>

Whenever the input was checked, it will changed the border color of the input and show the SVG icon (as a block).

input:checked + div {
  @apply border-blue-500;
}
input:checked + div svg {
  @apply block;
}
I used the tailwind @apply function here

Unfortunately, we still need to write a little bit if CSS to handle sibling selectors for checked attributes. If you still wanna use TailwindCSS, feel free to explore Tailwind variant on how to solve it - https://tailwindcss.com/docs/plugins#complex-variants

Congratulations, now it’s done. Feel free to play around with it at - https://play.tailwindcss.com/2tdJjb6CbD

Source Code

HTML

<div class="p-4">
  <div class="flex items-center mr-4 mb-2">
	<input type="checkbox" id="A3-yes" name="A3-confirmation" value="yes" class="opacity-0 absolute h-8 w-8" />
	<div class="bg-white border-2 rounded-md border-blue-400 w-8 h-8 flex flex-shrink-0 justify-center items-center mr-2 focus-within:border-blue-500">
	  <svg class="fill-current hidden w-3 h-3 text-blue-600 pointer-events-none" version="1.1" viewBox="0 0 17 12" xmlns="http://www.w3.org/2000/svg">
		<g fill="none" fill-rule="evenodd">
		  <g transform="translate(-9 -11)" fill="#1F73F1" fill-rule="nonzero">
			<path d="m25.576 11.414c0.56558 0.55188 0.56558 1.4439 0 1.9961l-9.404 9.176c-0.28213 0.27529-0.65247 0.41385-1.0228 0.41385-0.37034 0-0.74068-0.13855-1.0228-0.41385l-4.7019-4.588c-0.56584-0.55188-0.56584-1.4442 0-1.9961 0.56558-0.55214 1.4798-0.55214 2.0456 0l3.679 3.5899 8.3812-8.1779c0.56558-0.55214 1.4798-0.55214 2.0456 0z" />
		  </g>
		</g>
	  </svg>
	</div>
	<label for="A3-yes" class="select-none">Yes</label>
  </div>
</div>
HTML template

CSS

@tailwind base;
@tailwind components;
@tailwind utilities;

input:checked + div {
  @apply border-blue-500;
}
input:checked + div svg {
  @apply block;
}
CSS template

I send out my writing and ideas every week to my mailing list

Great! Check your inbox and click the link to confirm your subscription
Please enter a valid email address!