Cover photo by Wolfgang Mennel on Unsplash.
I was asked the other day at work to change a two-button setup for managing the active status of a user into some kind of slide toggle widget.
So instead of clicking a button to either enable/disable a user, there would be some kind of on/off toggle to change the user's status.
In the past, when I've had to do something like this I've just Googled a solution and then copied it into whatever project I've been working on.
This time, I thought it would be nice to create my own from scratch understanding how to create such a widget.
Here's the finished result of the slide toggle:
I opted to go for a simple slide toggle for on/off states using just HTML/CSS to make the widget more accessible and to give me a bit more a challenge!
Here's how I did it.
The Markup
<div class="custom-checkbox">
<input id="status"
type="checkbox"
name="status">
<label for="status">
<div class="status-switch"
data-unchecked="Off"
data-checked="On">
</div>
</label>
</div>
Hopefully, the markup speaks for itself but here are some points if you're not sure what's going on above:
- We wrap everything in a
div
which we'll use to set an overall height and width for our toggle - There is a checkbox
input
which we'll hide with our CSS styles, the main content will be inside thelabel
element (which itself has a furtherdiv
inside it) - Specifying the
input
's id inside thefor
attribute of thelabel
element allows the user to check/uncheck the checkboxinput
element by clicking thelabel
element - The
div
inside thelabel
has two data attributes (data-unchecked
anddata-checked
) which will form the text for the two states of our slide toggle
Initially, I had tried using two radio button inputs for the slide toggle with each representing either an on or off state.
However, I only got so far with this approach before the styling became a nightmare so I decided to change the radios for a single checkbox which made everything much easier.
As the slide toggle can only have two states; either 'checked' or 'unchecked', it makes more sense to use a checkbox.
The SCSS
The styling of the slide toggle could be done in plain CSS however, using SCSS makes working with the hierarchy of elements easier.
There's a reasonable amount so let's split it up into sections.
The container element
.custom-checkbox {
width: 260px;
height: 60px;
input#status {
display: none;
The first thing we'll do is just set some dimensions for the slide toggle. Changing the width
and height
values will scale all of the other elements to fit.
We'll also hide the input element so we don't see the default HTML checkbox input
element leaving all of the customisation to the content inside the label
.
The label and inner div content
+ label {
height: 100%;
width: 100%;
> .status-switch {
cursor: pointer;
width: 100%;
height: 100%;
position: relative;
background-color: grey;
color: white;
transition: all 0.5s ease;
padding: 3px;
border-radius: 3px;
Using the adjacent sibling selector (the +
symbol) we can select the label
which is next to the input
element.
After ensuring the height
and width
is 100%
we target the inner div
of the label
, with the class of .status-switch
.
This will be the 'unchecked', 'inactive' or 'off' state of the slide toggle.
Some key things here are to ensure the position
is set to relative
as we'll be absolutely positioning elements inside this and the padding
value set will also be used to adjust the inner height and width of the 'slide' button too.
You can choose a background-color
for the unchecked state here.
The before and after pseudo-elements
&:before,
&:after {
border-radius: 2px;
height: calc(100% - 6px);
width: calc(50% - 3px);
display: flex;
align-items: center;
position: absolute;
justify-content: center;
transition: all 0.3s ease;
}
The above is setting some common styles for the before
and after
pseudo-elements which will display the On / Off elements.
There's some basic flex styling to position the text content in the centre of each of the elements and we're using the value that we set in for padding
in the previous step to reduce the width
and height
slightly so that there is a little bit of a border around the slide toggle button.
If you were to view the slide toggle element now, it would look a bit like this:
That's because of the before
and after
elements are not visible yet, and they have no content.
So let's add some separate styles to these to position them correctly.
Positioning before and after
&:before {
background-color: white;
color: black;
box-shadow: 0 0 4px 4px rgba(#000, 0.2);
left: 3px;
z-index: 10;
content: attr(data-unchecked);
}
&:after {
right: 0;
content: attr(data-checked);
}
We'll make the before
element have a white background which will form the 'button' like part of the slide toggle and set it's left
property to 3px
which will again, preserve the border around the toggle.
The after
element will be positioned on the right
hand-side of the containing element.
Both of the elements will get their content set to the respective data-attribute
we set in the initial markup.
Our slide toggle should look like this now:
Updating the checked state
&:checked + label > .status-switch {
background-color: green;
&:after {
left: 0;
content: attr(data-unchecked);
}
&:before {
color: green;
left: 50%;
content: attr(data-checked);
}
To finish off our slide toggle, we'll simply target the :checked
state of the input
element and drill down to the .status-switch
class which is assigned to the inner div
of the label
.
Inside the selector, we can set a new background-color
and then essentially just 'swap over' the before
and after
pseudo-elements.
We do this by updating their left
positions and also updating their content
properties.
Because of the transition
properties that have been set up, the before
element appears to glide into position and the background-color
of the .status-switch
fades in and out.
Conclusion
There's a lot you can do to create your own custom inputs, buttons, toggles and sliders with just some CSS.
The aim of this is to make the code a little bit more accessible, removing the need for JavaScript.
I was surprised how relatively easy it was to create the styling for the slide toggle, once I had got to grips with the hierarchy of the elements and what should happen when the input
is in a checked or unchecked status.
I've only made use of Sass nesting features in the completed code, just to try and make it as readable as possible but the example could be improved to make use of other Sass features such as variables, mixins etc. to make a more reusable and customisable slide toggle component.
Full code and demo is on Codepen: https://codepen.io/codebubb/pen/OJXRGyN
Follow me on Twitter (@codebubb) for more articles and videos.
Have you got your own custom checkbox or slide toggle examples? Let me know in the comments below!
Top comments (5)
Nice tutorial but in my opinion toggle switches are too confusing, they provide poor visual feedback. Please just use checkbox input in your next project. 🙂
uxmovement.com/mobile/the-confusin...
OK, thanks for the feedback!
Very cool, thanks for sharing.
You're welcome 😀
I've been needing something as simple as this for weeks. So glad I finally found your post. Thank you!