November 16, 2018
Custom checkbox with only CSS and HTML tutorial

HTML checkbox sucks! Doesn’t it? Okay, your tastes might be different. For us, it does. Whatever, we prefer something more stylish matching the project theme.

Let us show you the code first and explain, then.

For instance, we need a BIG checkbox; that too… gradient background.

Here you go.

The idea

Use pseudo classes (:checked, :before and :after) to create a checkbox and a check mark. Then, hide the actual checkbox.

The code

See the Pen custom checkbox with css and html by Tech (@tntux) on CodePen.

Code explained


<input type="checkbox" id="check" /> <label for="check"></label>

Nothing tricky here, in fact. As in a normal form, we used a checkbox-type-input with an id of ‘check’, followed by a label with for=“check” (id of the checkbox). The for=“check” attribute of this label helps simulate checkbox clicks {{ read-mode }}. And no text for the label; the element is enough.


In fact, CSS is the lead player in this. Nothing confusing. A piece of cake!

Step 1:

Usually, HTML constructs the elements to show and CSS styles them. In here, we do not intend to display any HTML elements at all; instead, we hide HTML with CSS and constructs new pseudo elements for display purpose.

So, our first step is to hide the input element.

#check {
  opacity: 0;

Hide the checkbox element, first. Some people do this another way, by applying display: none;. This restricts keyboard access to the element (by using tab key) thus accessibility is at risk.

Step 2:

label {
  position: relative;

Since we use the pseudo elements (:before and :after, here) {{ read-more }}, this section of CSS shouldn’t be avoided. The position: relative; for parent, and position: absolute; for child/pseudo together does the positioning trick {{ read-modre }}.

Step 3:

#check + label:before,
#check:checked + label:after {
  content: "";
  position: absolute;
  left: -15px;
  top: 0;

This is where we start making our actual view. #check + label:before and #check:checked + label:after points to :before and :after pseudo elements of the label preceded by the element with id="check".

Did you note :checked pseudo class? This means, the :after pseudo element will be there if and only if the checkbox is checked; if unchecked, this element won’t be there at all.

This content: ”” (or sometimes, content: “<some text>”) is very important for any :before or :after element, else it won’t be displayed correctly.

Again, position absolute; this helps position our pseudo element with respect to the immediate parent with position: relative;. In our case, the #check element. Remember, if it can’t find any parent with position: relative, the element will be positioned according to the <body>.

Left: -15px position the pseudo element at the left most position of the #check. Likewise the top: 0 too.

Step 4:

Creating the checkbox.

#check + label:before {
  width: 80px;
  height: 80px;
  background-image: linear-gradient(to bottom, #2129a5 0%, #5d28ef 100%);
  border-radius: 10px;

This part is entirely up to you. You can determine whatever size, colour and other styles of the checkbox. You can make bigger buttons, or may be small ones, different background image or fill, border etc. etc. You decide.

Step 5:

And the final part, the check mark.

#check:checked + label:after {
  width: 60px;
  height: 20px;
  border-width: 0 0 10px 10px;
  border-style: solid;
  border-color: #fff;
  transform: rotate(-45deg) translate(-10px, 20px);

The check mark is shown only when the checkbox element has :checked state, as we said earlier (that’s what the :checked member does), whereas, the :before element will always be displayed irrespective of the checkbox state.

Making a check mark is very easy. You define a rectangle without top and right borders, then rotate it a bit. This translate(-10px, 20px) positions the tick mark in the desired position. This may change according to the size and other properties of the checkbox (:before element, here.)

When you click the pseudo element of the label, it activates the real checkbox.

That’s all.

Congratulations! You have made a stylish checkbox on your own.

comments powered by Disqus