Skip to content

Toggle Switch Custom Icons

Use checked-icon and unchecked-icon slots for custom icons or text.

Code

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

Toggle Switch Custom Icons
<div class="switch-example-container">
<!-- Animated icons -->
17 collapsed lines
<div class="switch-container">
<label for="animated-icons">Animated</label>
<sv-toggle-switch id="animated-icons" class="animated-icons">
<svg class="custom-switch-icon checked" slot="checked-icon" viewBox="0 -960 960 960" xmlns="http://www.w3.org/2000/svg">
<path
d="M480-360q50 0 85-35t35-85q0-50-35-85t-85-35q-50 0-85 35t-35 85q0 50 35 85t85 35Zm0 80q-83 0-141.5-58.5T280-480q0-83 58.5-141.5T480-680q83 0 141.5 58.5T680-480q0 83-58.5 141.5T480-280ZM200-440H40v-80h160v80Zm720 0H760v-80h160v80ZM440-760v-160h80v160h-80Zm0 720v-160h80v160h-80ZM256-650l-101-97 57-59 96 100-52 56Zm492 496-97-101 53-55 101 97-57 59Zm-98-550 97-101 59 57-100 96-56-52ZM154-212l101-97 55 53-97 101-59-57Zm326-268Z"
></path>
</svg>
<svg class="custom-switch-icon unchecked" slot="unchecked-icon" viewBox="0 -960 960 960" xmlns="http://www.w3.org/2000/svg">
<path
d="M480-120q-150 0-255-105T120-480q0-150 105-255t255-105q14 0 27.5 1t26.5 3q-41 29-65.5 75.5T444-660q0 90 63 153t153 63q55 0 101-24.5t75-65.5q2 13 3 26.5t1 27.5q0 150-105 255T480-120Zm0-80q88 0 158-48.5T740-375q-20 5-40 8t-40 3q-123 0-209.5-86.5T364-660q0-20 3-40t8-40q-78 32-126.5 102T200-480q0 116 82 198t198 82Zm-10-270Z"
></path>
</svg>
</sv-toggle-switch>
</div>
<!-- Text as icons -->
8 collapsed lines
<div class="switch-container">
<label for="text-as-icons">Text</label>
<sv-toggle-switch id="text-as-icons" class="text-as-icons">
<strong aria-hidden="true" slot="checked-icon">On</strong>
<span aria-hidden="true" slot="unchecked-icon">Off</span>
</sv-toggle-switch>
</div>
<!-- Animated icons inside the thumb -->
18 collapsed lines
<div class="switch-container">
<label for="icons-inside-thumb">Inside the thumb</label>
<sv-toggle-switch id="icons-inside-thumb" class="icons-inside-thumb">
<strong slot="checked-icon"></strong>
<span slot="unchecked-icon"></span>
<div class="custom-thumb" slot="thumb">
<svg class="thumb-icon unchecked" aria-hidden="true" viewBox="0 -960 960 960" xmlns="http://www.w3.org/2000/svg">
<path d="m256-200-56-56 224-224-224-224 56-56 224 224 224-224 56 56-224 224 224 224-56 56-224-224-224 224Z" />
</svg>
<svg class="thumb-icon checked" aria-hidden="true" viewBox="0 -960 960 960" xmlns="http://www.w3.org/2000/svg">
<path d="M382-240 154-468l57-57 171 171 367-367 57 57-424 424Z" />
</svg>
</div>
</sv-toggle-switch>
</div>
<!-- No icons -->
8 collapsed lines
<div class="switch-container">
<label for="no-icons">No icons</label>
<sv-toggle-switch id="no-icons">
<strong slot="checked-icon"></strong>
<span slot="unchecked-icon"></span>
</sv-toggle-switch>
</div>
</div>
<style>
.switch-example-container {
3 collapsed lines
display: flex;
flex-direction: column;
gap: 1em;
}
.switch-container {
14 collapsed lines
--transition-dur: 400ms;
display: flex;
gap: 0.5rem;
align-items: center;
label {
flex: 1;
cursor: pointer;
}
@media (prefers-reduced-motion: reduce) {
--transition-dur: 0s;
}
}
.animated-icons {
28 collapsed lines
.custom-switch-icon {
block-size: 1.4em;
transition:
scale var(--sv-check-dur) var(--sv-check-ease),
rotate var(--transition-dur) var(--sv-check-ease);
&.checked {
rotate: 180deg;
scale: 0;
}
&.unchecked {
rotate: 0deg;
scale: 1;
}
}
&:state(--checked) {
.custom-switch-icon.checked {
rotate: 0deg;
scale: 1;
}
.custom-switch-icon.unchecked {
rotate: 90deg;
scale: 0.5;
}
}
}
.text-as-icons {
4 collapsed lines
[slot="checked-icon"],
[slot="unchecked-icon"] {
font-size: 0.8em;
}
}
.icons-inside-thumb {
41 collapsed lines
.custom-thumb {
display: grid;
align-items: center;
justify-content: center;
inline-size: 100%;
block-size: 100%;
}
.thumb-icon {
display: block;
grid-area: 1/1;
inline-size: 1.4em;
block-size: 1.4em;
transition:
opacity var(--sv-check-dur) var(--sv-check-ease),
scale var(--transition-dur) var(--sv-check-ease);
&.checked {
opacity: 0;
fill: var(--sv-accent);
scale: 0;
}
&.unchecked {
opacity: 1;
fill: var(--sv-gray-5);
scale: 1;
}
}
&:state(--checked) {
.thumb-icon.checked {
opacity: 1;
scale: 1;
}
.thumb-icon.unchecked {
opacity: 0;
scale: 0;
}
}
}
</style>