Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
An example of a toggle switch with Vue 3
<template>
<label class="container">
<input
v-bind="$attrs"
class="input"
type="checkbox"
:checked="checked"
@change="$emit('update:checked', $event.target.checked)"
/>
<span class="switch"></span>
<span class="label">{{ label }}</span>
</label>
</template>
<script>
export default {
name: "Switch",
props: {
label: {
type: String,
required: true,
},
checked: {
type: Boolean,
required: true,
},
},
};
</script>
<style scoped>
.container {
cursor: pointer;
display: flex;
align-items: center;
}
.label {
margin-left: 12px;
color: #1a202c;
/* Show an ellipsis if the text takes more than one line */
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
/* Visually hide the checkbox input */
.input {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border-width: 0;
}
.switch {
--switch-container-width: 50px;
--switch-size: calc(var(--switch-container-width) / 2);
--light-gray: #e2e8f0;
--gray: #cbd5e0;
--dark-gray: #a0aec0;
--teal: #4fd1c5;
--dark-teal: #319795;
/* Vertically center the inner circle */
display: flex;
align-items: center;
position: relative;
height: var(--switch-size);
flex-basis: var(--switch-container-width);
/* Make the container element rounded */
border-radius: var(--switch-size);
background-color: var(--light-gray);
/* In case the label gets really long, the toggle shouldn't shrink. */
flex-shrink: 0;
transition: background-color 0.25s ease-in-out;
}
.switch::before {
content: "";
position: absolute;
/* Move a little bit the inner circle to the right */
left: 1px;
height: calc(var(--switch-size) - 4px);
width: calc(var(--switch-size) - 4px);
/* Make the inner circle fully rounded */
border-radius: 9999px;
background-color: white;
border: 2px solid var(--light-gray);
transition: transform 0.375s ease-in-out;
}
.input:checked + .switch {
background-color: var(--teal);
}
.input:checked + .switch::before {
border-color: var(--teal);
/* Move the inner circle to the right */
transform: translateX(
calc(var(--switch-container-width) - var(--switch-size))
);
}
.input:focus + .switch::before {
border-color: var(--gray);
}
.input:focus:checked + .switch::before {
border-color: var(--dark-teal);
}
.input:disabled + .switch {
background-color: var(--gray);
}
.input:disabled + .switch::before {
background-color: var(--dark-gray);
border-color: var(--dark-gray);
}
</style>
@hobbeschild

This comment has been minimized.

Copy link

@hobbeschild hobbeschild commented Apr 8, 2021

Thomas, this is brilliant and served my purposes perfectly. However, it doesn't render in IE11 (one dinosaur client I'm afraid). Any ideas why that might be? I am guessing one of the CSS directives is not compliant, but as I am not an expert in CSS it is not obvious to me.

@thomaslombart

This comment has been minimized.

Copy link
Owner Author

@thomaslombart thomaslombart commented Apr 8, 2021

Thomas, this is brilliant and served my purposes perfectly. However, it doesn't render in IE11 (one dinosaur client I'm afraid). Any ideas why that might be? I am guessing one of the CSS directives is not compliant, but as I am not an expert in CSS it is not obvious to me.

@hobbeschild Thanks for your feedback! I bet it's because of the CSS variables (for example var(--switch-size)) which are not available in IE 11 (https://caniuse.com/css-variables). To fix it, you have different choices:

  • Remove the variables and duplicate the properties everywhere
  • Use a preprocessor like Sass to still be able to use variables (in the end Sass will compile to CSS)
  • Tell your client that IE11 has less and less market share and that it'll soon be pointless (if it's not already the case) to support it 😄

Let me know if it helps.

@hobbeschild

This comment has been minimized.

Copy link

@hobbeschild hobbeschild commented Apr 10, 2021

Thomas, this is brilliant and served my purposes perfectly. However, it doesn't render in IE11 (one dinosaur client I'm afraid). Any ideas why that might be? I am guessing one of the CSS directives is not compliant, but as I am not an expert in CSS it is not obvious to me.

@hobbeschild Thanks for your feedback! I bet it's because of the CSS variables (for example var(--switch-size)) which are not available in IE 11 (https://caniuse.com/css-variables). To fix it, you have different choices:

  • Remove the variables and duplicate the properties everywhere
  • Use a preprocessor like Sass to still be able to use variables (in the end Sass will compile to CSS)
  • Tell your client that IE11 has less and less market share and that it'll soon be pointless (if it's not already the case) to support it 😄

Let me know if it helps.

I changed to Sass variables and it works fine! Thank you for the tip. :) Believe me those IE11 arguments have been tried.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment