Advertisement
Site Elements

Creating a JavaScript-Free Radio Toggle in CSS3

by

You'll often find yourself using toggle sliders as a trendy alternative to checkboxes. Today we'll be creating one using plain CSS3 and HTML.


Step 1: Begin With the Markup

Create a new HTML document and add a span tag with a class of toggle-bg. This will be the background area for the toggle.

<!DOCTYPE html>
<!--[if lt IE 7 ]><html class="ie ie6" lang="en"> <![endif]-->
<!--[if IE 7 ]><html class="ie ie7" lang="en"> <![endif]-->
<!--[if IE 8 ]><html class="ie ie8" lang="en"> <![endif]-->
<!--[if (gte IE 9)|!(IE)]><!--><html lang="en"> <!--<![endif]-->
<head>

	<meta charset="utf-8">
	<title></title>
	<meta name="description" content="">
	<meta name="author" content="">

	<!-- Don't Forget the Viewport Metatag http://enva.to/A79s3G -->
	<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">

	<!-- CSS -->
	<link rel="stylesheet" href="your_stylesheet.css">

</head>
<body>

	<span class="toggle-bg"></span>

</body>
</html>

Step 2: Semantics and Functionality

To make the toggle functional, we'll be using some invisible radio inputs. These have just a couple of requirements:

  • They must have different values
  • They must have the same name

I'll be using on and off as my values, with a name of toggle, but you may change this depending on your usage. For example, maybe you'll be toggling between yes and no.

Add the input to the span you created earlier. Your code should look like this:

<span class="toggle-bg">
	<input type="radio" name="toggle" value="off">
	<input type="radio" name="toggle" value="on"> 
</span>

Depending on your own usage, you may also want to place this all within a form.


Step 3: The Toggle Switch

The small circle that will be the switch itself is simply a span that we'll style later on. Give the span a class of switch and insert it after the inputs.

This is your final HTML markup:

<span class="toggle-bg">
	<input type="radio" name="toggle" value="off">
	<input type="radio" name="toggle" value="on"> 
	<span class="switch"></span>
</span>


Step 4: Style the Background

To keep things simple, we'll start out with the bare minimum required to get this toggle working. Add the following to your CSS document (or to your style element if you're using inline CSS.)

.toggle-bg{
	background: #222; /* You'll want to see the area being toggled, but feel free to change the color */
	display: block; /* ...So that we can set a height and width */
	float: left; /* ...So that it doesn't take up the full width of the page */
	height: 7px; /* You can change this later if you want */
	position: relative; /* Required to allow the switch to move around */
	width: 26px; /* This can be changed later as well */
}

Step 5: The Invisible Inputs

These inputs need to be absolutely positioned, then shifted slightly to fit correctly. We'll then turn their opacity down to 0.

.toggle-bg input{
	height: 28px;
	left: 0;
	margin: 0; /* Reset the margins and padding */
	opacity: 0; /* Invisible! */
	padding: 0;
	position: absolute;
	top: -10px; /* Shift vertically */
	width: 36px;
	z-index: 2; /* We want the input to be over the span.switch, which we'll give a z-index of 1 */
}

Step 6: The Toggle Switch

The switch should be square, so we can round it into a perfect circle later using a border-radius. It needs relative positioning to be able to move around, and since we need to give it a height and width, it will be a block-level element floated to the left.

.switch{
	background: #ccc;
	display: block;
	float: left;
	height: 14px;
	left: -1px; /* This is the starting point. When adding a border radius, a small bit of the background is shown if we use left: 0;, so -1px is best.*/
	position: relative;
	top: -4px; /* ...To keep it centered vertically */
	width: 14px;
	z-index: 1; /* Remember, it must be below the invisible inputs */
}

Step 7: CSS Hackery!

CSS3 added the new general sibling combinator, a selector that uses the tilde (~) to select elements that share the same parent. The order in which they appear in the CSS (before or after the tilde) mirrors the order in which they appear in the DOM.

We also have access to the new :checked pseudo-class. This will allow us to specifically target the (currently invisible) radio input that is checked..

