47 CSS Toggles & Switches39 / 47

Pure CSSMIT licensed

Day / Night

A dark-mode toggle that morphs from a sun in a sky-blue track to a crescent moon over a deep night track. The most "what does this control" pattern in the bunch.

Published Updated

Live Demo
Try it

The code

<label class="tgl-39" aria-label="Theme: light or dark">
  <input class="tgl-39__input" type="checkbox" checked>
  <span class="tgl-39__track" aria-hidden="true">
    <span class="tgl-39__thumb">
      <span class="tgl-39__crater tgl-39__c1"></span>
      <span class="tgl-39__crater tgl-39__c2"></span>
      <span class="tgl-39__crater tgl-39__c3"></span>
    </span>
    <span class="tgl-39__star tgl-39__s1"></span>
    <span class="tgl-39__star tgl-39__s2"></span>
    <span class="tgl-39__star tgl-39__s3"></span>
  </span>
</label>
.tgl-39 {
  font-family: "Inter", "Segoe UI", system-ui, sans-serif;
  font-size: 14px;
  min-height: 100vh;
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 24px;
  padding: 48px 20px;
  background: #14141e;
  box-sizing: border-box;
}

.tgl-39__input {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0,0,0,0);
  white-space: nowrap;
  border: 0;
}

.tgl-39__track {
  position: relative;
  width: 72px;
  height: 36px;
  background: linear-gradient(180deg, #87ceeb 0%, #4a90c2 100%);
  border-radius: 999px;
  overflow: hidden;
  transition: background 0.4s ease;
  box-shadow: inset 0 1px 3px rgba(0,0,0,0.2);
}

.tgl-39__thumb {
  position: absolute;
  top: 3px;
  left: 3px;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  background: radial-gradient(circle at 35% 35%, #ffe066 0%, #f5a623 90%);
  box-shadow: 0 0 14px rgba(255, 224, 102, 0.7);
  transition: left 0.4s cubic-bezier(0.4, 0, 0.2, 1), background 0.4s ease, box-shadow 0.4s ease;
}

.tgl-39__crater {
  position: absolute;
  border-radius: 50%;
  background: #2a2a30;
  opacity: 0;
  transition: opacity 0.4s ease;
}

.tgl-39__c1 {
  top: 6px;
  left: 8px;
  width: 6px;
  height: 6px;
}

.tgl-39__c2 {
  top: 14px;
  left: 18px;
  width: 4px;
  height: 4px;
}

.tgl-39__c3 {
  top: 20px;
  left: 6px;
  width: 5px;
  height: 5px;
}

.tgl-39__star {
  position: absolute;
  width: 2px;
  height: 2px;
  background: #fff;
  border-radius: 50%;
  opacity: 0;
  transition: opacity 0.4s ease;
}

.tgl-39__s1 {
  top: 8px;
  left: 14px;
}

.tgl-39__s2 {
  top: 18px;
  left: 24px;
  width: 1.5px;
  height: 1.5px;
}

.tgl-39__s3 {
  top: 10px;
  left: 28px;
}

.tgl-39__input:not(:checked) ~ .tgl-39__track {
  background: linear-gradient(180deg, #0a1322 0%, #1c2540 100%);
}

.tgl-39__input:not(:checked) ~ .tgl-39__track .tgl-39__thumb {
  left: 39px;
  background: radial-gradient(circle at 35% 35%, #e8e6f0 0%, #a8a5bb 90%);
  box-shadow: 0 0 12px rgba(168, 165, 187, 0.5);
}

.tgl-39__input:not(:checked) ~ .tgl-39__track .tgl-39__crater {
  opacity: 0.5;
}

.tgl-39__input:not(:checked) ~ .tgl-39__track .tgl-39__star {
  opacity: 0.85;
}

.tgl-39__input:focus-visible ~ .tgl-39__track {
  outline: 2px solid #ffe066;
  outline-offset: 3px;
}

@media (prefers-reduced-motion: reduce) {
  .tgl-39__track,
    .tgl-39__thumb,
    .tgl-39__crater,
    .tgl-39__star {
    transition: none;
  }
}
/* No JavaScript — the thumb's radial gradient swaps sun→moon while crater and star spans crossfade with opacity over the re-graded track. */
Paste this into ChatGPT, Claude, Cursor, or any coding assistant. The block below is pre-framed with everything the AI needs to integrate this demo into your project — markup, styles, scoping notes, and the source URL. Hit Copy and paste straight into your chat.
Here's a working CSS Toggles & Switche from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: Day / Night
Source: https://codefronts.com/components/css-toggles-switches/day-night/

A dark-mode toggle that morphs from a sun in a sky-blue track to a crescent moon over a deep night track. The most "what does this control" pattern in the bunch.
## HTML
```html
<label class="tgl-39" aria-label="Theme: light or dark">
  <input class="tgl-39__input" type="checkbox" checked>
  <span class="tgl-39__track" aria-hidden="true">
    <span class="tgl-39__thumb">
      <span class="tgl-39__crater tgl-39__c1"></span>
      <span class="tgl-39__crater tgl-39__c2"></span>
      <span class="tgl-39__crater tgl-39__c3"></span>
    </span>
    <span class="tgl-39__star tgl-39__s1"></span>
    <span class="tgl-39__star tgl-39__s2"></span>
    <span class="tgl-39__star tgl-39__s3"></span>
  </span>
</label>
```
## CSS
```css
.tgl-39 {
  font-family: "Inter", "Segoe UI", system-ui, sans-serif;
  font-size: 14px;
  min-height: 100vh;
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 24px;
  padding: 48px 20px;
  background: #14141e;
  box-sizing: border-box;
}

.tgl-39__input {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0,0,0,0);
  white-space: nowrap;
  border: 0;
}

.tgl-39__track {
  position: relative;
  width: 72px;
  height: 36px;
  background: linear-gradient(180deg, #87ceeb 0%, #4a90c2 100%);
  border-radius: 999px;
  overflow: hidden;
  transition: background 0.4s ease;
  box-shadow: inset 0 1px 3px rgba(0,0,0,0.2);
}

.tgl-39__thumb {
  position: absolute;
  top: 3px;
  left: 3px;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  background: radial-gradient(circle at 35% 35%, #ffe066 0%, #f5a623 90%);
  box-shadow: 0 0 14px rgba(255, 224, 102, 0.7);
  transition: left 0.4s cubic-bezier(0.4, 0, 0.2, 1), background 0.4s ease, box-shadow 0.4s ease;
}

.tgl-39__crater {
  position: absolute;
  border-radius: 50%;
  background: #2a2a30;
  opacity: 0;
  transition: opacity 0.4s ease;
}

.tgl-39__c1 {
  top: 6px;
  left: 8px;
  width: 6px;
  height: 6px;
}

.tgl-39__c2 {
  top: 14px;
  left: 18px;
  width: 4px;
  height: 4px;
}

.tgl-39__c3 {
  top: 20px;
  left: 6px;
  width: 5px;
  height: 5px;
}

.tgl-39__star {
  position: absolute;
  width: 2px;
  height: 2px;
  background: #fff;
  border-radius: 50%;
  opacity: 0;
  transition: opacity 0.4s ease;
}

.tgl-39__s1 {
  top: 8px;
  left: 14px;
}

.tgl-39__s2 {
  top: 18px;
  left: 24px;
  width: 1.5px;
  height: 1.5px;
}

.tgl-39__s3 {
  top: 10px;
  left: 28px;
}

.tgl-39__input:not(:checked) ~ .tgl-39__track {
  background: linear-gradient(180deg, #0a1322 0%, #1c2540 100%);
}

.tgl-39__input:not(:checked) ~ .tgl-39__track .tgl-39__thumb {
  left: 39px;
  background: radial-gradient(circle at 35% 35%, #e8e6f0 0%, #a8a5bb 90%);
  box-shadow: 0 0 12px rgba(168, 165, 187, 0.5);
}

.tgl-39__input:not(:checked) ~ .tgl-39__track .tgl-39__crater {
  opacity: 0.5;
}

.tgl-39__input:not(:checked) ~ .tgl-39__track .tgl-39__star {
  opacity: 0.85;
}

.tgl-39__input:focus-visible ~ .tgl-39__track {
  outline: 2px solid #ffe066;
  outline-offset: 3px;
}

@media (prefers-reduced-motion: reduce) {
  .tgl-39__track,
    .tgl-39__thumb,
    .tgl-39__crater,
    .tgl-39__star {
    transition: none;
  }
}
```

## JavaScript
```js
/* No JavaScript — the thumb's radial gradient swaps sun→moon while crater and star spans crossfade with opacity over the re-graded track. */
```

How this works

Inverted-state design: CHECKED is day, unchecked is night — matching a 'light theme on' semantic. The 72×36 track crossfades between sky and midnight gradients; the 30px thumb slides 36px and morphs sun→moon by swapping its radial gradient (gold → silver) while three crater dots inside it and three star dots on the track fade in via opacity.

Every celestial detail is a positioned span with an opacity transition, so night assembles itself in one 0.4s beat. Glows travel with the thumb via box-shadow color swaps. The label carries an explicit aria-label ('Theme: light or dark') since the control has no visible text.

Make it yours

  • Flip the state semantics by swapping the :not(:checked) selectors if your model is 'dark mode on'.
  • Add clouds to the day state — a white blob span fading opposite the stars.
  • Slow to 0.7s for a more cinematic transition.
  • Bind it to a real theme by pairing with :has() on <html> (see demo 02).

Gotchas — read before shipping

  • Craters/stars must be aria-hidden decorations — the checkbox alone carries state for AT.
  • The thumb slides via left; on this 36px travel it's fine, but transform is the stricter choice.
  • Keep sun and moon glows distinct in more than hue (gold spread vs dimmer silver) for grayscale legibility.

Browser support

ChromeSafariFirefoxEdge
26+7+16+26+

Gradient swaps + opacity transitions; universal in modern browsers.

Techniques used in this demo

Search CodeFronts

Loading…