3D Switch in CSS
3D Switch in CSS

Hy Everyone, In this tutorial we will learn to create a 3d switch in CSS. This 3D switch will be built using HTML & CSS, no Javascript knowledge is required. A switch is useful for Dark and Light theme modes. Let’s Learn with the code!

Table of Contents

3D Switch in CSS

Here we will create two files called index.html and style.css. Let’s start with our first file index.html.

index.html

<!DOCTYPE html>
<head>
  <title>3D Switch in CSS</title>
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <label class="switch">
  <input type="checkbox" checked/>
  <div class="indicator left"></div>
  <div class="indicator right"></div>
  <div class="button"></div>
</label>
</body>
</html>

As you can see we have two indicator classes for left and right. In the Below Image orange part is our class=” indicator left” and the gray part is our class=” indicator right”.

Left and right parts of the button

After Class Button, it will look like this.

After Adding Button

For the True and false conditions we are using the checkbox it’s default value is chacked it means true.

<input type="checkbox" checked/>

It’s all our simple HTML code, Let’s move to our style.css file.

style.css

First, we will define the common height and width for body and HTML.

body, html {
  width: 100vw;
  height: 100vh;
}

Now write the separate code for a body like background, display type, item alignment, etc.

we have created five variables –hue, –width, –accent-hue, –duration, –easing, and you can see their values and change according to you.

body {
  background: white;
  display: flex;
  align-items: center;
  justify-content: center;
  --hue: 220deg;
  --width: 23rem;
  --accent-hue: 22deg;
  --duration: 0.6s;
  --easing: cubic-bezier(1, 0, 1, 1);
}

Now we will write the code for the input element.

input {
  display: none;
}

as you can see in the input our display is none, what if you do not set its value to none. It will look like this. It will show the checkbox icon. So for that reason, we set its value to none.

without input { display:none; }

Let’s write the code for the switch class.


.switch {
  --shadow-offset: calc(var(--width) / 20);
  position: relative;
  cursor: pointer;
  display: flex;
  align-items: center;
  width: var(--width);
  height: calc(var(--width) / 2.5);
  border-radius: var(--width);
  box-shadow: 
    inset 10px 10px 10px hsl(var(--hue) 20% 80%),
    inset -10px -10px 10px hsl(var(--hue) 20% 93%);
}

here we used calc function in –shadow offset, calc is used to calculate the width of an element. After that, we used display flex,
A flex container expands items to fill available free space or shrinks them to prevent overflow.

At the end, we used box-shadow value as inset,
The inset CSS property is a shorthand that corresponds to the top, right, bottom, and/or left properties. It has the same multi-value syntax as the margin shorthand.

.indicator {
  content: '';
  position: absolute;
  width: 40%;
  height: 60%;
  transition: all var(--duration) var(--easing);
  box-shadow: 
    inset 0 0 2px hsl(var(--hue) 20% 15% / 60%),
    inset 0 0 3px 2px hsl(var(--hue) 20% 15% / 60%),
    inset 0 0 5px 2px hsl(var(--hue) 20% 45% / 60%);
}

In indicator class, for transition-duration, we are using var(–duration) and var(–easing) variables, as we defined earlier in the body style element.

Now create the code for the left and right indicator classes.

.indicator.left {
  --hue: var(--accent-hue);
  overflow: hidden;
  left: 10%;
  border-radius: 100px 0 0 100px;
  background: linear-gradient(180deg, hsl(calc(var(--accent-hue) + 20deg) 95% 80%) 10%, hsl(calc(var(--accent-hue) + 20deg) 100% 60%) 30%, hsl(var(--accent-hue) 90% 50%) 60%, hsl(var(--accent-hue) 90% 60%) 75%, hsl(var(--accent-hue) 90% 50%));
}

.indicator.left::after {
  content: '';
  position: absolute;
  opacity: 0.6;
  width: 100%;
  height: 100%;
  background: url("data:image/svg+xml;base64,PHN2ZwogIHhtbG5zPSdodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZycKICB4bWxuczp4bGluaz0naHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluaycKICB3aWR0aD0nNTAwJyBoZWlnaHQ9JzUwMCc+CgogICAgPGZpbHRlciBpZD0nbm9pc2UnIHg9JzAnIHk9JzAnPgogICAgICA8ZmVUdXJidWxlbmNlCiAgICAgICAgdHlwZT0nZnJhY3RhbE5vaXNlJwogICAgICAgIGJhc2VGcmVxdWVuY3k9JzAuNjUnCiAgICAgICAgbnVtT2N0YXZlcz0nMycKICAgICAgICBzdGl0Y2hUaWxlcz0nc3RpdGNoJwogICAgICAvPgogICAgICA8ZmVCbGVuZCBtb2RlPSJzY3JlZW4iLz4KICAgIDwvZmlsdGVyPgoKICAgIDxyZWN0IHdpZHRoPSc1MDAnIGhlaWdodD0nNTAwJyBmaWx0ZXI9InVybCgjbm9pc2UpIiBvcGFjaXR5PScwLjUnLz4KPC9zdmc+");
}

.indicator.right {
  right: 10%;
  border-radius: 0 100px 100px 0;
  background-image: linear-gradient(180deg, hsl(var(--hue) 20% 95%), hsl(var(--hue) 20% 65%) 60%, hsl(var(--hue) 20% 70%) 70%, hsl(var(--hue) 20% 65%));
}

Our both left and right indicator are created, Now it’s time to create a button. 😍


.button {
  position: absolute;
  z-index: 1;
  width: 55%;
  height: 80%;
  left: 5%;
  border-radius: 100px;
  background-image: linear-gradient(160deg, hsl(var(--hue) 20% 95%) 40%, hsl(var(--hue) 20% 65%) 70%);
  transition: all var(--duration) var(--easing);
  box-shadow:
    2px 2px 3px hsl(var(--hue) 18% 50% / 80%),
    2px 2px 6px hsl(var(--hue) 18% 50% / 40%),
    10px 20px 10px hsl(var(--hue) 18% 50% / 40%),
    20px 30px 30px hsl(var(--hue) 18% 50% / 60%);
}

.button::before, 
.button::after {
  content: '';
  position: absolute;
  top: 10%;
  width: 41%;
  height: 80%;
  border-radius: 100%;
}

.button::before {
  left: 5%;
  box-shadow: inset 1px 1px 2px hsl(var(--hue) 20% 85%);
  background-image: linear-gradient(-50deg, hsl(var(--hue) 20% 95%) 20%, hsl(var(--hue) 20% 85%) 80%);
}

.button::after {
  right: 5%;
  box-shadow: inset 1px 1px 3px hsl(var(--hue) 20% 70%);
  background-image: linear-gradient(-50deg, hsl(var(--hue) 20% 95%) 20%, hsl(var(--hue) 20% 75%) 80%);
}

::before and ::after pseudo-elements. If you don’t know how to use it then read our previous post CSS before and after pseudo-elements.

The linear-gradient() function sets a linear gradient as the background image. We will discuss this in detail in our CSS Course later.

input:checked ~ .button {
  left: 40%;
}

input:not(:checked) ~ .indicator.left,
input:checked ~ .indicator.right {
  box-shadow: 
    inset 0 0 5px hsl(var(--hue) 20% 15% / 100%),
    inset 20px 20px 10px hsl(var(--hue) 20% 15% / 100%),
    inset 20px 20px 15px hsl(var(--hue) 20% 45% / 100%);
}

What is the use of tilde (~) in CSS?

If we want to set a background color for all <ul> elements that are preceded by an <p> element with the same parent.

You can Live run it with an Example, Click on the Play button at the top of the code:

<!DOCTYPE html>
<html>
<head>
<style> 
p ~ ul {
  background: #454545;
  color:white;
}
</style>
</head>
<body>

<div>A div element.</div>
<ul>
  <li>Coffee</li>
  <li>Tea</li>
  <li>Milk</li>
</ul>

<p>The first paragraph.</p>
<ul>
  <li>Coffee</li>
  <li>Tea</li>
  <li>Milk</li>
</ul>

<h2>Another list</h2>
<ul>
  <li>Coffee</li>
  <li>Tea</li>
  <li>Milk</li>
</ul>

</body>
</html>

The tilde (~) selects the element with the same parent.

If you are having any issues with this code, then visit our GitHub Account Click Here!

You Might like this:


Hope You like this blog. Thanks for reading!

Oh, hi there 👋 It’s nice to meet you.

Sign up to receive awesome content in your inbox, every week.

We don’t spam! Read our privacy policy for more info.

Leave a Reply