First, we'll use these selectors to reset the starting position of the toggle switch.

.toggle-bg input:checked~.switch{ left: -1px; } /* initial toggle position */

Next, we'll tell the browser the final toggle position.

.toggle-bg input~:checked~.switch{ left: 13px; } /* final relative toggle position */

Finally, we'll put the :checked input behind the unchecked input and the switch so that the second input can be clicked.

.toggle-bg input:checked{ z-index: 0; }

By now, it should look like this:

Unstyled toggle

Step 8: Story So Far

Here is the complete, unstyled CSS:

.toggle-bg{
	background: #222; /* You'll want to see the area being toggled, but feel free to change the color */
	display: block; /* ...So that we can set a height and width */
	float: left; /* ...So that it doesn't take up the full width of the page */
	height: 7px; /* You can change this later if you want */
	position: relative; /* Required to allow the switch to move around */
	width: 26px; /* This can be changed later as well */
}

.toggle-bg input{
	height: 28px;
	left: 0;
	margin: 0; /* Reset the margins and padding */
	opacity: 0; /* Invisible! */
	padding: 0;
	position: absolute;
	top: -10px; /* Shift vertically */
	width: 36px;
	z-index: 2; /* We want the input to be over the span.switch, which we'll give a z-index of 1 */
}

.switch{
	background: #ccc;
	display: block;
	float: left;
	height: 14px;
	left: -1px; /* This is the starting point. When adding a border radius, a small bit of the background is shown if we use left: 0;, so -1px is best.*/
	position: relative;
	top: -4px; /* ...To keep it centered vertically */
	width: 14px;
	z-index: 1; /* Remember, it must be below the invisible inputs */
}

.toggle-bg input:checked~.switch{ left: -1px; } /* initial toggle position */

.toggle-bg input~:checked~.switch{ left: 13px; } /* final relative toggle position */

.toggle-bg input:checked{ z-index: 0; }

Step 9: Border Radii

You now have a goofy-looking square slider, so let's round out those corners! We'll add a border-radius of 8px to the span with a class of toggle-bg and to the span with a class of switch.

border-radius: 8px;

Note: As with opacity and the transition coming up, I'm not using any vendor prefixes here for the sake of the tutorial, but you'll need them for compatibility with some older browsers.

Toggle with border radius

Step 10: Transitions

Transitions should be added to the span with a class of switch. Feel free to adjust the settings. Left: is the only part of the following transition that can not be changed.

transition: left .2s ease;

Step 11: Background, Shadows, Gradients...

Now that all the functionality is there, everything can be customized to your liking. You can add a box-shadow and background gradient to the span with a class of toggle-bg or to the switch. Because it's round, radial gradients will tend to look better on the switch.

Here are my settings, but please change them to suit your style and your project.

Give the body an off-white background and a margin so the toggle isn't right in the corner:

body{
	background: #f6f8f9;
	margin: 200px;
}

