Checkboxes are perhaps one of the most commonly used elements in web applications and it is becoming more and more common to see them in the form of a switch control, this may be because apart from looking good aesthetically, they work very well on smartphones.

Before it was a bit complicated to make this kind of controls but now thanks to frameworks like Vue it is very easy to achieve. In this post I will show you how you can create a switch component that you can reuse in your applications.

Here you can see the finished component:

The template

<template>
  <div class="m-switch">
    <input
      type="checkbox"
      class="m-switch__checkbox"
      :value="value"
      :checked="checked"
      @change="change"
    >
    <div class="m-switch__ui">
      <div class="m-switch__handle"></div>
    </div>
  </div>
</template>
  • The idea is simple, since checkboxes are limited in terms of styles, we will visually hide the input so that the user can interact with it but without seeing it. We will also have a pair of divs that will represent both the checked and unchecked state.
  • The checked data property will keep the local state within the component.
  • We'll use the @change event to change the state based on the user interaction.

The behavior

export default {
  data () {
    return {
      checked: this.value
    }
  },
  methods: {
    change () {
      this.checked = !this.checked
      this.$emit('input', this.checked)
    }
  }
}
  • Here the most important part is the change() function that is called every time the user clicks on the component.
  • First we invert the state of the component and then we emit the input event to reflect the new value.

The styles

.m-switch {
  position: relative;
  overflow: hidden;
  width: 58px;
  height: 36px;
  border-radius: 100px;
}

.m-switch__checkbox {
  position: absolute;
  width: 100%;
  height: 100%;
  outline: 0;
  cursor: pointer;
  z-index: 2;
  opacity: 0;
  appearance: none;
}

.m-switch__ui {
  display: flex;
  align-items: center;
  position: absolute;
  width: 100%;
  height: 100%;
  padding: 0 3px;
  background-color: #DDD;
  z-index: 1;
  transition: all linear .2s;
}

.m-switch__handle {
  width: 30px;
  height: 30px;
  background-color: white;
  border-radius: 50%;
  box-shadow: 0 2px 10px 0 rgba(0, 0, 0, 0.2);
  transition: transform linear .2s;
}

.m-switch__checkbox:checked + .m-switch__ui {
  background-color: #21D35B;
}

.m-switch__checkbox:checked + .m-switch__ui .m-switch__handle {
  transform: translateX(calc(100% - 8px));
}
  • The div with the .m-switch class will act as a small container and define the size of the switch.
  • The class .m-switch__checkbox will have the styles to make the checkbox invisible and put it on top so that the user can interact with it.
  • The .m-switch__ui class styles will define the base state of the switch's background, in this case it will have a gray background color.
  • The div with the class .m-switch__handle will act as the indicator that will move from side to side based on the state of the component (left if it is not checked or right if it is).
  • Finally, using the adjacent sibling combinator we change the background color and change the position of the indicator when the switch is checked.

As you can see, making this kind of components with Vue is simple, there is no need to install any library and we have total control.