Skip to content

Toggle Switch

INFO

This page has not yet been updated to use the defineModel macro, which was added in Vue 3.4. The techniques described here should still work, but in some cases it might be better to use defineModel instead.

Toggle Switch Example

Using a toggle switch should be very similar to using a checkbox:

vue
<template>
  <basic-toggle-switch v-model="switchValue" />
  <pre>Bound value: {{ switchValue }}</pre>
</template>
<script setup>
import { ref } from 'vue'
import BasicToggleSwitch from './toggle-switch.vue'

const switchValue = ref(true)
</script>
<template>
  <basic-toggle-switch v-model="switchValue" />
  <pre>Bound value: {{ switchValue }}</pre>
</template>
<script setup>
import { ref } from 'vue'
import BasicToggleSwitch from './toggle-switch.vue'

const switchValue = ref(true)
</script>

v-model is used to achieve a two-way data binding on the data value held in the parent.

Live Example
Bound value: true

SFC Playground

The implementation includes a lot of CSS, but it is otherwise very similar to a checkbox:

vue
<template>
  <div
    class="toggle-switch"
    :class="{ checked: modelValue }"
    @click="toggle"
  />
</template>

<script setup>
const props = defineProps({
  modelValue: {
    required: true,
    type: Boolean
  }
})

const emit = defineEmits(['update:modelValue'])

const toggle = () => {
  emit('update:modelValue', !props.modelValue)
}
</script>

<style scoped>
.toggle-switch {
  background: #ddd;
  border-radius: 0.75em;
  box-shadow: 0.0625em 0.0625em 0.0625em rgba(0, 0, 0, 0.08) inset;
  cursor: pointer;
  flex: none;
  height: 1.5em;
  position: relative;
  transition: background-color 150ms;
  width: 3em;
}

.toggle-switch::before {
  background: #fff;
  background-image: radial-gradient(circle at 0.375em 0.375em, rgba(0, 0, 0, 0) 0, rgba(0, 0, 0, 0.05) 1em);
  border-radius: 0.625em;
  box-shadow: 0.0625em 0.0625em 0.0625em rgba(0, 0, 0, 0.08);
  content: "";
  display: block;
  height: 1.25em;
  left: 0.125em;
  position: absolute;
  top: 0.125em;
  transition: left 150ms;
  width: 1.25em;
  will-change: left;
}

.checked {
  background-color: #aac3f2;
}

.checked::before {
  background-image: radial-gradient(circle at 0.375em 0.375em, rgba(0, 0, 0, 0) 0, rgba(0, 0, 0, 0.05) 1em);
  left: 1.625em;
}

.toggle-switch:hover {
  box-shadow: 0.0625em 0.0625em 0.125em rgba(0, 0, 0, 0.12) inset;
}

.toggle-switch:hover::before {
  background-image: radial-gradient(circle at 0.375em 0.375em, rgba(0, 0, 0, 0) 0, rgba(0, 0, 0, 0.0375) 1em);
  box-shadow: 0.0625em 0.0625em 0.0625em rgba(0, 0, 0, 0.12);
}
</style>
<template>
  <div
    class="toggle-switch"
    :class="{ checked: modelValue }"
    @click="toggle"
  />
</template>

<script setup>
const props = defineProps({
  modelValue: {
    required: true,
    type: Boolean
  }
})

const emit = defineEmits(['update:modelValue'])

const toggle = () => {
  emit('update:modelValue', !props.modelValue)
}
</script>

<style scoped>
.toggle-switch {
  background: #ddd;
  border-radius: 0.75em;
  box-shadow: 0.0625em 0.0625em 0.0625em rgba(0, 0, 0, 0.08) inset;
  cursor: pointer;
  flex: none;
  height: 1.5em;
  position: relative;
  transition: background-color 150ms;
  width: 3em;
}

.toggle-switch::before {
  background: #fff;
  background-image: radial-gradient(circle at 0.375em 0.375em, rgba(0, 0, 0, 0) 0, rgba(0, 0, 0, 0.05) 1em);
  border-radius: 0.625em;
  box-shadow: 0.0625em 0.0625em 0.0625em rgba(0, 0, 0, 0.08);
  content: "";
  display: block;
  height: 1.25em;
  left: 0.125em;
  position: absolute;
  top: 0.125em;
  transition: left 150ms;
  width: 1.25em;
  will-change: left;
}

.checked {
  background-color: #aac3f2;
}

.checked::before {
  background-image: radial-gradient(circle at 0.375em 0.375em, rgba(0, 0, 0, 0) 0, rgba(0, 0, 0, 0.05) 1em);
  left: 1.625em;
}

.toggle-switch:hover {
  box-shadow: 0.0625em 0.0625em 0.125em rgba(0, 0, 0, 0.12) inset;
}

.toggle-switch:hover::before {
  background-image: radial-gradient(circle at 0.375em 0.375em, rgba(0, 0, 0, 0) 0, rgba(0, 0, 0, 0.0375) 1em);
  box-shadow: 0.0625em 0.0625em 0.0625em rgba(0, 0, 0, 0.12);
}
</style>

An individual toggle switch represents a choice between two values. This is effectively the same as a Checkbox (checked/unchecked) or a Toggle Button (pressed/unpressed).

Multiple toggle switches can be used to model multiple selections, often represented using an Array or Set containing the selected values. This can also be represented using a list, like a <select multiple>. Some dropdowns also support multiple selections, often in combination with a tag/chip/pill component to show the selected values when the list is collapsed.

Libraries

Various libraries include a toggle switch component, including: