Toggle Button In Css With Stretchable Elastic Effect

Toggle Button In Css With Stretchable Elastic Effect
Code Snippet:Stretchable Elastic Toggle - CSS
Author: Josetxu
Published: 3 weeks ago
Last Updated: October 28, 2025
Downloads: 49
License: MIT
Edit Code online: View on CodePen
Read More

Creating an engaging and visually appealing toggle button can enhance user experience. This tutorial will guide you through the process of creating a toggle button in CSS with a stretchable elastic effect, adding a unique and interactive element to your web projects.

Step 1: Set Up the Basic HTML Structure

First, we need to construct the basic HTML structure for our toggle button. This involves creating a div that will hold the checkbox input and a label that will act as the toggle.

<div class="toggle">
	<input type="checkbox" id="btn">
	<label for="btn">
		<span class="thumb"></span>
	</label>
</div>

Step 2: Add CSS Styling for the Toggle Button

Now, let’s move on to styling our toggle button. We will use CSS to create the visual appearance and the elastic effect. First we add google fonts.

@import url('https://fonts.googleapis.com/css2?family=Varela+Round&display=swap');

:root {
	--sz: 10vmin;
	--on: #FF9800;
	--off: #243747;
	--bg: linear-gradient(135deg, #17212f, #11151e);
	--tr: all 0.5s ease 0s;
	--elastic: linear(0 0%, 0.22 2.1%, 0.86 6.5%, 1.11 8.6%, 1.3 10.7%, 1.35 11.8%, 1.37 12.9%, 1.37 13.7%, 1.36 14.5%, 1.32 16.2%, 1.03 21.8%, 0.94 24%, 0.89 25.9%, 0.88 26.85%, 0.87 27.8%, 0.87 29.25%, 0.88 30.7%, 0.91 32.4%, 0.98 36.4%, 1.01 38.3%, 1.04 40.5%, 1.05 42.7%, 1.05 44.1%, 1.04 45.7%, 1 53.3%, 0.99 55.4%, 0.98 57.5%, 0.99 60.7%, 1 68.1%, 1.01 72.2%, 1 86.7%, 1 100%);
}	

* {
	box-sizing: border-box;
	transition: var(--tr);
	animation-play-state: paused;
}

body {
	margin: 0;
	padding: 0;
	width: 100vw;
	height: 100vh;
	overflow: hidden;
	display: flex;
	align-items: center;
	justify-content: center;
	background: var(--bg);
}

body:before, body:after {
	content: "";
	position: absolute;
	width: 100%;
	height: 100%;
	background: 
		repeating-conic-gradient(#0002 0.000095%, #fff0 .0005%, #fff0 .005%, #fff0 .0005%), 
		repeating-conic-gradient(#0002 0.00001%, #fff0 .00009%, #fff0 .00075%, #fff0 .000025%);
	opacity: 0.75;
	filter: blur(0.75px);
}

.toggle  {
	position: relative;
	width: calc(var(--sz) * 4);
	height: calc(var(--sz) * 2);
	display: flex;
	align-items: center;
	justify-content: center;
}

input {
	display: none;
}

label[for=btn] {
	position: absolute;
	width: calc(var(--sz) * 4);
	height: calc(var(--sz) * 2);
	background: linear-gradient(0deg, #121720, #0d1217);
	border-radius: var(--sz);
	box-shadow: 0 0 calc(var(--sz) / 50) calc(var(--sz) / 50) #0006, 0 calc(var(--sz) * -0.05) calc(var(--sz) / 10) calc(var(--sz) / 500) #0b0b10, 0 0 calc(var(--sz) / 10) calc(var(--sz) / 50) #b9e1ff88, 0 calc(var(--sz) * -0.05) calc(var(--sz) / 5) calc(var(--sz) / 50) #15182fcc;
}	

.thumb {
	position: absolute;
	height: calc(calc(var(--sz) * 2) - calc(var(--sz) / 8));
	top: calc(calc( var(--sz) / 10) + calc(var(--sz) / -20));
	background: 
		repeating-conic-gradient(#0002 0.000095%, #fff0 .0005%, #fff0 .005%, #fff0 .0005%), 
		repeating-conic-gradient(#0002 0.00001%, #fff0 .00009%, #fff0 .00075%, #fff0 .000025%),
		var(--bg);
	border-radius: var(--sz);
	box-shadow: 
		0 calc(var(--sz) * -0.05) calc(var(--sz) * 0.05) 0 #000c inset, 0 calc(var(--sz) * 0.05) calc(var(--sz) * 0.05) 0 #fff2 inset,     0 0 calc(var(--sz) / 10) calc(var(--sz) / 50) #000c,     0 calc(var(--sz) / 3) calc(var(--sz) / 3) 0 #000d;
	cursor: pointer;
	display: flex;
	align-items: center;
	justify-content: flex-start;
	z-index: 1;
	overflow: hidden;
	padding: calc(var(--sz)* 0.65);  
	transition: var(--tr); 
	animation: go-left 1s ease 0s;
	width: calc(var(--sz)* 1.875); 
	right: calc(var(--sz)* 2.05); 
}

#btn:checked + label .thumb {
	transition: var(--tr); 
	animation: go-right 1s ease 0s;
	width: calc(var(--sz)* 1.875); 
	right: calc(var(--sz)* 0.075); 
	justify-content: flex-end;
}


@keyframes go-left {
	0%   { 
		width: calc(var(--sz)* 1.875); 
		right: calc(var(--sz)* 0.075); 
	}
	40%, 60%  { 
		width: calc(var(--sz)* 3.85); 
		right: calc(var(--sz)* 0.075); 
	}
	100% { 
		width: calc(var(--sz)* 1.875); 
		right: calc(var(--sz)* 2.05);  
	}
}


@keyframes go-right {
	0%   { 
		width: calc(var(--sz)* 1.875); 
		right: calc(var(--sz)* 2.05);  
	}
	40%, 60%  { 
		width: calc(var(--sz)* 3.85); 
		right: calc(var(--sz)* 0.075); 
	}
	100% { 
		width: calc(var(--sz)* 1.875); 
		right: calc(var(--sz)* 0.075); 
	}
}


label[for=btn]:before, 
label[for=btn]:after {
	--clr: var(--on);
	content: "ON";
	color: #fff;
	font-family: 'Varela Round', serif;
	width: 50%;
	float: left;
	text-align: center;
	display: flex;
	justify-content: center;
	height: 100%;
	font-size: calc(var(--sz)* 0.75);
	padding: 0 0 0 calc(var(--sz)* 0.2);
	box-sizing: border-box;
	transform-origin: 100% 50%;
	animation: muelle-on 1.5s var(--elastic) 0.5s;
	color: var(--clr);
	text-shadow: 0 0 calc(var(--sz) * 0.1) var(--clr), 0 0 calc(var(--sz) * 0.3) #000, 0 0 calc(var(--sz) * 0.5) var(--clr), 0 calc(var(--sz) * 0.0125) calc(var(--sz) * 0.05) #233443, 0 calc(var(--sz) * -0.0125) calc(var(--sz) * 0.05) #000;
	align-items: center;
	line-height: calc(var(--sz) * 0.55);
}

label[for=btn]:after {
	content: "OFF";
	padding: 0 calc(var(--sz) * 0.325) 0 0;
	transform-origin: 0% 50%;
	--clr: var(--off);
	text-shadow: 0 calc(var(--sz) * 0.0125) calc(var(--sz) * 0.05) #233443, 0 calc(var(--sz) * -0.0125) calc(var(--sz) * 0.05) #000;
}

#btn:checked + label[for=btn]:before {
	animation-name: muelle-off; 
}

#btn:checked + label[for=btn]:after {
	animation: muelle-off 1.5s var(--elastic) 0.5s; 
}

@keyframes muelle-on {
	0% { transform: scaleX(0.35); }
	100% { transform: scaleX(1); }
}

@keyframes muelle-off {
	0% { transform: scaleX(0.35); }
	100% { transform: scaleX(1); }
}


/* light */
span.thumb:before {
	content: "";
	background: #121212;
	position: relative;
	width: calc(var(--sz) / 1.75);
	height: calc(var(--sz) / 1.75);
	border-radius: var(--sz);
	box-shadow: 0 0 calc(var(--sz) / 50) calc(var(--sz) / 50) #0008, 0 calc(var(--sz) * -0.05) calc(var(--sz) / 10) calc(var(--sz) / 500) #000, 0 calc(var(--sz) * 0.025) calc(var(--sz) / 10) calc(var(--sz) / 500) #fff8, 0 0 calc(var(--sz) / 20) calc(var(--sz) / 25) #000;
}

span.thumb:after {
	content: "";
	transition: var(--tr);transition: var(--tr);
	width: calc(var(--sz) / 1.75);
	height: calc(var(--sz) / 1.75);
	position: absolute;
	border-radius: var(--sz);
	--clr: var(--off);
	--shn: #fff8;
	box-shadow: 
		0 0 0 calc(var(--sz) * 0.025) #000c inset, 
		0 0 calc(var(--sz) / 2.5) 0 var(--clr), 
		0 0 calc(var(--sz) / 3) calc(var(--sz) / 20) var(--clr) inset, 
		0 calc(var(--sz) / -20) calc(var(--sz) / 10) calc(var(--sz) / 10) #000c inset;
	background: radial-gradient(circle at 50% 32%, var(--shn) 0 calc(var(--sz) / 20), var(--clr) calc(var(--sz) / 3) calc(var(--sz) / 3));
}

#btn:checked + label span.thumb:after {
	--clr: var(--on);
	--shn: #fff;
}

Step 3: Implementing the Elastic Effect with Keyframes

The core of the stretchable elastic effect lies in the keyframe animations within the CSS. We define animations for both the ‘on’ and ‘off’ states of the toggle, creating the illusion of elasticity when the state changes.

Step 4: Enhancing the Visual Appeal with Pseudo-elements

We can further enhance the visual appeal of the toggle button by using pseudo-elements (`::before` and `::after`) to add the “ON” and “OFF” text labels. These labels will also incorporate animations to synchronize with the elastic effect.

Step 5: Add light Effect

Enhance toggle thumb button with a light effect by using pseudo-elements (`::before` and `::after`).

By following these steps, you should now have a functional and visually appealing toggle button with a stretchable elastic effect. Feel free to customize the colors, sizes, and animation timings to match your specific design requirements.

Related posts:

Loading... ...

Loading preview...

Device: Desktop
Dimensions: 1200x800
Lines: 0 Characters: 0 Ln 1, Ch 1

Leave a Comment

About W3Frontend

W3Frontend provides free, open-source web design code and scripts to help developers and designers build faster. Every snippet is reviewed before publishing for quality. Learn more.