I'm using HTML and CSS to learn/practice 2D and 3D transformations and for this I'm drawing a 3D 9v stack (because it's simple and square). So far everything has been easy because I have only needed transformations to rotate and move the different (rectangular) faces of the stack.
But I find that the electrodes in the cell are circular and I don't know how to make one div
(or another) element circular (3D tube). I imagine it would be to "simulate" a circle using lots of vertices, but that seems tricky.
This is what I've got so far (on JSFiddle ):
@-moz-keyframes spin {
from {transform:rotateY(0deg) rotateX(0) rotateZ(0);}
to {transform:rotateY(360deg) rotateX(360deg) rotateZ(360deg);}
}
@-webkit-keyframes spin {
from {transform:rotateY(0deg) rotateX(0) rotateZ(0);}
to {transform:rotateY(360deg) rotateX(360deg) rotateZ(360deg);}
}
@keyframes spin {
from {transform:rotateY(0deg) rotateX(0) rotateZ(360);}
to {transform:rotateY(360deg) rotateX(360deg) rotateZ(0deg);}
}
.container {
-webkit-perspective: 1000px;
perspective: 1000px;
position:relative;
width:120px;
height:200px;
margin:100px;
}
#battery {
width: 100%;
height: 100%;
position: absolute;
transform-style: preserve-3d;
-webkit-animation: spin 14s infinite linear;
-moz-animation: spin 14s infinite linear;
animation: spin 14s infinite linear;
}
.face {
position:absolute;
top:0;
left:0;
transform-origin:0 0;
opacity:10.6;
overflow:hidden;
}
.face:before, .face:after, .face span:after, .face span:before {
position:absolute;
top:0;
left:0;
transform-origin: left top 0;
display:block;
font-family:arial,sans-serif;
white-space: pre;
}
.large {
width:120px;
height:200px;
background:#111111;
box-sizing:border-box;
box-shadow:inset 0px 66px 0px #CC7722;
}
.side {
width:66px;
height:200px;
background:black;
box-sizing:border-box;
box-shadow:inset 0px 66px 0px #AA5500;
}
.short {
width:120px;
height:66px;
background:#222222;
}
.top {
box-shadow:inset 0 0 0 8px #BB6611;
}
.bottom {
box-shadow:inset 0 0 0 8px #111111;
}
.front:before, .back:before, .right:before {
content:"DURACELL";
color:silver;
transform: rotate(90deg) translate(72px, -68px);
font-weight:bold;
font-size:1.3em;
}
.front:after, .back:after {
content:"ALKALINE BATTERY";
color:silver;
transform: rotate(90deg) translate(73px, -44px);
font-weight:bold;
font-size:0.5em;
}
.back:after { content:"PILE ALCALINE"; }
.right:before { transform: rotate(90deg) translate(72px, -50px) }
.right:after {
content:"Duracell, div of P&G, Bethel, CT 06801 \a P&G Inc., Toronto, ON M5W1C5 \a Made in U.S.A. / Fabrique aux E.-U. \a 95756099";
width:130px;
color:silver;
transform: rotate(90deg) translate(73px, -27px);
font-weight:bold;
font-size:0.29em;
letter-spacing:-0.1px;
line-height:1.2em;
}
.right span:before {
content:"\2b06\a+";
font-weight:bold;
line-height:0.8em;
top:20px;
left:20px;
font-size:1.3em;
}
.right span:after {
content:"MAR \a 2015";
color:#AA5500;
transform: rotate(90deg) translate(150px, -23px);
width:60px;
font-weight:bold;
font-size:0.6em;
text-align:center;
}
.left:before {
content:"MN1604 \a 6LR61 \a 9 VOLTS";
line-height:1em;
transform: rotate(90deg) translate(15px, -59px);
font-size:0.5em;
font-weight:bold;
letter-spacing:-0.1px;
}
.left span:before {
content:"Caution: do not connect improperly. Charge or dispose of in fire. Battery may explode or leak. Do not carry batteries loose in your pocket or elsewhere as burn injury could result.";
width:120px;
color:silver;
transform: rotate(90deg) translate(73px, -60px);
font-weight:200;
font-size:0.25em;
letter-spacing:-0.2px;
line-height:1.2em;
text-transform:uppercase;
white-space: normal;
}
#battery .front { transform: rotateY( 0deg ) translateZ( 66px ); }
#battery .back { transform: rotateY( 180deg ) translateX( -120px ); }
#battery .right { transform: rotateY( 90deg ) translateZ( 120px ) translateX(-66px); }
#battery .left { transform: rotateY( -90deg ) translateZ( 0 ); }
#battery .top { transform: rotateX( -270deg ) translateZ( 0 ); }
#battery .bottom { transform: rotateX( 90deg ) translateZ( -200px ); }
<div class="container">
<div id="battery">
<div class="face large front"></div>
<div class="face large back"></div>
<div class="face side right"><span></span></div>
<div class="face side left"><span></span></div>
<div class="face short top"></div>
<div class="face short bottom"></div>
</div>
</div>
and this is how it looks:
I imagine it could be done with SVG or a canvas
, but I want to limit myself to HTML+CSS3 (with 2D and 3D transformations). So my questions really are:
- Can you have a
div
curve? ( not a circle, but a tube ) - Can they be
div
curved? (eg to create two semicircles and join them in a circle)
And if the element cannot be curved, what could be an alternative? Or is my only option to simulate it as I was saying before?
The first thing to keep in mind when handling 3D transformations in CSS is that html elements don't have thickness so it's impossible to make a circle, square or other shape in CSS that has depth as they will always be reduced to a plane .
In your example, the stack is made up of different flat elements that together make up a cube, giving the impression of depth precisely to overcome this limitation.
The correct way to simulate what you want is with a canvas that comes with functions to manipulate this type of three-dimensional transformations. I recommend you take a look at three.js
Creating a flat circle with CSS is very easy with the property
border-radius: 50%
but to achieve a cylinder by overlapping many layers would take many elements (and probably the help of javascript for simplicity). Here you have a demo.Still at some point in the rotation you will see a flash when all the electrode layers are perpendicular to the screen where the trick becomes apparent.
As an alternative you can make a hexagonal prism based on plans. The more planes you use the closer you will get to the figure of the circle but you will need a large number of elements to achieve this (one for each side and several to simulate an upper layer).
Another way to make a cylinder. I had seen several out there but with lots
div
and lots of CSS lines, I liked Asier's solution because it is simple and he has given me the idea of trying it with just onediv
.PS: After reading @devconcept's answer I've realized that my example only works for a static drawing, if you want to rotate you would have to do some tricks to simulate a 3D object, it doesn't seem easy.
Creating a circular div is very easy using the border-radius property:
For the cylinder effect you could use the box-shadow property: