Crafting a 3D Sphere, Cubes, and Intersection Using CSS

Share your love

Bring geometry to life in your browser by creating mesmerizing 3D shapes and intersections with CSS! In this blog, we’ll explore how to design a 3D sphere, cubes, and their dynamic intersections—all using pure CSS. By mastering CSS 3D transforms, perspective, and lighting effects, we’ll construct visually stunning shapes that interact and overlap, showcasing the beauty of geometry. Whether you’re looking to enhance your web animations or dive into advanced CSS design, this tutorial will spark your creativity. Let’s intersect design and innovation—one shape at a time!

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 CSS – 3D – Sphere – Cubes – Intersection (No JS) by Konstantin Denerz (@konstantindenerz) 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.

<div class="wrapper">
<div class="container">
    <div class="wall">
        <div class="surface"></div>
        <div class="surface"></div>
        <div class="left"></div>
        <div class="top"></div>
    </div>
    <div class="wall">
        <div class="surface"></div>
        <div class="surface"></div>
        <div class="left"></div>
        <div class="top"></div>
    </div>
    <div class="wall">
        <div class="surface"></div>
        <div class="surface"></div>
        <div class="left"></div>
        <div class="top"></div>
    </div>
    <div class="wall">
        <div class="surface"></div>
        <div class="surface"></div>
        <div class="left"></div>
        <div class="top"></div>
    </div>
    <div class="wall">
        <div class="surface"></div>
        <div class="surface"></div>
        <div class="left"></div>
        <div class="top"></div>
    </div>
    <div class="wall">
        <div class="surface"></div>
        <div class="surface"></div>
        <div class="left"></div>
        <div class="top"></div>
    </div>
    <div class="ball-container">
        <div class="ball"></div>
    </div>
</div>
  </div>

CSS Code 

Create a file style.css and paste the code below.

// @property rule (CSS Future Tip 🔮): https://drafts.css-houdini.org/css-properties-values-api/

// 🔥 cos(): https://web.dev/css-trig-functions/
@property --angle {
  syntax: "<angle>";
  inherits: true;
  initial-value: 0deg;
}

@property --circle-diameter {
  syntax: "<length>";
  inherits: true;
  initial-value: 0;
}

$walls: 6;
$half: $walls / 2;
$surfaces: $walls * 2;

:root {
  --color-background: conic-gradient(
    black,
    #192d39,
    #0e1e2e,
    #281133,
    #14293d,
    #16031a,
    black
  );
  --color-on-background: white;

  --c1: #6eccee;
  --c2: #ffdc99;
  --c3: #e3a4d0;
  --c4: #d455ff;
  --animation-duration: 2.8s;
  --border-width: 0.6vmin;
  --glow: drop-shadow(0 0 6vmin rgba(255, 255, 255, 0.19));

  --hole-pos-y: 20%;
  --hole-radius: 22vmin;
  --offset-per-surface: calc(360deg / 24);
}

.container {
  position: relative;
  width: 50vmin;
  aspect-ratio: 1/1.2;
  --angle: 30deg;
  animation: angle var(--animation-duration) linear infinite;
  transform-style: preserve-3d;
  transform: rotateX(-45deg) rotateY(45deg);
}

