How to make a tetrahedron? - css

I am trying to make a CSS tetrahedron, so I have tackled the problem by doing some CSS3 triangles and activating the 3D transformations with the perspective property.
But I have some issues to wrap my mind over all the transformations, here is some of my code:
.navbar-brand-logo {
width: 64px;
height: 64px;
transform-style: preserve-3d;
perspective: 600px;
position: relative;
}
.face {
width: 0;
height: 0;
position: absolute;
border-style: solid;
border-width: 64px 32px 0 32px;
transform-origin: 0 0;
border-color: transparent transparent transparent rgba(50, 50, 50, 0.6);
}
.logo-base-left {
transform: rotateX(180deg) translateY(-64px);
}
.logo-base-right {
transform: rotateY(180deg) rotateX(180deg) translateY(-64px);
}
.logo-up {
border-color: transparent transparent transparent rgba(50, 50, 50, 0.8);
transform: rotateY(180deg) scaleY(0.5) translateY(-64px);
}
.logo-down-up {
border-color: transparent transparent transparent rgba(50, 50, 50, 0.9);
border-width: 64px 0 0px 4px;
transform: scaleX(128px) translateZ(0px);
}
<section class="navbar-brand-logo">
<figure class="face logo-base-left"></figure>
<figure class="face logo-base-right"></figure>
<figure class="face logo-up"></figure>
<figure class="face logo-down-up"></figure>
</section>
I am having issues to imagine how can I make the two other faces (the left up one and the right one).
Here is a CodePen which illustrate the current attempt:
Furthermore, is it a good idea to use a CSS3 tetrahedron as a logo?
Would it be better if it was an SVG?
WebGL / Canvas is a no-no due to browser support.

Here are a few steps describing an approach to make a responsive tetrahedron: demo - responsive tetrahedron.
link to animation
Step 1 the faces:
A tetrahedron has 4 triangular faces. Each face is an equilateral triangle.
In the following example, I used the clip-path property to make the 4 equilateral triangles:
.tetra{
position:relative;
width:20%;
padding-bottom:17.32%; /* height of equilateral triangle = sin60° * width */
margin:0 auto;
}
.tetra div{
position:absolute;
top:0;left:0;
width:100%; height:100%;
-webkit-clip-path:polygon(50% 0, 100% 100%, 0% 100%);
clip-path:polygon(50% 0, 100% 100%, 0% 100%);
background:teal;
}
.tetra .face2{
transform-origin:0% 100%;
transform:rotate(-60deg);
background:gold;
}
.tetra .face3{
transform-origin:100% 100%;
transform:rotate(60deg);
background:darkorange;
}
.tetra .face4{
transform-origin:50% 100%;
transform:rotate(180deg);
background:pink;
}
<div class="tetra">
<div class="face1"></div>
<div class="face2"></div>
<div class="face3"></div>
<div class="face4"></div>
</div>
Step 2 make it 3d
For this, we rotate each face separately in the 3d environment with perspective and transform-style:
body{
perspective:9000px;
}
.tetra{
position:relative;
width:20%;
padding-bottom:17.32%; /* height of equilateral triangle = sin60° * width */
margin:0 auto;
transform-style:preserve-3d;
}
.tetra div{
position:absolute;
top:0;left:0;
width:100%; height:100%;
-webkit-clip-path:polygon(50% 0, 100% 100%, 0% 100%);
clip-path:polygon(50% 0, 100% 100%, 0% 100%);
background:teal;
transform-style:preserve-3d;
}
/* Rotation of –109.5° is angle(C, M[AB], D), per http://www.f-lohmueller.de/pov_tut/geo/geom_200e.htm, 180° – atan(2 * sqrt(2)) ≈ 109.5° */
.tetra .face2{
transform-origin:0% 100%;
transform:rotate(-60deg) rotatex(-109.5deg);
background:gold;
}
.tetra .face3{
transform-origin:100% 100%;
transform:rotate(60deg) rotatex(-109.5deg);
background:darkorange;
}
.tetra .face4{
transform-origin:50% 100%;
transform:rotate(180deg) rotatex(-109.5deg);
background:pink;
}
<div class="tetra">
<div class="face1"></div>
<div class="face2"></div>
<div class="face3"></div>
<div class="face4"></div>
</div>
At this point, you have a tetrahedron but you can only see 3 face so to see the whole 3d shape:
Step 3 make it rotate!
Top see the whole tetrahedron, you need to rotate it with a transition or keyframe animation :
body{
perspective:9000px;
padding-top:10%;
}
.tetra{
position:relative;
width:20%;
padding-bottom:17.32%; /* height of equilateral triangle = sin60° * width */
margin:0 auto;
transform-style:preserve-3d;
transform:rotatex(90deg) rotateY(0deg) rotatez(0deg);
animation: rotate 10s linear infinite;
}
.tetra div{
position:absolute;
top:0;left:0;
width:100%; height:100%;
-webkit-clip-path:polygon(50% 0, 100% 100%, 0% 100%);
clip-path:polygon(50% 0, 100% 100%, 0% 100%);
background:teal;
transform-style:preserve-3d;
}
/* Rotation of –109.5° is angle(C, M[AB], D), per http://www.f-lohmueller.de/pov_tut/geo/geom_200e.htm, 180° – atan(2 * sqrt(2)) ≈ 109.5° */
.tetra .face2{
transform-origin:0% 100%;
transform:rotate(-60deg) rotatex(-109.5deg);
background:gold;
}
.tetra .face3{
transform-origin:100% 100%;
transform:rotate(60deg) rotatex(-109.5deg);
background:darkorange;
}
.tetra .face4{
transform-origin:50% 100%;
transform:rotate(180deg) rotatex(-109.5deg);
background:pink;
}
#keyframes rotate{
50%{transform:rotatex(100deg) rotateY(10deg) rotatez(180deg);}
100%{transform:rotatex(90deg) rotateY(0deg) rotatez(360deg);}
}
<div class="tetra">
<div class="face1"></div>
<div class="face2"></div>
<div class="face3"></div>
<div class="face4"></div>
</div>
Note that this uses properties that aren't supported by all browsers, especialy clip-path that is only supported by chrome. This property is used to make the equilateral triangles and you can use other approaches (see here).
For browser support and vendor prefixes, also see canIuse for:
clip-path
3d transforms
CSS animations

