tl;dr: I would like to create an actual 3d sphere with CSS - not just an illusion
Note: some of the snippet examples are not responsive. Please use full screen.
With pure CSS you can create and animate a 3d cube like so:
#cube-wrapper {
position: absolute;
left: 50%;
top: 50%;
perspective: 1500px;
}
.cube {
position: relative;
transform-style: preserve-3d;
animation-name: rotate;
animation-duration: 30s;
animation-timing-function: linear;
animation-iteration-count: infinite;
}
@keyframes rotate {
0% {
transform: rotate3d(0, 0, 0, 0);
}
100% {
transform: rotate3d(0, 1, 0, 360deg);
;
}
}
.face {
position: absolute;
width: 200px;
height: 200px;
border: solid green 3px;
}
#front_face {
transform: translateX(-100px) translateY(-100px) translateZ(100px);
background: rgba(255, 0, 0, 0.5);
}
#back_face {
transform: translateX(-100px) translateY(-100px) translateZ(-100px);
background: rgba(255, 0, 255, 0.5);
}
#right_face {
transform: translateY(-100px) rotateY(90deg);
background: rgba(255, 255, 0, 0.5);
}
#left_face {
transform: translateY(-100px) translateX(-200px) rotateY(90deg);
background: rgba(0, 255, 0, 0.5);
}
#top_face {
transform: translateX(-100px) translateY(-200px) rotateX(90deg);
background: rgba(0, 255, 255, 0.5);
}
#bottom_face {
transform: translateX(-100px) rotateX(90deg);
background: rgba(255, 255, 255, 0.5);
}
.cube {
transform: rotateX(90deg) rotateY(90deg);
}
<div id="cube-wrapper">
<div class="cube">
<div id="front_face" class="face"></div>
<div id="right_face" class="face"></div>
<div id="back_face" class="face"></div>
<div id="left_face" class="face"></div>
<div id="top_face" class="face"></div>
<div id="bottom_face" class="face"></div>
</div>
</div>
I want to create and animate a 3d sphere in the same manner.
So... the first idea I get is to use border-radius
and...well... it doesn't work.
#cube-wrapper {
position: absolute;
left: 50%;
top: 50%;
perspective: 1500px;
}
.cube {
position: relative;
transform-style: preserve-3d;
animation-name: rotate;
animation-duration: 30s;
animation-timing-function: linear;
animation-iteration-count: infinite;
}
@keyframes rotate {
0% {
transform: rotate3d(0, 0, 0, 0);
}
100% {
transform: rotate3d(0, 1, 0, 360deg);
;
}
}
.face {
position: absolute;
width: 200px;
height: 200px;
border: solid green 3px;
border-radius: 100vw
}
#front_face {
transform: translateX(-100px) translateY(-100px) translateZ(100px);
background: rgba(255, 0, 0, 0.5);
}
#back_face {
transform: translateX(-100px) translateY(-100px) translateZ(-100px);
background: rgba(255, 0, 255, 0.5);
}
#right_face {
transform: translateY(-100px) rotateY(90deg);
background: rgba(255, 255, 0, 0.5);
}
#left_face {
transform: translateY(-100px) translateX(-200px) rotateY(90deg);
background: rgba(0, 255, 0, 0.5);
}
#top_face {
transform: translateX(-100px) translateY(-200px) rotateX(90deg);
background: rgba(0, 255, 255, 0.5);
}
#bottom_face {
transform: translateX(-100px) rotateX(90deg);
background: rgba(255, 255, 255, 0.5);
}
.cube {
transform: rotateX(90deg) rotateY(90deg);
}
<div id="cube-wrapper">
<div class="cube">
<div id="front_face" class="face"></div>
<div id="right_face" class="face"></div>
<div id="back_face" class="face"></div>
<div id="left_face" class="face"></div>
<div id="top_face" class="face"></div>
<div id="bottom_face" class="face"></div>
</div>
</div>
So, I reconsidered my approach and looked for a different method.
I looked at:
- Implementing "Pure CSS Sphere" into website - how do I do it?
- How to create a sphere in css?
- Display an image wrapped around a sphere with CSS/Javascript
- cssanimation.rocks - CSS spheres
- MDN - Circle
Then I tried again...the best I got were overly complicated 3d object illusions.
Like this:
body {
overflow: hidden;
background: #333;
}
.wrapper {
margin: 1em;
animation-duration: 20s;
}
.planet,
.planet:before,
.planet:after {
height: 300px;
width: 300px;
border-radius: 100vw;
will-change: transform;
margin: 0 auto;
}
.planet {
box-shadow: inset 0px 0px 10px 10px rgba(0, 0, 0, 0.4);
position: relative;
}
.wrapper,
.planet,
.planet:before {
animation-name: myrotate;
animation-duration: 20s;
}
.wrapper,
.planet,
.planet:before,
.planet:after {
animation-timing-function: linear;
animation-iteration-count: infinite;
}
.planet:before,
.planet:after {
content: '';
position: absolute;
top: 0;
left: 0;
}
.planet:before {
box-shadow: inset 20px 20px 100px 00px rgba(0, 0, 0, .5), 0px 0px 5px 3px rgba(0, 0, 0, .1);
}
.planet:after {
filter: saturate(2.5);
background: linear-gradient(rgba(0, 0, 0, 1), transparent), url("https://i.sstatic.net/eDYPN.jpg");
opacity: 0.3;
box-shadow: inset -20px -20px 14px 2px rgba(0, 0, 0, .2);
animation-name: myopacity;
animation-duration: 5000000s;
}
@keyframes myrotate {
0% {
transform: rotatez(0deg);
}
100% {
transform: rotatez(360deg);
}
}
@keyframes myopacity {
0% {
background-position: 0px;
transform: rotatez(0deg);
}
50% {
background-position: 100000000px;
}
100% {
background-position: 0;
transform: rotatez(-360deg);
}
}
<div class="wrapper">
<div class="planet"></div>
</div>
And this:
body {
background: #131418;
}
.wrapper {
margin: 1em;
max-width: 100%;
position: fixed;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
.planet,
.planet:before,
.planet:after {
height: 500px;
width: 500px;
max-height: 30vw;
max-width: 30vw;
border-radius: 100vw;
will-change: transform;
}
.planet {
box-shadow: inset 0px 0px 100px 10px rgba(0, 0, 0, .5);
position: relative;
float: left;
margin: 0 2em;
}
.planet,
.planet:before,
.planet:after {
animation-name: myrotate;
animation-duration: 10s;
}
.wrapper,
.planet,
.planet:before,
.planet:after {
animation-timing-function: linear;
animation-iteration-count: infinite;
}
.planet:before,
.planet:after {
content: '';
position: absolute;
top: 0;
left: 0;
}
.planet:before {
box-shadow: inset 50px 100px 50px 0 rgba(0, 0, 0, .5), 0 0 50px 3px rgba(0, 0, 0, .25);
background-image: -webkit-radial-gradient( top, circle cover, #ffffff 0%, #000000 80%);
opacity: .5;
}
.planet:after {
opacity: .3;
background-image: -webkit-radial-gradient( bottom, circle, #ffffff 0%, #000000 -200%);
box-shadow: inset 0px 0px 100px 50px rgba(0, 0, 0, .5);
}
@keyframes myrotate {
0% {
transform: rotatez(0deg);
}
100% {
transform: rotatez(-360deg);
}
}
.bg {
background: wheat;
}
<div class="wrapper">
<div class="planet bg"></div>
</div>
Which are okay until you try to actually rotate them on either the x-axis or the y-axis like the cube in my first example...here's what happens then: (simplified example)
.sphere {
background: black;
width: 300px;
height: 300px;
border-radius: 100vw;
animation: myrotate 10s linear infinite
}
@keyframes myrotate {
0% {
transform: rotate3d(0, 0, 0, 0);
}
100% {
transform: rotate3d(0, 1, 0, 360deg);
}
}
<div class="sphere"></div>
All you get is a flat 2d object - which is expeceted considering that it's what the element is
The closest thing I found is the following shape created in a tutorial by Timo Korinth
@-webkit-keyframes animateWorld {
0% {
-webkit-transform: rotateY(0deg) rotateX(0deg) rotateZ(0deg);
}
50% {
-webkit-transform: rotateY(360deg) rotateX(180deg) rotateZ(180deg);
}
100% {
-webkit-transform: rotateY(720deg) rotateX(360deg) rotateZ(360deg);
}
}
html {
background: #FFFFFF;
}
. world {
-webkit-perspective: 1000px;
}
.cube {
margin-left: auto;
margin-right: auto;
position: relative;
width: 200px;
height: 200px;
-webkit-transform-style: preserve-3d;
-webkit-animation-name: animateWorld;
-webkit-animation-duration: 10s;
-webkit-animation-iteration-count: infinite;
-webkit-animation-timing-function: linear;
}
.circle {
position: absolute;
width: 100%;
height: 100%;
border: 2px dashed #009BC2;
border-radius: 50%;
opacity: 0.8;
background: rgba(255, 255, 255, 0);
}
.zero {
-webkit-transform: rotateX(90deg);
}
.two {
-webkit-transform: rotateY(45deg);
}
.three {
-webkit-transform: rotateY(90deg);
}
.four {
-webkit-transform: rotateY(135deg);
}
.five {
width: 173px;
height: 173px;
margin: 14px;
-webkit-transform: rotateX(90deg) translateZ(50px);
}
.six {
width: 173px;
height: 173px;
margin: 14px;
-webkit-transform: rotateX(90deg) translateZ(-50px);
}
<div class="world">
<div class="cube">
<div class="circle zero"></div>
<div class="circle one"></div>
<div class="circle two"></div>
<div class="circle three"></div>
<div class="circle four"></div>
<div class="circle five"></div>
<div class="circle six"></div>
</div>
</div>
So here's my
Question:
How do I create an actual 3 dimensional sphere with pure CSS? More specifically, one that is covered - not just a frame - and doesn't involve hundreds of html elements.
Notes:
- Three dimensional spheres have height, width and depth - just like the cube in my first example snippet
- I don't need any physics and there's no need for any user-interaction. Just an animated spinning sphere.
Additional resources:
box-shadow
s with different offsets and colors. So CSS can be used as kind of (terribly slow and ineffective, but still...) graphics drawing tool:) – Prepossessing