Add the following to the styles for .toggle-bg:

	background: linear-gradient(to bottom, #f6f8f9 0%,#e5ebee 50%,#d7dee3 51%,#f5f7f9 100%);
    box-shadow: 0 1px 0 #fff, inset 0 0 2px #d7dee3, inset 0 1px 0 #d7dee3, inset 0 1px 5px #d7dee3;

Add the following to the styles for .switch:

background: radial-gradient(ellipse at center, #ffffff 0%,#fefefe 50%,#fdfdfd 51%,#ffffff 100%);
box-shadow: 0 1px 1px #65727b, 0 0 1px #b6bdc2;
Styled toggle

Step 12: iOS Toggles

For an iOS style toggle, where the switch is the same size as its background, change the following in the style for .switch:

	height: 30px;
	top: 0;
	width: 30px;

Change the final toggle position to be left 41 pixels:

.toggle-bg input~:checked~.switch{ left: 41px; }

Change the sizes of the inputs and remove vertical shifting by changing the following in the styles for .toggle-bg input:

height: 30px;
top: 0;
width: 70px;

Change all your border radii to 30px instead of 8px.

Tip: keep the border-radius value equal to the height of the element it modifies.

And finally, change the height and width of .toggle-bg to fit the changed elements:

height: 30px;
width: 70px;
iOS styled toggle


Conclusion

Congratulations! You can now create JavaScript-free toggles with some cool new CSS3. You'll probably want to change the background gradients, and luckily there is a great online tool to help with this; check out Colorzilla's free gradient editor. There's also a Mac app called Gradient that works similarly.


Browser Support

Because this method relies on some brand new CSS3 features, older browsers aren't supported. Browser support for the :checked pseudo-class includes the following:

  • All versions of Chrome
  • All versions of Firefox
  • Internet Explorer 9+
  • Opera 9+
  • Safari 3+

And the following browsers have support for the general-sibling combinator:

  • All versions of Chrome
  • All versions of Firefox
  • Internet Explorer 7+
  • Opera 9+
  • Safari 3+

jsFiddle

I've created three jsFiddles for you to experiment with on your own. The first includes the bare minimum CSS you'll need to have a working toggle slider. The second, much shinier, includes everything from the first one plus some extra styles and transitions. The last one is the one I'm calling an "iOS style toggle" since, like the toggles on iOS, the switch's height is equal to the toggle background's height.

Because this is all CSS, there are quite a few variations you can create. Here are a few to get your started:

  • Create a vertical, rather than horizontal toggle (maybe for an equalizer?)
  • Use an image with an angular gradient as the switch's background for a more realistic, metallic look.
  • Add a label to the inside of a large toggle.
  • Use jQuery to change the background of .toggle-bg when a child input is checked. Or, even better, figure out if this is possible using nothing but CSS.
  • Add a label to each input within an iOS style toggle and selectively show and hide the labels using jQuery.

Note: when creating a label for the toggle's radio inputs, you'll need to use JavaScript to show and hide the inactive input's label if you wish to be able to use the label as a way of unchecking the input. Otherwise, you'll only be able to check (but not uncheck) the input by pressing the label.

I hope you found this tutorial useful. Thanks for reading!

Related Posts
  • Web Design
    Complete Websites
    Building the Responsive Timeline Portfolio PagePortfolio thumb
    During this tutorial we will be building the fantastic Timeline Portfolio as seen in an earlier tutorial by Tomas Laurinavicius. We will be using some responsive techniques as well as CSS3 animations, Sass and a little bit of jQuery.Read More…
  • Code
    Theme Development
    Custom Controls in the Theme CustomizerTheme customizer custom control 400
    In the last article, we explored the advanced controls available in the Theme Customizer, and how to implement them. We’re going to look at how to create our own custom control, allowing you to choose which Category of Posts are displayed on the home page. To get started, download version 0.6.0 of our Theme Customizer Example.Read More…
  • Web Design
    HTML/CSS
    Creating Friendlier, “Conversational” Web FormsForm retina
    Web forms are constantly a hot topic when it comes to web design and user interaction. The reasons for this are vast, but one of the more obvious reasons is that forms are the most basic way for a user to input information into your application. In this article, we'll discuss a few techniques that allow your forms to respond to the user's input, while helping to obscure unnecessarily confusing or overwhelming elements.Read More…
  • Web Design
    UX
    Walk Users Through Your Website With Bootstrap TourTour retina
    When you have a web application which requires some getting used to from your users, a walkthrough of the interface is in order. Creating a walkthrough directly on top of the interface makes things very clear, so that's what we're going to build, using Bootstrap Tour.Read More…
  • Web Design
    Email
    Creating a Simple Responsive HTML EmailEmail new rwd thumb
    In this tutorial I will show you how to create a simple responsive HTML email which will work in every email client, including all the new smartphone mail clients and apps. It uses minimal media queries and a fluid width approach to ensure maximum compatibility.Read More…
  • Web Design
    HTML/CSS
    How to Customize the Foundation 4 Top BarFoundation preview
    Zurb's Foundation 4 features a brilliant top bar which has become almost symbolic of a Foundation site build. Today we're going to look at how you can implement it in a different way, placing it elsewhere on the page, giving you a custom and responsive horizontal navigation menu.Read More…