Skip to content

Switch iOS

Recreate the iOS liquid glass switch with ::part(switch) colors and an :active glass thumb slotted into thumb.

Code

The following example assumes that you have imported the component and set up the theme.

iOS Switch
<div class="switch-wrapper">
<sv-toggle-switch class="ios-switch" aria-label="Wi-Fi">
<!-- Blank the default icons: the iOS switch has none -->
<span slot="background"></span>
<!-- White thumb that turns to clear glass while pressed -->
<div class="liquid-thumb" aria-hidden="true" slot="thumb"></div>
</sv-toggle-switch>
</div>
<style>
.switch-wrapper {
4 collapsed lines
display: grid;
place-items: center;
padding: 3.5em 2.5em;
border-radius: 4px;
}
.ios-switch {
--sv-thumb-h: 1.7em;
--sv-thumb-w: 3em;
--sv-switch-w: 4.6em;
--sv-check-ease: cubic-bezier(0.34, 1.3, 0.64, 1);
/* The slotted glass thumb replaces the built-in one */
&::part(thumb) {
3 collapsed lines
display: grid;
place-items: center;
background: transparent;
}
/* The toggle switch container */
&::part(switch) {
4 collapsed lines
padding: 0.2em;
background: light-dark(#78788052, #39393d);
border-radius: 2em;
box-shadow: inset 0 0 1px light-dark(#30303073, #ffffff40);
}
/* When the toggle switched is checked */
&:state(--checked)::part(switch) {
2 collapsed lines
background: #0a84ff;
box-shadow: none;
}
}
/* White pill thumb at rest */
.liquid-thumb {
12 collapsed lines
position: relative;
inline-size: 100%;
block-size: 100%;
background: #fff;
border-radius: 100em;
box-shadow:
0 1px 4px #0000004d,
0 4px 10px #00000026;
transition:
scale var(--sv-check-dur) var(--sv-check-ease),
background var(--sv-check-dur) var(--sv-check-ease),
box-shadow var(--sv-check-dur) var(--sv-check-ease);
/* Only the thumb grows and turns to clear glass while pressed */
.ios-switch:active & {
6 collapsed lines
overflow: clip;
background: #ffffff1a;
box-shadow:
0 6px 16px #00000045,
inset 0 1px 1px #ffffff8c;
scale: 1.4;
/* Refraction: bends what sits behind the thumb through the lens map, clear center. */
&::before {
5 collapsed lines
position: absolute;
inset: 0;
content: "";
border-radius: inherit;
backdrop-filter: blur(0.4px);
}
/* Edge ring that reflects the colors behind it, glinting along the light diagonals */
&::after {
11 collapsed lines
position: absolute;
inset: 0;
padding: 1px;
content: "";
border-radius: inherit;
backdrop-filter: blur(4px) brightness(180%) saturate(190%);
mask:
conic-gradient(#00000040 0deg, #000 110deg, #000 170deg, #00000026 250deg, #000 290deg, #000 340deg, #00000040 360deg),
linear-gradient(#000 0 0) content-box,
linear-gradient(#000 0 0);
mask-composite: intersect, exclude, add;
}
}
}
@media (prefers-reduced-motion: reduce) {
.liquid-thumb {
transition-duration: 0s;
}
}
</style>