Pure CSS toggle switch

There’s no need to use a library to implement a nice toggle for your project. This can be done with pure CSS and completely zero JavaScript.

There is a nice codepen implemented by Marcus Burnette, which involves using a :checked pseudo-class selector on the <input type="checkbox" />. Let’s see how it’s done exactly.

The markup

We are using a checkbox input with a label after it, and the label is assigned to the input with for="id" attribute. We will also prefix all the toggles with a <span> just to make sure the usual <input type="checkbox" /> is still styled as usual.

<span class="csstoggle">
  <input type="checkbox" id="switch" /><label for="switch">Toggle</label>

Let’s add the basic styles to hide the checkbox, and style the label as a horizontal toggle with a circle inside. I’ve also added a common display: inline-flex for the toggle to position nicely among other elements on the page.

.csstoggle {
	display: inline-flex;

.csstoggle input[type=checkbox]{
	height: 0;
	width: 0;
	visibility: hidden;

.csstoggle label {
	cursor: pointer;
	text-indent: -9999px;
	width: 60px;
	height: 30px;
	background: #444;
	display: block;
	border-radius: 30px;
	position: relative;
	border: 1px solid black;

.csstoggle label:after {
	content: '';
	position: absolute;
	top: 5px;
	left: 5px;
	width: 20px;
	height: 20px;
	background: #fff;
	border-radius: 20px;
	transition: 0.3s;

You should get something like this as a result:

If you click the toggle at this moment – you won’t see anything, although the <input> will change it’s checked attribute. Let’s add three more things: change the toggle background when it’s checked, move the circle to the right, and add a slight width-changing effect on the circle:

.csstoggle input:checked + label {
	background: #bada55;
	border: 1px solid #97b832;

.csstoggle input:checked + label:after {
	left: calc(100% - 5px);
	transform: translateX(-100%);

.csstoggle label:active:after {
	width: 30px;

And the result is this:

Leave a Comment

Your email address will not be published. Required fields are marked *