The Möbius loop, a symbol of endlessness and simplicity, is as mesmerizing in mathematics as it is in design. What if you could bring this geometric marvel to life on the web? In this blog, we’ll demonstrate how to create a beautifully rotating Möbius loop using nothing but HTML and CSS. With clever use of CSS 3D transforms, gradients, and animations, we’ll capture the elegance of this one-sided surface and set it in motion. Whether you’re exploring creative web elements or diving into mathematical art, this project will inspire you to push the boundaries of what CSS can achieve. Let’s get the loop spinning!
I would recommend you don’t just copy and paste the code, just look at the code and type by understanding it.
Demo
See the Pen Rotating Möbius Loop – SCSS by Josetxu (@josetxu) on CodePen.
HTML Code
Starter Template
<!doctype html> <html lang="en"> <head> <!-- Required meta tags --> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <!-- CSS --> <link rel="stylesheet" href="style.css"> <title>Coding Torque</title> </head> <body> <!-- Further code here --> </body> </html>
Paste the below code in your <body>
tag.
- for (i = 0; i < 400; i++) .cam .content .zoom - for (var l=0; l<18; l++) .line .cuboid - for (var s=0; s<6; s++) .side
CSS Code
Create a file style.css and paste the code below.
@import url('https://fonts.googleapis.com/css2?family=Days+One&family=Gluten&display=swap'); * { transform-style: preserve-3d; box-sizing: border-box; } body { margin: 0; padding: 0; width: 100vw; height: 100vh; overflow: hidden; perspective: 100vmin; background: radial-gradient(circle at 50% 100%, #607D8B80, #fff0), radial-gradient(circle at 50% 0%, #607D8B40, #1e0053); background-color: #000; } body:before, body:after { content: "hover to rotate"; position: absolute; width: 100%; text-align: center; text-transform: uppercase; font-family: 'Gluten', Arial, Helvetica, serif; color: #7678bb; text-shadow: 0px -1px 0 #0008, 0px 1px 0 #0008; top: 5vh; left: 0; z-index: -1; } body:after { content: "click & hold to zoom"; top: 95vh; } .content { width: 50vmin; height: 50vmin; left: calc(50% - 25vmin); top: calc(50% - 25vmin); background: #f000; display: flex; align-items: center; justify-content: center; transform: rotateX(40deg); position: absolute; transition: all 0.5s ease 0s; z-index: 1; } .cuboid { --height: 6; --width: 6; --depth: 6; --hue: 250; --sat: 15%; --lum: 45%; height: calc(var(--height) * 1vmin); width: calc(var(--width) * 1vmin); position: absolute; } .cuboid .side { position: absolute; top: 50%; left: 50%; height: 100%; width: 100%; border-radius: 2px; background: hsl(var(--hue), var(--sat), var(--lum)); } .cuboid .side:nth-of-type(1) { transform: translate3d(-50%, -50%, calc(var(--depth) * 0.5vmin)); } .cuboid .side:nth-of-type(2) { transform: translate3d(-50%, -50%, calc(var(--depth) * -0.5vmin)) rotateY(180deg); } .cuboid .side:nth-of-type(3) { width: calc(var(--depth) * 1vmin); transform: translate(-50%, -50%) rotateY(90deg) translate3d(0, 0, calc(var(--width) * 0.5vmin)); --lum: 70%; } .cuboid .side:nth-of-type(4) { width: calc(var(--depth) * 1vmin); transform: translate(-50%, -50%) rotateY(-90deg) translate3d(0, 0, calc(var(--width) * 0.5vmin)); --lum: 70%; } .cuboid .side:nth-of-type(5) { height: calc(var(--depth) * 1vmin); transform: translate(-50%, -50%) rotateX(90deg) translate3d(0, 0, calc(var(--height) * 0.5vmin)); --lum: 20%; } .cuboid .side:nth-of-type(6) { height: calc(var(--depth) * 1vmin); transform: translate(-50%, -50%) rotateX(-90deg) translate3d(0, 0, calc(var(--height) * 0.5vmin)); --lum: 20%; } .cuboid .side:before { content: ""; position: absolute; width: 100%; height: 100%; background: repeating-conic-gradient(#0004 0%, #fff0 .0003%, #fff0 .0005%, #fff0 .00095%), repeating-conic-gradient(#fff2 0%, #fff0 .0005%, #fff0 .0015%, #fff0 .009%); background-size: 100% 101%; } .line { width: 50%; height: 10vmin; position: absolute; left: 0; transform-origin: 100% 50%; } @for $i from 1 through 18 { .line:nth-child(#{$i}) { transform: rotate(($i) * 20deg); .cuboid { transform: rotateY($i * 10deg); animation: spin-#{$i} 6s linear 0s infinite; } @keyframes spin-#{$i} { to { transform: rotateY(($i) * 10deg + 360deg); } } } } .zoom { width: 100%; height:100%; display: flex; align-items: center; justify-content: center; } .cam { width: 5vw; height: 5vh; float: left; box-sizing: border-box; position: relative; z-index: 3; cursor: zoom-in; /*transform: translateZ(0vmin);*/ /*box-shadow: 0 0 1px 0 red inset;*/ @for $i from 1 through 20 { @for $j from 1 through 20 { $key: ($i - 1) * 20 + $j; &:nth-child(#{$key}) { &:hover ~ .content { transform: rotateX(($i - 8) * 10deg + 65) rotateY(($j - 8) * 10deg - 24); } } } } &:active ~ .content .zoom { transform: scale3d(1.75, 1.75, 1.75); transition: all 0.75s ease 0s; } }
Final Output
Written by: Piyush Patil
Code Credits: https://codepen.io/josetxu/pen/poGxZXv
If you found any mistakes or have any doubts please feel free to Contact Us
Hope you find this post helpful💖