Dark Mode Toggle Button without Javascript II
Written by Lucie Zdeňková on 2025-01-16
htmlcssIn the previous part Dark Mode Toggle without Javascript, we demonstrated how to set up CSS variables and style the wrapper div container. In this second part, we will focus on styling the toggle itself.
Toggle Button UI
In the image, you can see the final appearance of the toggle UI achieved using the following CSS.
Hiding the Checkbox Input
The hidden checkbox input is the key principle of this solution. While the checkbox
remains functional for accessibility and state management, the visible toggle UI is
controlled through the <label>
element. Properties display:
none
and visibility: hidden
, along with width: 0
and
height: 0
completely hide the checkbox from view.
input#darkmode-toggle {
width: 0;
height: 0;
visibility: hidden;
display: none;
}
Styling the Toggle Container
This section defines the toggle's main visual container. It acts as a clickable area
styled to look like a rounded switch. The property display: block
allows
the label to act as a block-level element, making it possible to set width
and height
. The position: relative
is necessary for styling
the knob in next step, cursor: pointer
indicates to users that this
element is interactive. Properties border-radius, box-shadow
define the
rounded shape and shadows of the toggle, while background-color
uses a
previously set CSS variable var(--toggle-bg)
to allow dynamic theme
changes.
label.darkmode-label {
display: block;
position: relative;
cursor: pointer;
width: 100px;
height: 40px;
border-radius: 40px;
box-shadow: inset 0px 1px 3px rgba(0, 0, 0, 0.4), inset 0px -1px 3px rgba(255, 255, 255, 0.4);
background-color: var(--toggle-bg);
}
Styling the Toggle Knob
The knob is styled to move smoothly between light and dark modes. Using
position: absolute;
the knob is placed relative to the toggle container
styled in the code snippet above. Property content: ""
ensures the
:after
pseudo-element is rendered. We are using the CSS variables to
dynamically adjust horizontal placement by using left: var(--label-left)
,
backgroud of the knob is changed by background: linear-gradient(180deg,
var(--gradient-bg1), var(--gradient-bg2))
and movement animations are controlled
by transform: var(--transformantion)
. The remaining properties
width, height, border-radius, box-shadow
follow similar logic as described
in the previous code snippet. Lastly, top: 2px
aligns the knob
vertically.
label.darkmode-label:after {
position: absolute;
content: "";
left: var(--label-left);
transform: var(--transformantion);
background: linear-gradient(180deg, var(--gradient-bg1), var(--gradient-bg2));
width: 36px;
height: 36px;
top: 2px;
border-radius: 36px;
box-shadow: 0px 1px 2px rgba(0, 0, 0, 0.2);
}
Animations and Additional Elements
Following code snippet adds smooth animations to the toggle's movements and
interactions. First property transition: 0.3s
ensures a 0.3-second
animation for the toggle changes. Property width: 52px
with selector
label.darkmode-label:active:after
slightly enlarges the knob during
interaction for a tactile feedback effect.
label.darkmode-label,
label.darkmode-label:after {
transition: 0.3s
}
label.darkmode-label:active:after {
width: 52px;
}
Icon Styling
Following CSS code styles sun and moon illustrations mentioned in previous blog
post. We need to reach icon color change according to the theme selection. Suitable
solution is setting backgroud image by CSS variable background-image:
var(--img-sun)
and background-image: var(--img-moon)
. It's
necessary to use <span>
element inside the
<label>
element, so display: block
allows setting
dimensions width
and height
. Property position:
absolute
sets absolute position to the label container, meanwhile properties
left, top
sets vertical and horizontal positioning. Previously mentioned
transition: 0.3s
makes the animation effect. Lastly, z-index:
1
defines placement of icons above the other elements.
label.darkmode-label span.sun {
background-image: var(--img-sun);
display: block;
position: absolute;
width: 24px;
height: 24px;
left: 8px;
top: 8px;
transition: 0.3s;
z-index: 1;
}
label.darkmode-label span.moon {
background-image: var(--img-moon);
display: block;
position: absolute;
width: 24px;
height: 24px;
left: 68px;
top: 8px;
transition: 0.3s;
z-index: 1;
}
This code creates a functional and visually appealing toggle switch by combining CSS
variables, pseudo-elements, and transitions. The hidden checkbox input manages the
toggle state, while the <label>
and associated pseudo-elements
provide the interactive UI. CSS variable dynamic properties like
--toggle-bg
and --label-left
allow seamless adaptation
between themes. This is everyting you need to implement dark mode toggle on the static
website without the need to use javascript.
Thank you for reading and see ya next time!