CSS Day Night Switch (CSS/HTML only) [PART 2]
Tags: tutorial, css, webdev, ui
Published: 2021-01-17 17:52:01

Now let's get this finished by implementing the night state of our nice day-night-switch by implementing a moon, day-night transitions and a few sparkling stars as a bonus.

Read the full article or watch me code this on Youtube:

{% youtube oqe5vHs0pyI %}

# Result

{% codepen https://codepen.io/crayon-code/pen/PoGVYVq %} 

## Turning off the lights

So, let's start by turning off the lights, which means that as soon as the switch is unchecked, the background color as well as the border color fade to a darker tone of blue.

```scss
input.day-night-switch {
  // unchecked styles
  + label.day-night-switch {
    border-color: #2a4569;
    background-color: #223349;
  }
}
```

Since also everything appears darker at night (who would have thought...), the mountains also fade from a lighter gray to a darker one, as soon as the checkbox is unchecked.

```scss
input.day-night-switch {
  // unchecked styles
  + label.day-night-switch {
    > .mountains {
      > * {
        background-color: #878787;
        border-color: #5c5c5c;
      }
    }
  }
}
```

## Sunset

First let's define a position to which sun and moon are shifted as soon as they need to set. In this case sun and moon are going to shifted 25% of the height below the lower edge, i.e. 1.25 x the height of the entire switch.

```scss
input.day-night-switch {
  --shift: calc(var(--height) * 1.25);
}
```

Now, to make the sun set, we simply update its value for the `top` property as soon as the checkbox is unchecked. Additionally it is scaled down to `0` to create a little bit of a stronger sunset effect.

```scss
input.day-night-switch {
  // unchecked styles
  + label.day-night-switch {
    > .celestial {
      &.sun {
        transition-delay: 0ms;
        top: var(--shift);
        left: var(--pos-right);
        transform: scale(0);
      }
    }
  }
}
```

## Let the moon come out!

Now that the sun is able to come and go, there's space for the moon. Therefore let's put a `div` with the `celestial` class for the shared styling of sun and moon and the `moon` class for the moon-specific styling...

```pug
label(for="day-night").day-night-switch
  ...
  div.celestial.moon
```

... which is most importantly the moon's color:


```scss
label.day-night-switch {
  > .celestial {
    &.moon {
      background-color: #d2cec4;
      border-color: #a9a18f;
    }
  }
}
```

Analogously to the sun, the moon gets also set its coordinates to where it should be during daytime (checked) and nighttime (unchecked):

```scss
input.day-night-switch {
  // checked styles
  &:checked {
    + label.day-night-switch {
      > .celestial {
        &.moon {
          transition-delay: 0ms;
          left: var(--pos-left);
          top: var(--shift);
          transform: scale(0);
        }
      }
    }
  }
}

input.day-night-switch {
  // unchecked styles
  + label.day-night-switch {
    > .celestial {
      &.moon {
        transition-delay: var(--transition-duration);
        top: var(--padding);
        left: var(--pos-left);
        overflow: hidden;
        transform: scale(1);
      }
    }
  }
}
```

## Craters!

However, the moon looks still a little but dull and boring and actually not really like a moon. To fix this, let's add a few craters:

```pug
label(for="day-night").day-night-switch
  ...
  div.celestial.moon
    div.craters
      div.crater
      div.crater
      div.crater
      div.crater
      div.crater
```

Very similar to the clouds the craters are positioned relatively to the `--switch-size` inside the moon. Each crater is in the end just a `div` which is made a circle through `border-radius: 50%`. 

The border width of each crater is set to to slightly smaller value than the border width of the moon. But it should never be smaller than `1px`, which is achieved by using the `max(...)` function, returning always the largest value of the ones which are passed to it. So should 65% of the `--border-width` be ever the smaller one, `1px` is returned.

```scss
label.day-night-switch {
  > .celestial {
    &.moon {
      > .craters {
        > .crater {
          background-color: #d2cec4;
          border-color: #a9a18f;
          border-width: calc(max(var(--border-width) * 0.65, 1px));
          border-style: solid;
          position: absolute;

          &:nth-child(1) {
            border-radius: 50%;
            width: calc(var(--switch-size) * 0.15);
            height: calc(var(--switch-size) * 0.15);
            top: calc(var(--switch-size) * 0.7);
            left: calc(var(--switch-size) * 0.4);
          }

          &:nth-child(2) {
            border-radius: 50%;
            width: calc(var(--switch-size) * 0.3);
            height: calc(var(--switch-size) * 0.3);
            top: calc(var(--switch-size) * 0.1);
            left: calc(var(--switch-size) * -0.05);
          }

          &:nth-child(3) {
            border-radius: 50%;
            width: calc(var(--switch-size) * 0.1);
            height: calc(var(--switch-size) * 0.1);
            top: calc(var(--switch-size) * 0.2);
            left: calc(var(--switch-size) * 0.6);
          }

          &:nth-child(4) {
            border-radius: 50%;
            width: calc(var(--switch-size) * 0.1);
            height: calc(var(--switch-size) * 0.1);
            top: calc(var(--switch-size) * 0.3);
            left: calc(var(--switch-size) * 0.25);
          }

          &:nth-child(5) {
            border-radius: 50%;
            width: calc(var(--switch-size) * 0.2);
            height: calc(var(--switch-size) * 0.2);
            top: calc(var(--switch-size) * 0.5);
            left: calc(var(--switch-size) * 0.8);
          }
        }
      }
    }
  }
}
```


## Sparkling stars

Now finally, let's make this night sky perfectly clear by adding a few sparking stars. The good thing is that we already have a few `.decoration` elements for the clouds in the DOM that we don't need at night time. So let's simply reuse them for the stars and by that creat

```scss
input.day-night-switch {
  // unchecked styles
  + label.day-night-switch {
    > .decorations {
      > .decoration {
        position: absolute;
        background-color: white;
        border-radius: 50%;
        width: calc(max(var(--border-width) * 0.75, 2px));
        height: calc(max(var(--border-width) * 0.75, 2px));
        animation: 2s sparkle ease-in-out infinite;
        animation-direction: alternate;

        &:nth-child(1) {
          top: calc(var(--switch-size) * 0.7);
          left: calc(var(--switch-size) * 1.7);
        }
        &:nth-child(2) {
          animation-delay: 300ms;
          animation-duration: 3s;
          top: calc(var(--switch-size) * 0.4);
          left: calc(var(--switch-size) * 1.4);
        }
        &:nth-child(3) {
          animation-delay: 800ms;
          animation-duration: 3.5s;
          top: calc(var(--switch-size) * 0.9);
          left: calc(var(--switch-size) * 2.2);
        }
        &:nth-child(4) {
          animation-delay: 1400ms;
          animation-duration: 2.5s;
          top: calc(var(--switch-size) * 0.3);
          left: calc(var(--switch-size) * 2);
        }
      }
    }
  }
}
```

The sparkling animation itself is just going to alternate between 100% and 25% of opacity for each star:

```scss
@keyframes sparkle {
  0% {
    opacity: 1;
  }

  100% {
    opacity: 0.25;
  }
}

input.day-night-switch {
  // unchecked styles
  + label.day-night-switch {
    > .decorations {
      > .decoration {
        transition: all var(--transition-duration) ease-in-out;
        animation: 2s sparkle ease-in-out infinite;
        animation-direction: alternate;
      }
    }
  }
}
```

To make the sparkling a little bit more exciting, different delays and duration are applied to each star...aaaand it's done!

```scss
// unchecked styles
  + label.day-night-switch {
    > .decorations {
      > .decoration {

        &:nth-child(2) {
          animation-delay: 300ms;
          animation-duration: 3s;
        }
        &:nth-child(3) {
          animation-delay: 800ms;
          animation-duration: 3.5s;
        }
        &:nth-child(4) {
          animation-delay: 1400ms;
          animation-duration: 2.5s;
        }
      }
    }
```

That's all you need to create such a nice little day night swith. I hope you enjoyed creating it.