.wall {
  position: absolute;
  inset: 0;
  --wall-gap: 10vmin;
  filter: var(--glow);
  $surfaceIndex: 0;
  @for $i from 1 through $walls {
    $index: $i - 3;
    $surfaceIndex: $surfaceIndex + 1;

    &:nth-of-type(#{$i}) {
      transform: translateZ(calc(var(--wall-gap) * #{$index - 1}));
      --index: #{$i};

      .surface,
      .top {
        --index: #{$surfaceIndex};

        &:nth-child(2) {
          $surfaceIndex: $surfaceIndex + 1;
          --index: #{$surfaceIndex};
        }
      }
    }
  }
}

.surface {
  position: absolute;
  inset: 0;
  --angle-offset: calc(var(--index) * var(--offset-per-surface));
  --circle-diameter: calc(
    var(--hole-radius) * cos(calc(var(--angle) + var(--angle-offset)))
  );
  -webkit-mask: radial-gradient(
    circle at 50% var(--hole-pos-y),
    transparent var(--circle-diameter),
    black var(--circle-diameter)
  );
  mask: radial-gradient(
    circle at 50% var(--hole-pos-y),
    transparent var(--circle-diameter),
    black var(--circle-diameter)
  );
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-size: 100% 100%;
  mask-size: 100% 100%;
  -webkit-mask-position: 0 0;
  mask-position: 0 0;
  background: radial-gradient(
      circle at 50% var(--hole-pos-y),
      var(--c4) calc(var(--circle-diameter) + var(--border-width)),
      var(--c4) calc(var(--circle-diameter) + var(--border-width)),
      transparent var(--circle-diameter)
    ),
    linear-gradient(black, black),
    linear-gradient(
      45deg,
      var(--c1),
      var(--c3),
      var(--c2),
      var(--c1),
      var(--c4),
      var(--c3),
      var(--c2)
    );
  background-repeat: no-repeat;
  background-size: 100% 100%,
    calc(100% - var(--border-width) * 2) calc(100% - var(--border-width) * 2),
    100%, 100%;
  background-position: 0 0, var(--border-width) var(--border-width), 0 0;

  &:nth-child(2) {
    --circle-diameter: calc(
      var(--hole-radius) * cos(calc(var(--angle) + var(--angle-offset)))
    );
    transform: translate(4vmin, 5.7vmin);
  }
}

.left {
  position: absolute;
  transform: skewY(55deg) translateY(2.9vmin);
  inset: 0;
  width: 4.5vmin;
  background: linear-gradient(black, black) no-repeat,
    linear-gradient(to top, var(--c1), var(--c3), var(--c2), var(--c1))
      no-repeat;
  background-size: calc(100% - var(--border-width) * 2)
      calc(100% - var(--border-width) * 2),
    100%, 100%;
  background-position: var(--border-width) var(--border-width), 0 0;
}

.top {
  position: absolute;
  transform: skewX(36deg) translateX(2vmin);
  inset: 0;
  height: 6vmin;
  background: linear-gradient(black, black) no-repeat,
    linear-gradient(to right, var(--c1), var(--c3), var(--c2), var(--c1))
      no-repeat;
  background-size: calc(100% - var(--border-width) * 2)
      calc(100% - var(--border-width) * 2),
    100%, 100%;
  background-position: var(--border-width) var(--border-width), 0 0;
  --angle-offset: calc(var(--index) * var(--offset-per-surface));
  --circle-diameter: calc(
    var(--hole-radius) * cos(calc(var(--angle) + var(--angle-offset)))
  );
  -webkit-mask: radial-gradient(
    calc(var(--circle-diameter) * 0.86) at 50%
      calc(60% / cos(calc(var(--angle) + var(--angle-offset)))),
    transparent var(--circle-diameter),
    black var(--circle-diameter)
  );
  mask: radial-gradient(
    calc(var(--circle-diameter) * 0.86) at 50%
      calc(60% / cos(calc(var(--angle) + var(--angle-offset)))),
    transparent var(--circle-diameter),
    black var(--circle-diameter)
  );
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-size: 100% 100%;
  mask-size: 100% 100%;
  -webkit-mask-position: 0 0;
  mask-position: 0 0;
}

@keyframes angle {
  from {
    --angle: 360deg;
  }
  to {
    --angle: 0deg;
  }
}

.ball-container {
  display: grid;
  place-items: center;
  position: absolute;
  inset: 0;
  transform: translateZ(-60vmin);
  animation: ball-container var(--animation-duration) linear infinite;
}

.ball {
  width: 42vmin;
  aspect-ratio: 1;
  border-radius: 50%;
  filter: var(--glow);
  background: radial-gradient(
      21.5vmin 21.5vmin at center,
      black 20vmin,
      transparent 20vmin
    ),
    conic-gradient(
      var(--c1),
      var(--c3),
      var(--c2),
      var(--c4),
      var(--c3),
      var(--c1),
      var(--c2),
      var(--c1)
    );
  box-shadow: 0 0 10vmin rgba(255, 255, 255, 0.08);
  transform: rotateX(45deg) rotateY(45deg) translateY(-20vmin);
}

@keyframes ball-container {
  from {
    transform: translateZ(-40vmin);
    opacity: 0;
  }
  10% {
    transform: translateZ(-25vmin);
    opacity: 1;
  }

  85% {
    opacity: 1;
  }
  to {
    opacity: 0;
    transform: translateZ(70vmin);
  }
}

body {
  width: 100vw;
  height: 100vh;
  display: grid;
  place-items: center;
  background: var(--color-background);
  color: var(--color-on-background);
  overflow: hidden;
  mix-blend-mode: plus-lighter;
}

Final Output

Written by: Piyush Patil

Code Credits: https://codepen.io/konstantindenerz/pen/xxyZJpO

If you found any mistakes or have any doubts please feel free to Contact Us

Hope you find this post helpful💖

Share your love

Leave a Reply

Your email address will not be published. Required fields are marked *