<h1>Switches</h1>
<div class="themes">
<p>Theme:</p>
<label class="theme__color">
<input type="radio" name="color" class="theme__input" value="green" checked>
<span class="theme__icon" style="--color: hsl(160, 79%, 46%)"></span>
</label>
<label class="theme__color">
<input type="radio" name="color" class="theme__input" value="blue">
<span class="theme__icon" style="--color: hsl(200, 79%, 46%)"></span>
</label>
</div>
<section class="switches" data-theme="green">
<div class="switch switch--1">
<label class="switch__label">
<input type="checkbox" class="switch__input">
<span class="switch__design"></span>
</label>
</div>
<div class="switch switch--2">
<label class="switch__label">
<input type="checkbox" class="switch__input">
<span class="switch__design"></span>
</label>
</div>
<div class="switch switch--3">
<label class="switch__label">
<input type="checkbox" class="switch__input">
<span class="switch__design"></span>
</label>
</div>
<div class="switch switch--4">
<label class="switch__label">
<input type="checkbox" class="switch__input">
<span class="switch__design"></span>
</label>
</div>
<div class="switch switch--5">
<label class="switch__label">
<input type="checkbox" class="switch__input">
<span class="switch__design"></span>
</label>
</div>
<div class="switch switch--6">
<label class="switch__label">
<input type="checkbox" class="switch__input">
<span class="switch__design"></span>
</label>
</div>
<div class="switch switch--7">
<label class="switch__label">
<input type="checkbox" class="switch__input">
<span class="switch__design"></span>
</label>
</div>
</section>
<a href="https://abubakersaeed.netlify.app/designs/d6-switches" class="abs-site-link" rel="nofollow noreferrer" target="_blank">abs/designs/d6-switches</a>
// default
// ==========================================================
*,
*::after,
*::before {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html {
font-size: 62.5%;
}
body {
& {
--color: hsl(220, 50%, 90%);
--global-background: hsl(220, 25%, 10%);
}
& {
min-height: 100vh;
padding: 2rem;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
color: var(--color);
background: var(--global-background);
}
}
h1 {
font-size: 3.2rem;
font-weight: normal;
letter-spacing: .4rem;
}
p {
font-size: 1.6rem;
}
// themes & switches
// ==========================================================
.theme {
&s {
display: flex;
align-items: center;
position: absolute;
top: 6rem;
right: 6rem;
padding: .4rem 2rem .4rem 3rem;
border: 1px solid hsla(0, 0%, 100%, .2);
border-radius: .8rem;
}
&__color {
& {
margin: 1rem;
cursor: pointer;
position: relative;
}
&:first-of-type {
margin-left: 2rem;
}
}
&__input {
opacity: 0;
position: absolute;
left: 50%;
top: 50%;
z-index: -1;
}
&__input:checked+&__icon {
box-shadow: 0 0 0 .5rem var(--global-background), 0 0 0 .6rem hsla(0, 0%, 100%, .2);
transform: scale(1);
}
&__input:focus+&__icon {
box-shadow: 0 0 0 .5rem var(--global-background), 0 0 0 .6rem var(--color);
}
&__icon {
display: inline-block;
width: 2.6rem;
height: 2.6rem;
border-radius: 100rem;
background: var(--color);
transform: scale(.6);
transition: .2s;
}
}
.switches {
&[data-theme="green"] {
--primary-light: hsl(160, 79%, 46%);
--primary-dark: hsl(160, 79%, 16%);
--ripple: hsla(160, 79%, 46%, .1);
--focus: hsl(160, 69%, 46%);
}
&[data-theme="blue"] {
--primary-light: hsl(200, 79%, 46%);
--primary-dark: hsl(200, 79%, 16%);
--ripple: hsla(200, 79%, 46%, .1);
--focus: var(--primary-light);
}
& {
display: flex;
align-items: center;
margin-top: 8rem;
}
}
// main
// ==========================================================
.switch {
&:not(:last-of-type) {
margin-right: 4rem;
}
&__label {
position: relative;
cursor: pointer;
}
&__input {
opacity: 0;
position: absolute;
top: 50%;
left: 50%;
z-index: -1;
transform: translate(-50%, -50%);
}
&__input:focus+&__design {
box-shadow: 0 0 0 .1rem var(--global-background), 0 0 0 .2rem var(--focus);
}
// variables
// ----------------------------------------------------
& {
--width: 6rem;
--height: 3rem;
--background: hsl(0, 0%, 30%);
--checked-background: var(--primary-dark);
--thumb-size: 1.6rem;
--thumb-ripple-color: var(--ripple);
--thumb-background: hsl(0, 0%, 65%);
--checked-thumb-background: var(--primary-light);
--thumb-space-between-edges: .6rem;
--thumb-out: var(--thumb-space-between-edges);
}
&--1,
&--3,
&--5,
&--7 {
--width: 4rem;
--height: 1.6rem;
--thumb-size: 2rem;
--thumb-space-between-edges: 0rem;
--thumb-out: -.3rem;
}
&--2,
&--6 {
--background: hsla(0, 0%, 20%);
}
&--3,
&--4 {
--border: 1px solid hsl(0, 0%, 60%);
--background: transparent;
}
&--7 {
--width: 3rem;
--thumb-out: calc((var(--thumb-size) / 2) - ((var(--thumb-size) / 2) * 2) + .2rem);
}
// appearance
// ----------------------------------------------------
&__design {
display: inline-block;
width: var(--width);
height: var(--height);
border: var(--border);
border-radius: 100rem;
background: var(--background);
position: relative;
transition: .2s, box-shadow 0s;
}
&__design::before {
content: '';
position: absolute;
left: var(--thumb-out);
top: 50%;
transform: translateY(-50%);
width: var(--thumb-size);
height: var(--thumb-size);
border-radius: 100rem;
background: var(--thumb-background);
transition: inherit;
}
&--5 &__input:not(:checked)+&__design,
&--7 &__input:not(:checked)+&__design {
--thumb-ripple-color: hsla(0, 0%, 65%, .1);
}
&--6 &__design {
transition: .3s, box-shadow 0s;
}
// states
// ----------------------------------------------------
&__input:checked+&__design {
border-color: transparent;
background: var(--checked-background);
}
&__input:checked+&__design::before {
left: calc(100% - (var(--thumb-size) + var(--thumb-out)));
background: var(--checked-thumb-background);
}
&--6 &__input:checked+&__design::before {
left: calc(100% - var(--thumb-out));
transform: translate(-100%, -50%);
}
&--5 &__design:hover::before,
&--7 &__design:hover::before,
&--5 &__input:focus+&__design::before,
&--7 &__input:focus+&__design::before {
box-shadow: 0 0 0 .9rem var(--thumb-ripple-color);
}
&--6 &__design:active::before {
width: calc(var(--thumb-size) + .4rem);
}
}
.abs-site-link {
position: fixed;
bottom: 20px;
left: 20px;
color: hsla(0, 0%, 100%, .6);
font-size: 1.6rem;
}
View Compiled
// @AbubakerSaeed96 (twitter)
// abubakersaeed.netlify.com
// =========================
// 1&2 Simple
// 3&4 Outline/Border
// 5 Material Design-like
// 6 I've seen it on sites but I don't know what people call that design/effect (maybe liquid/or-like?)
// 7 Material Design-like (Half thumb out)
/*
#keyboard-users: It's not an outline but more of a custom outline using box-shadow. All the effects that mouse users can see you'll get the same except for the sixth switch.
*/
/* Things to keep in mind.
=========================
Colors:
1. Outline Color (...that you'll see when you focus the switch) should be brighter than the background color of the switch. So that #keyboard-users can see/know which switch/item they are currently on. It can be same as thumb background color (as I used in my blue theme).
2. Choose colors wisely. And don't just pick any color. I've tried purple (and even though I like purple...) it doesn't look good on switches.
==========================
These are for my component not saying you should not try/use in yours...
*/
// Thank You for viewing.
// ========================================
// Theming Stuff
const $ = e => document.querySelectorAll(e);
const _switches = $(".switches")[0];
const _colors = $("input[name='color']");
for (let i = 0; i < _colors.length; i++) {
_colors[i].addEventListener("change", e => {
if (e.target.checked) _switches.setAttribute('data-theme', e.target.value);
})
}
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.