// You can play with it using the different settings in the CSS section.
View Compiled
$show-face: false;
$hide-backface: false;
$random-color: true; // priority
$random-border: false;
$random-face: false;
$length: 3;
$size: 75vmin;
$time: 30s;
$ratio-border: 0.025;
$color-background: #170a19;
$opacity-border: 1;
$opacity-face: 0.05;
$colors: (
#f46060,
#ff8364,
#ffb677,
#acdeaa,
#8ed6ff,
#6886c5,
#cca8e9,
#726a95,
#709fb0,
#f4ebc1,
#e36387,
#d8345f,
#f7e8f0
);
@function random-color($colors: $colors, $length: length($colors)) {
@return nth($colors, random($length));
}
$color-border: random-color();
$color-face: random-color();
@mixin cube-world($length: $length, $size: $size, $gap: null, $selector: li) {
$indice: floor($length / 2);
$diameter: $size / $length;
$radius: $diameter / 2;
$gap: if($gap, $gap, $diameter * 2);
$space: $diameter + $gap;
$distance: $space * $indice;
$grid: $length * $length;
:root {
--length: #{$grid * $length};
--distance-front: #{$distance * 2 - $gap / 2};
--distance-back: #{-2 * $distance + $gap / 2};
--perspective: #{$distance + $diameter};
--diameter: #{$diameter};
--radius: #{$radius};
--border: #{$diameter * $ratio-border};
}
// Update this using only 1 loop
@for $i from 0 to $length {
$x: ($i - $indice) * $space;
@for $j from 0 to $length {
$y: ($j - $indice) * $space;
@for $k from 0 to $length {
$z: ($k - $indice) * $space;
$index: $i * $length + $k * $grid + $j + 1;
#{$selector}:nth-child(#{$index}) {
@if $random-color {
$color: random-color();
--color-border: #{rgba($color, $opacity-border)};
@if $show-face {
--color-face: #{rgba($color, $opacity-face)};
}
} @else {
--color-border: #{rgba(
if($random-border, random-color(), $color-border),
$opacity-border
)};
@if $show-face {
--color-face: #{rgba(
if($random-face, random-color(), $color-face),
$opacity-face
)};
}
}
transform: translate3d($x, $y, $z + $radius);
}
}
}
}
}
@keyframes rotate {
0%,
25% {
transform: rotate3d(0, 0, 0, 0);
}
75%,
100% {
transform: rotate3d(1, 1, 0, 360deg);
}
}
@keyframes translate {
0%,
100% {
transform: translate3d(0, 0, var(--distance-front));
}
50% {
transform: translate3d(0, 0, var(--distance-back));
}
}
%center {
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
}
*,
*::after,
*::before {
margin: 0;
border: 0;
padding: 0;
box-sizing: border-box;
}
body {
@extend %center;
height: 100vh;
width: 100vw;
position: relative;
overflow: hidden;
transform-style: preserve-3d;
perspective: var(--perspective);
background-color: $color-background;
}
section {
transform-style: preserve-3d;
animation: translate $time ease-in-out infinite;
}
ul {
@extend %center;
transform-style: preserve-3d;
animation: rotate $time ease-in-out infinite;
}
li,
div {
@extend %center;
transform-style: preserve-3d;
&,
&::after,
&::before {
height: var(--diameter);
width: var(--diameter);
position: absolute;
transform-origin: center center calc(-1 * #{var(--radius)});
border: var(--border) solid var(--color-border);
background-color: var(--color-face);
backface-visibility: if($hide-backface, hidden, null);
}
&::after,
&::before {
content: "";
}
}
li {
&::after {
transform: rotate3d(1, 0, 0, 90deg);
}
&::before {
transform: rotate3d(-1, 0, 0, 90deg);
}
}
div {
transform: rotate3d(0, 1, 0, 180deg);
&::after {
transform: rotate3d(0, 1, 0, 90deg);
}
&::before {
transform: rotate3d(0, -1, 0, 90deg);
}
}
@include cube-world();
View Compiled
// You can play with it using the different settings in the CSS section.
(() => {
const root = document.documentElement;
const style = getComputedStyle(root);
const length = style.getPropertyValue("--length");
const scene = document.createElement("section");
const world = document.createElement("ul");
const cube = document.createElement("li");
cube.appendChild(document.createElement("div"));
const cubes = Array.from({ length }, () => cube.cloneNode(true));
document.body
.appendChild(scene)
.appendChild(world)
.append(...cubes);
})();
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.