If you want to animate the logo (once, on hover, doesn't matter), then going with 3D CSS is probably a good idea.
With SVG, you would get better browser support, faster rendering, and easier control over the shape, so if you're not animating the logo I'd suggest going with SVG.
For building the shape of a tetrahedron in 3D, check out Ana Tudor's codepen, this is but one of many tetrahedron examples she's made: http://codepen.io/thebabydino/pen/vFrHx – you can play with the animation rot in this pen to get an idea of how to rotate / animate it.

In organic molecules tetrahedra are often related helices, f.e.:
Boerdijk–Coxeter helix. So it would be nice to write code to show this helix.
Here is javascript for the helix:
var s set equal to the sides of the square canvas
var a=s/6, b=s/9;
c.beginPath();
for (var i=0; i<2*Math.PI; i+=0.01){
x=s/4+a*Math.cos(i)-b*Math.sin(i);
y=3*s/4+a*Math.cos(i)+b*Math.sin(i);
if(i==0) {c.moveTo(x,y);} else {c.lineTo(x,y);}
}
c.lineWidth=1;
c.strokeStyle="#0f6";
c.stroke();

Related

CSS3 Animation: How do I create smooth movement of background image? Seems to be a Chrome only issue

Trying to smoothly animate a div's background image #bg2 over a short pixel distance (while a clip path animates over it). I'm not able to get the image to move smoothly, it jitters and judders. The clip path animation is fine.
I've tried different easing (linear / ease-in-out etc) suggested in another SO thread, and also extending the distance it needs to move, but it still seems to jump pixel by pixel (sort of), rather than move smoothly. (Although, extending the move distance isn't an option in the actual use case).
How can smooth movement of the cat background image #bg2 be accomplished? Thanks.
** Edit: It's totally smooth for me in Firefox, for me it's jittery in Chrome 91.0.4472.114 on Mojave 10.14.6, and less jittery in Safari. For other it seems to be smooth on Chrome also. Hmmm...
var clickTag = "#";
#main-container {
position: absolute;
width: 970px;
height: 250px;
left:-200px;
box-sizing: border-box;
background: #333;
overflow:hidden; perspective: 800px;
border:1px solid #ccc;
}
div, img {
position: absolute;
background-repeat:no-repeat;
width: 970px;
height: 250px;
z-index: 4;
background-size: 970px 250px;
}
#bg2{
width: 970px;
height: 250px;
z-index:2;
background-image:url('https://i.stack.imgur.com/6EcDu.jpg');
-webkit-clip-path: circle(9% at 682px 110px);
clip-path: circle(9% at 682px 110px);
transform: translateY(20px);
background-position: -5px -10px;
}
#bg2{animation: grow 2.5s 2.5s cubic-bezier(0.215, 0.610, 0.355, 1.000) forwards;-webkit-animation: groww 2.5s 2.5s cubic-bezier(0.215, 0.610, 0.355, 1.000) forwards;}
#-webkit-keyframes groww {
0% {opacity:1;transform: translateY(20px);clip-path: circle(9% at 682px 110px);-webkit-clip-path: circle(9% at 682px 110px);background-position: -5px -10px;}
100% {opacity:1;transform: translateY(-4px);clip-path: circle(15% at 682px 128px);-webkit-clip-path: circle(15% at 682px 128px);background-position: 0px 0px;}
}
#keyframes grow {
0% {opacity:1;transform: translateY(20px);clip-path: circle(9% at 682px 110px);background-position: -5px -10px;}
100% {opacity:1;transform: translateY(-4px);clip-path: circle(15% at 682px 128px);background-position: 0px 0px;}
}
<a href="javascript:window.open(window.clickTag)">
<div id="main-container" class="animate">
<div id="bg2"></div>
</div>
</a>
I'm a bit curious about why having a large banner while not displaying it all.
Anyways, I provide another way of animating, basically just changing the height. Hopefully that could give some ideas.
I removed the width to make it slightly more responsive.
The animation somewhat jittery in this solution, but I guess that it depends on your bezier curve. So perhaps that's the issue all along?
var clickTag = "#";
#main-container {
position: relative;
height: 250px;
box-sizing: border-box;
border: 1px solid #ccc;
background-color: #333;
}
#bg2 {
position: absolute;
left: 75%;
top: 50%;
transform: translate(-50%, -50%);
height: 40%;
aspect-ratio: 1;
border-radius: 50%;
background-image: url('https://i.stack.imgur.com/6EcDu.jpg');
background-position: right 25% center;
animation: grow 2.5s 2.5s cubic-bezier(0.215, 0.610, 0.355, 1.000) forwards;
}
#keyframes grow {
to { height: 80%; }
}
<a href="javascript:window.open(window.clickTag)">
<div id="main-container">
<div id="bg2"></div>
</div>
</a>

