Tailwind & Vue turorial: Build your own custom "switch" cover image

Tailwind & Vue turorial: Build your own custom "switch"

Stratulat Alexandru • January 12, 2019

tutorial tailwind vue

Building custom components with Vue is already a breeze, but once you add Tailwind, things get really cool. I'm getting ready to publish a series of short go-through tutorials to show you how to build dropdowns, dialogs, sliders, tooltips, progress bars, snackbars, and everything else that is a must in a modern application. Stay tuned!

Here is what we're going to build (examples are interactive):

Let's start by creating a new file called, let's say VSwitch.vue.

1. The main container

<template>
  <div class="w-12 h-6 rounded-full shadow bg-grey inline-block"></div>
</template>

Breakdown of the classes:

  • w-12 Width 3rem
  • h-6 Height 1.5rem
  • rounded-full Fully rounded corners
  • shadow Basic shadow
  • bg-grey Grey background
  • inline-block Display inline block

2. The switch

<template>
  <div class="w-12 h-6 rounded-full shadow bg-grey inline-block">
    <div class="w-1/2 h-full rounded-full shadow bg-white"></div>
  </div>
</template>

Breakdown of the classes:

  • w-1/2 Width 50%
  • h-full Height 100%
  • rounded-full Fully rounded corners
  • shadow Basic shadow
  • bg-white White background

3. The value prop

To be able to use v-model on the component like this:

<v-switch v-model="someVariable" />

specify a value prop inside the component.

<script>
export default {
  props: {
    value: {
      type: Boolean,
      required: true,
    },
  },
};
</script>

By default, to trigger updates on the v-model variable from inside a component, we have to emit an input event. It doesn't sound quite good in context of a "switch", so we'll rename the event to change.

Example:

<script>
export default {
  model: {
    event: 'change',
  },
  props: {
    value: {
      type: Boolean,
      required: true,
    },
  },
};
</script>

Now just emit the change event when our switch is clicked:

<template>
  <div
    class="w-12 h-6 rounded-full shadow bg-grey inline-block"
    @click="$emit('change', !value)"
  >
    <div class="w-1/2 h-full rounded-full shadow bg-white"></div>
  </div>
</template>

4. Active background

Let's make the background green when the switch is active.

<template>
  <div
    :class="value ? 'bg-green' : 'bg-grey'"
    class="w-12 h-6 rounded-full shadow inline-block"
    @click="$emit('change', !value)"
  >
    <div class="w-1/2 h-full rounded-full shadow bg-white"></div>
  </div>
</template>

Notice the binded :class. It has a condition which returns the class bg-green (background green) or bg-grey (background grey) based on the value.

4. Switch position

To move the switch, we'll use transform, because it is animatable.

<template>
  <div
    :class="value ? 'bg-green' : 'bg-grey'"
    class="w-12 h-6 rounded-full shadow inline-block"
    @click="$emit('change', !value)"
  >
    <div
      :style="{ transform: `translateX(${value ? 100 : 0}%)` }"
      class="w-1/2 h-full bg-white rounded-full shadow"
    />
  </div>
</template>

Notice that we added a style to the switch. translateX will be either 100% or 0%, based on the value.

Full Example

The last thing I would add to the container classes is cursor-pointer.

<template>
  <div
    :class="value ? 'bg-green' : 'bg-grey'"
    class="w-12 h-6 rounded-full shadow inline-block cursor-pointer"
    @click="$emit('change', !value)"
  >
    <div
      :style="{ transform: `translateX(${value ? 100 : 0}%)` }"
      class="w-1/2 h-full bg-white rounded-full shadow"
    />
  </div>
</template>

<script>
export default {
  model: {
    event: 'change',
  },
  props: {
    value: {
      type: Boolean,
      required: true,
    },
  },
};
</script>

Note: In this example we didn't cover transitions, since they aren't available in Tailwind by default. I recommend this Tailwind plugin glhd-tailwindcss-transitions. After installation you can use the transition class on the container and the switch.

Sign up for new posts

No spam. Unsubscribe at any time.