CSS Animated wavy line not displaying properly in Chrome

I have created a simple animated wavy line to use as a divider on one of my websites. Looks perfect in safari but it displays strange in Chrome.
Here's the safari screenshot:
Here's the chrome screenshot:
The safari one is perfect for me, but it seems chrome isn't liking it.
I have tried adding ALL vendor prefixes to the start of the selectors and various places but I cant seem to fix the issue.
Can anyone please tell me where I'm going wrong?
Here's a CODEPEN and here's a code snippet:
.wavy-line {
width: 150px;
height: 50px;
overflow: hidden;
margin: 0 auto 0 auto;
}
.wavy-line:before {
content: attr(data-text);
position: relative;
top: -35px;
color: rgba(0,0,0,0);
width: calc(100% + 27px);
font-size: 4em;
text-decoration-style: wavy;
text-decoration-color: #25173A;
text-decoration-line: underline;
animation: animate .9s linear infinite;
-webkit-animation: animate .9s linear infinite;
}
#keyframes animate {
0% { left: -0px; }
100% { left: -30px;}
}
#-webkit-keyframes animate {
0% { left: -0px; }
100% { left: -30px;}
}
.wavy-line-green:before { text-decoration-color: #56AE5F; }
.wavy-line-blue:before { text-decoration-color: #1FB5D1; }
.wavy-line-yellow:before { text-decoration-color: #F9B930; }
<div class="wavy-line wavy-line-green" data-text="xxxxxxxxxxxxxx"></div>
<div class="wavy-line wavy-line-blue" data-text="xxxxxxxxxxxxxx"></div>
<div class="wavy-line wavy-line-yellow" data-text="xxxxxxxxxxxxxx"></div>
I will consider a previous answer to draw the waves using CSS and then you can easily animate them. You simply need to adjust the CSS variable to control the shape:
.wave {
--c:red; /* Color */
--t:5px; /* Thickness */
--h:50px; /* Height */
--w:120px; /* Width */
--p:13px; /* adjust this to correct the position when changing the other values*/
margin:5px auto;
width:calc(var(--w)*4);
height:calc(var(--h) + 10px);
overflow:hidden;
position:relative;
}
.wave:before {
content:"";
position:absolute;
padding:5px 0;
top:0;
left:0;
width:200%;
bottom:0;
background:
radial-gradient(farthest-side at 50% calc(100% + var(--p)), transparent 47%, var(--c) 50% calc(50% + var(--t)),transparent calc(52% + var(--t))),
radial-gradient(farthest-side at 50% calc(0% - var(--p)), transparent 47%, var(--c) 50% calc(50% + var(--t)),transparent calc(52% + var(--t)));
background-size:var(--w) var(--h);
background-position:calc(var(--w)/2) calc(-1*(var(--h)/2)),0px calc(var(--h)/2);
background-repeat:repeat-x;
background-origin:content-box;
animation:move 3s infinite linear;
}
#keyframes move {
to {
transform:translateX(-50%);
}
}
<div class="wave"></div>
<div class="wave" style="--w:140px;--h:40px;--p:13px; --t:8px;--c:purple"></div>
<div class="wave" style="--w:100px;--h:30px;--p:14px;--t:10px;--c:green;"></div>
<div class="wave" style="--w: 64px;--h: 22px;--p: 11px;--t: 7px;--c: orange;"></div>

How to create quadrilateral (rhombus shape) with specific degree?

How can I create a quadrilateral with css, when I know which degree each corner has.
I already tried to recreate a quadrilateral I have with transform and skew.
However, this does not work really well.
This is what I try to archive.
The exact requirements are:
A div with this as background in one color. On the image are just construction lines. It should be a solid quadrilateral with these angles.
This was my first idea:
transform: rotate(-45deg) skew(27.5deg, 62.5deg)
transform-origin: top center;
I would consider multiple background to achieve this where I simply need to find the width/height of the element. Based on your illustration we have this:
From this we can have the following formula:
tan(alpha) = W/H
and
tan(beta/2) = H/W
We only need to use one of them and you will notice that there isn't one solution which is logical as you simply need to keep a ratio between H and W and the width of our element will simply be 2*W and its height 2*H.
Since H/W is also the same as 2*H/2*W we can simply consider that width = tan(alpha)*height
.box {
height:var(--h);
width:calc(1.92098213 * var(--h)); /* tan(62.5)xH */
background:
linear-gradient(to bottom right,transparent 49%,red 50%) top left,
linear-gradient(to top right,transparent 49%,red 50%) bottom left,
linear-gradient(to bottom left ,transparent 49%,red 50%) top right,
linear-gradient(to top left ,transparent 49%,red 50%) bottom right;
background-size:50% 50%;
background-repeat:no-repeat;
}
<div class="box" style="--h:50px;"></div>
<div class="box" style="--h:100px;"></div>
<div class="box" style="--h:200px;"></div>
You can adjust the gradient if you want only borders:
.box {
height:var(--h);
width:calc(1.92098213 * var(--h)); /* tan(62.5)xH */
background:
linear-gradient(to bottom right,transparent 49%,red 50%,transparent calc(50% + 2px)) top left,
linear-gradient(to top right,transparent 49%,red 50%,transparent calc(50% + 2px)) bottom left,
linear-gradient(to bottom left ,transparent 49%,red 50%,transparent calc(50% + 2px)) top right,
linear-gradient(to top left ,transparent 49%,red 50%,transparent calc(50% + 2px)) bottom right;
background-size:50% 50%;
background-repeat:no-repeat;
}
<div class="box" style="--h:50px;"></div>
<div class="box" style="--h:100px;"></div>
<div class="box" style="--h:200px;"></div>
Using transform the idea is to rely on rotateX() in order to visually decrease the height to keep the formula defined previously. So we start by having Width=height (a square) then we rotate like below:
This is a view from the side. The green is our rotated element and the red the initial one. It's clear that we will see the height H1 after performing the rotation and we have this formula:
cos(angle) = H1/H
And we aleardy have tan(alpha)=W/H1 so we will have
cos(angle) = W/(H*tan(alpha))
and H=W since we defined a square initially so we will have cos(angle) = 1/tan(alpha) --> angle = cos-1(1/tan(alpha))
.box {
width:150px;
height:150px;
background:red;
margin:50px;
transform:rotateX(58.63017731deg) rotate(45deg); /* cos-1(0.52056)*/
}
<div class="box">
</div>
We can also apply the same logic using rotateY() to update the width in the situation where you will have beta bigger than 90deg and alpha smaller than 45deg. In this case we will have W < H and the rotateX() won't help us.
The math can easily confirm this. when alpha is smaller than 45deg tan(alpha) will be smaller than 1 thus 1/tan(alpha) will bigger than 1 and cos is only defined between [-1 1] so there is no angle we can use with rotateX()
Here is an animation to illustrate:
.box {
width:100px;
height:100px;
display:inline-block;
background:red;
margin:50px;
animation:change 5s linear infinite alternate;
}
.alt {
animation:change-alt 5s linear infinite alternate;
}
#keyframes change {
from{transform:rotateX(0) rotate(45deg)}
to{ transform:rotateX(90deg) rotate(45deg)}
}
#keyframes change-alt {
from{transform:rotateY(0) rotate(45deg)}
to{ transform:rotateY(90deg) rotate(45deg)}
}
<div class="box">
</div>
<div class="box alt">
</div>
In various way you can do it. Since you're trying to use degree value so here I can give you an example: first of you can take four lines for your rectangle and rotate them as you want with degree value. Here is what I mean:
<div class="top_line"></div>
<div class="right_line"></div>
<div class="bottom_line"></div>
<div class="left_line"></div>
Css
.top_line { height: 170px; border-right: 1px solid yellow; transform: rotate(50deg);
position: absolute; top: 140px; left: 400px; transform-origin: 0% 130%; }
.right_line {height: 140px; border-right: 1px solid red; transform: rotate(130deg);
position: absolute; top: 140px; left: 500px; transform-origin: 0% 50%; }
.bottom_line { height: 140px; border-right: 1px solid green; transform: rotate(130deg);
position: absolute; top: 140px; left: 400px; transform-origin: -1800% 80%; }
.left_line { height: 140px; border-right: 1px solid blue; transform: rotate(50deg);
position: absolute; top: 140px; left: 400px; }
Here is the live preview

constructing a 3d pyramid with css

Here is a jsbin of what I have so far and below is an image of what I am trying to construct:
Here is the html, I have only 2 sides of the pyramid added so far:
<div class="pyramid-container">
<div id="pyramid">
<div class="base"></div>
<div></div>
<div></div>
</div>
</div>
And here is the css:
.pyramid-container {
perspective: 800px;
}
#pyramid {
position: relative;
transform-style: preserve-3d;
transform-origin: 116px 200px 116px;
padding-left: 100px;
margin-top: 50px
}
#pyramid div:not(.base) {
position: absolute;
width: 0;
height: 0;
border-left: 100px solid transparent; /* left arrow slant */
border-right: 100px solid transparent; /* right arrow slant */
border-bottom: 100px solid; /* bottom, add background color here */
font-size: 12px;
line-height: 0;
opacity: .5;
}
.base {
position: absolute;
width: 200px;
height: 200px;
background-color: #ff0000;
transform: rotateX(80deg) translate3d(0px, 10px, 0px);
}
#pyramid div:nth-child(2) {
border-bottom-color: blue;//#e04545;
transform: rotateX(-30deg) rotateY(0deg) rotateZ(0deg) translate3d(0px, 0px, 100px);
}
#pyramid div:nth-child(3) {
border-bottom-color: yellow;//#ccaf5a;
transform: rotateX(30deg) rotateY(0deg) rotateZ(0deg) translate3d(0px, 25px, 0px);
}
I am using css3 to create 1 base rectangular div and 4 triangular divs.
I would like some help with the maths involved as well as how to position the elements.
I would like all 4 of the triangle sides to meet at an apex and have the four triangle bottom sides positioned on the rectangular div.
I am struggling with how to get the points of the different triangles to meet in at an apex.
Can anyone help me out with the maths or what logic to use to achieve this.
I'm not looking for code but more the logic or maths I should use.
So first, a couple fundamental points on CSS transforms
the order of transforms is important
the perspective will change with the size of container (#pyramid for you)
the origin of the transform is not inherited, and if not set with transform-origin, it is by default the center of the object (borders et al. included, afaict)
x is the horizontal axis, y the vertical one and z the one orthogonal to the screen's surface (when you don't have perspective)
Then on pyramids:
Let us look at the Base angle (let's call it α). Expressing the triangle sizes based on the angle α, you get:
width = Base
apothem (height of triangle) = (1/2 Base) / cos(α)
height of the pyramid = (1/2 Base) * tan(α)
In the pyramid of your attempt, Base = 200px thus 1/2 Base = 100px and Apothem = triangle height = 100px. This forces cos(α) = 1 thus α = 0° -- you will have a flat pyramid.
If you want α = 60°, you want apothem = 200px, and you'll get pyramid height = 173.2
If you want α = 45°, you want apothem = 141px, and you'll get pyramid height = 100
etc.
The main secret now you know the parameters, is to reason at each step, about where the axis are pointed, and at which point of the object you are applying the transforms. Paper & pencil or trial & error, whatever works is good.
So here's how I would do to place triangles:
put css-transform at the middle of the base of all triangles
rotate by a multiple of 90° around axis Y to orient each triangle for a different face of the pyramid (respectively 0, 90, 180, 270)
translate along Z by 1/2 Base to get the right position
rotate along X axis by the desired angle (90°-α) to make them meet at apex.
Thanks to the first rotation, the two identical last steps will do what you want on all triangles.
For the base, it's easier, you can keep the default css-transform
rotate by 90° along X (will make it "flat" on the plane perpendicular to the screen)
shift it along Z by (Apothem - 1/2 Base) to align with the base of the triangles
Below is what it would look like for α = 45°, feel free to not open the snippet if you don't want spoilers.
#pyramid {
perspective: 400px;
padding: 50px 0 0 200px;
}
#pyramid div:not(.base) {
position: absolute;
border-left: 100px solid transparent; /* 1/2 Base */
border-right: 100px solid transparent; /* 1/2 Base */
border-bottom: 141px solid; /* Apothem */
transform-origin: 100px 141px 0; /* bottom of trangle (1/2 Base, Apothem) */
opacity: .5;
}
.base {
position: absolute;
width: 200px;
height: 200px;
background-color: #2f2f2f;
/* transform by default from middle (100px, 100px)
move by Apothem - 1/2 Base = 41px */
transform: rotateX(90deg) translate3d(0px, 0px, -41px);
opacity: .5;
}
#pyramid div:nth-child(2) {
border-bottom-color: #e04545;
transform: rotateY(0deg) translate3d(0px, 0px, 100px) rotateX(45deg);
}
#pyramid div:nth-child(3) {
border-bottom-color: #ccaf5a;
transform: rotateY(90deg) translate3d(0px, 0px, 100px) rotateX(45deg);
}
#pyramid div:nth-child(4) {
transform: rotateY(180deg) translate3d(0px, 0px, 100px) rotateX(45deg);
}
#pyramid div:nth-child(5) {
border-bottom-color: #4ccfc7;
transform: rotateY(270deg) translate3d(0px, 0px, 100px) rotateX(45deg);
}
<!doctype html>
<html>
<head><title>Pyramid</title></head>
<body>
<div class="pyramid-container">
<div id="pyramid">
<div class="base"></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
</div>
</body>
</html>

Transform rotate not working properly in chrome

The following code renders a perfect rotating circle in safari, but not in chrome.
<style>
.circle{
height:1000px;
width:1000px;
background-color:#000;
border-radius: 50%;
}
#-webkit-keyframes rotating {
from{
-webkit-transform: rotate(0deg);
}
to{
-webkit-transform: rotate(360deg);
}
}
.rotating {
-webkit-animation: rotating 2s linear infinite;
-webkit-transform-origin: center;
}
</style>
<div class="circle rotating">
</div>
http://jsfiddle.net/p4ban9cs/
It does not renders perfectly, the problem is visible when rotating a big circle, it's like a wiggling circle on chrome.
thank you for help.
Adding an outer element as a wrapper and apply same styling to it, to mask the inner circle rotation as seen in this Fiddle
<div class="overlay">
<div class="circle rotating">Test</div>
</div>
.overlay{
height:1000px;
width:1000px;
box-shadow:0 0 0 10px #000 ;
background:black;
border-radius: 50%;
}

Resources