0% found this document useful (0 votes)
105 views

Iron Man's Arc Reactor Using CSS3 Transforms and Animations - CSS-Tricks PDF

The document describes how to create an animated Arc reactor from Iron Man's suit using CSS3 transforms and animations. It provides code to create a full page wrapper with a radial gradient background. It then centers a reactor container using flexbox and creates concentric circles for the reactor core using absolute positioning, margins, box shadows for glow effects, and layered div elements. The goal is to recreate the Arc reactor visual effect from the movies using only CSS.
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
105 views

Iron Man's Arc Reactor Using CSS3 Transforms and Animations - CSS-Tricks PDF

The document describes how to create an animated Arc reactor from Iron Man's suit using CSS3 transforms and animations. It provides code to create a full page wrapper with a radial gradient background. It then centers a reactor container using flexbox and creates concentric circles for the reactor core using absolute positioning, margins, box shadows for glow effects, and layered div elements. The goal is to recreate the Arc reactor visual effect from the movies using only CSS.
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 28

Home / Articles /

Iron Man’s Arc Reactor Using CSS3


Transforms and Animations
4 Comments
Author
Go to
Kunal Sarkar
Comments

Published Updated
Apr 2, 2018 Apr 4, 2018

Alright Iron Man fans, fire up your code editors! We are going to make the Arc reactor from Iron
Man’s suit in CSS. Here’s what the end result will look like:

Embedded Pen Here

The Full Page Wrapper


We will make our Arc reactor on a dark full-page background. Here’s our code to make a full page
wrapper element:
CSS

body {
margin: 0;
}

.fullpage-wrapper {
height: 100vh;
background: radial-gradient(#353c44, #222931);
}

Why do we declare no margin on the body? The <body> element has some margin set to it by
default in the user agent stylesheet. This prevents the elements inside the <body> to touch the
edges of the screen. Since we want our wrapper to cover the entire screen, edge to edge, we
removed that default margin on <body> element by setting it to 0 .

We’ve given our .fullpage-wrapper the full height of the viewport. We don’t have to specify a
width because a div is full width by default. We could have gone with another approach by setting
both the width and height of the element to 100% but that comes with some possible drawbacks
as more elements are added to the screen. Using viewport units ensures our wrapper always
occupies the full vertical space of the screen, regardless of what it is or what other elements are
added to the layout.

We also used a radial gradient on our wrapper using radial-gradient() (https://css-


tricks.com/snippets/css/css-radial-gradient/) CSS function. The parameters inside the function are
the color start and end points. So, the center of the background will be more #353c44 and more
#222931 towards the edges. It’s subtle, but a nice touch.
Centering the Reactor
Container
Before we start creating our reactor, let’s create a container for it and center it:

CSS

.reactor-container {
width: 300px;
height: 300px;
margin: auto;
border: 1px dashed #888;
}

This gives us a 300px x 300px box with dashed border. The margin: auto; declaration ensures
equal horizontal spacing.
But why it doesn’t center it vertically?

Per CSS2 specs, if we give auto margin to the left and right side, then the entire available space will
be equally divided to left and right margin. This isn’t the same case for the top and bottom margin
though. For top and bottom margin the CSS2 spec
(https://www.w3.org/TR/CSS22/visudet.html#Computing_heights_and_margins) says:

If margin-top , or margin-bottom are auto , their used value is 0 .

However, we do have a good news. The flexbox layout follows new rules of alignment, and here’s
what the Flexbox spec (https://www.w3.org/TR/css-flexbox-1/#auto-margins) has to say:

Prior to alignment via justify-content and align-self, any positive free space is
distributed to auto margins in that dimension.

This means if the element in consideration is displayed as a flex item, then margin: auto; will
work in both the directions. Let’s make our wrapper a flex container and its child elements flex
items:

CSS

.fullpage-wrapper {
width: 100%;
height: 100vh;
background: radial-gradient(#353c44, #222931);
display: flex;
}

There, that’s much better:

There are many other methods to center elements in HTML. There’s a detailed guide on centering
(https://css-tricks.com/centering-css-complete-guide/) right here on CSS-Tricks to learn more.

The Reactor Core: Concentric


Circles in CSS
We know that new elements in HTML are created from left to right (for left-to-right languages), or
top to bottom. Elements never overlap, until you provide some negative margin.

So, how are we going to display concentric circles? We will use absolute positioning.

The default value of position (https://css-tricks.com/almanac/properties/p/position/) property


is static . Static and relative positioning follow the flow of top to bottom and left to right.
However, an absolutely positioned element is not treated as a part of the document flow and can be
positioned anywhere using the top, right, bottom and left properties.

Let’s start by creating the smallest circle:

HTML

<div class="fullpage-wrapper">
<div class="reactor-container">
<!-- the smallest circle -->
<div class="core-inner"></div>
</div>
</div>

CSS

.core-inner {
position: absolute;
width: 70px;
height: 70px;
border-radius: 50%;
border: 5px solid #1b4e5f;
background-color: #fff;
}
We need to center this div. You might be tempted to apply the same flexbox concept we used on the
reactor element to center this circle as well. But, here’s what CSS2 spec
(https://www.w3.org/TR/CSS22/visudet.html#abs-non-replaced-height) has to say about setting
margin: auto; on absolutely positioned elements:

If none of the three ( top , height , and bottom ) are auto : If both margin-top and
margin-bottom are auto , solve the equation under the extra constraint that the two
margins get equal values.

This means if an absolutely positioned element has any value for top , height and bottom other
than auto , then setting the top and bottom margin to auto will center the element vertically.

Same case for horizontal centering: if an absolutely positioned element has any value for left ,
width and right other than auto , then setting the left and right margin to auto will center the
element horizontally.

That means we don’t need flexbox layout to center an absolutely positioned element with a known
height and width. We just have to make sure that we give some value to top , right , bottom and
left other than auto . So, we will use 0 :

CSS

.core-inner {
position: absolute;
width: 70px;
height: 70px;
top: 0;
right: 0;
bottom: 0;
left: 0;
margin: auto;
border-radius: 50%;
border: 5px solid #1b4e5f;
background-color: #fff;
}

We do not want to repeat these five lines for all the concentric circles we are going to have, so let’s
create a separate class for this. We also don’t want to define border-radius: 50%; for all the
divs that we want to display as circles, so we will create a class for that too:

CSS

.circle {
border-radius: 50%;
}

.abs-center {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
margin: auto;

.core-inner {
width: 70px;
height: 70px;
border: 5px solid #1b4e5f;
background-color: #fff;
}

Also, add these new classes to out .core-inner element:

HTML

<div class="fullpage-wrapper">
<div class="reactor-container">
<!-- the smallest circle -->
<div class="core-inner circle abs-center"></div>
</div>
</div>

Okay, our concentric circle is centered. Let’s make it glow.

But CSS doesn’t have any "glow" property.


Don’t worry, we have the box-shadow (https://css-tricks.com/almanac/properties/b/box-shadow/)
property. Instead of giving the shadow a dark color, we will give it a bright color to make the shadow
look like glow. Pretty clever, isn’t it? 😉
Let’s do this:

CSS

.core-inner {
width: 70px;
height: 70px;
border: 5px solid #1b4e5f;
background-color: #fff;
box-shadow: 0px 0px 7px 5px #52fefe;
}

Let’s take a break and understand the syntax of box-shadow first because we will be using it a lot.
Here are what those values for box-shadow mean in that order:

• x-offset : how much we want to push the shadow on the right side (x-axis). Negative values
will push the shadow to the left side.
• y-offset : how much we want to push the shadow up or down (y-axis).
• blur-radius : how blurry we want our shadow to be.

• spread-radius : how much we want our shadow to spread.

• color : color of the shadow.

Play with these values a bit to see their effects in real time.

In real life, shadows don’t drop only outside of an object. Shadows drop upon the objects too.
Imagine a pit dug by a dog, it will have a shadow inside it, right?

We can give a shadow inside an element using the inset keyword in the box-sizing property.
To give an element both, outside and inside shadow, we simply separate them with a comma. Let’s
do this to get an outside and inside glow to our reactor’s inner core:

CSS

.core-inner {
width: 70px;
height: 70px;
border: 5px solid #1B4e5f;
background-color: #fff;
box-shadow: 0px 0px 7px 5px #52fefe, 0px 0px 10px 10px #52fefe inset;
}
Now it’s starting to look sci-fi!

Let’s create one more circle on top. We want the inner circle to display on top of the other circles, so
we will add new circle divs *above* the inner-circle in code:

HTML

<div class="fullpage-wrapper">
<div class="reactor-container">
<!-- the second circle -->
<div class="core-outer circle abs-center"></div>
<!-- the smallest circle -->
<div class="core-inner circle abs-center"></div>
</div>
</div>

The elements down in the code, are displayed above on the screen. If we put the core-outer below
the core-inner in the code, then core-inner won’t be visible, because core-outer will cover it.

Let’s give style to outer-code. The outer core will be a little bigger than the inner core and we will
give an outer and inner glow to core-outer too:

CSS

.core-outer {
width: 120px;
height: 120px;
border: 1px solid #52fefe;
background-color: #fff;
box-shadow: 0px 0px 2px 1px #52fefe, 0px 0px 10px 5px #52fefe inset;
}
I want you to do one thing: look at the shadows (glow) and try to identify which one is of which
circle. There are four shadows and two circles (until now).

To finish designing the core, we will need one more circle that will wrap the inner and outer circles:

HTML

<div class="fullpage-wrapper">
<div class="reactor-container">
<!-- the third circle -->
<div class="core-wrapper circle abs-center"></div>
<!-- the second circle -->
<div class="core-outer circle abs-center"></div>
<!-- the smallest circle -->
<div class="core-inner circle abs-center"></div>
</div>
</div>

This one will be a little bigger, and will again have same shadows, we will use a dark background for
core-wrapper:
CSS

.core-wrapper {
width: 180px;
height: 180px;
background-color: #073c4b;
box-shadow: 0px 0px 5px 4px #52fefe, 0px 0px 6px 2px #52fefe inset;
}

Creating Reactor Coils and


Rotating with CSS3 Transforms
We have the core of the reactor, now we need a tunnel around the core. Actually, we can create an
illusion of a round tunnel by drawing just one more circle little bigger than the core-wrapper . Let’s
do it:
HTML

<div class="fullpage-wrapper">
<div class="reactor-container">
<!-- the largest circle -->
<div class="tunnel circle abs-center"></div>
<!-- the third circle -->
<div class="core-wrapper circle abs-center"></div>
<!-- the second circle -->
<div class="core-outer circle abs-center"></div>
<!-- the smallest circle -->
<div class="core-inner circle abs-center"></div>
</div>
</div>

...a little wider and add same glow to the tunnel:

CSS

.tunnel {
width: 220px;
height: 220px;
background-color: #fff;
box-shadow: 0px 0px 5px 1px #52fefe, 0px 0px 5px 4px #52fefe inset;
}
Our tunnel is ready.

Make sure you do not just copy paste the code. Have a look at the glows of the circles and identify
which glow is of which circle, whether it is outside glow or inset glow.

Now, we need eight coils on this tunnel. The coils are simple rectangles, but the major challenge is
that we need the coils to run along the round path of the tunnel; not in straight line.

One way to do this would be to create eight small rectangles, shift their center to the center of the
reactor, and rotate each coil by an increasing angle (in multiples of 45deg ).

Let’s not complicate it and make one rectangle coil at a time:

HTML

<div class="fullpage-wrapper">
<div class="reactor-container">
<div class="tunnel circle abs-center"></div>
<div class="core-wrapper circle abs-center"></div>
<div class="core-outer circle abs-center"></div>
<div class="core-inner circle abs-center"></div>
<div class="coil-1"></div>
</div>
</div>
CSS

.coil-1 {
position: absolute;
width: 30px;
height: 26px;
background-color: #073c4b;
box-shadow: 0px 0px 5px #52fefe inset;
}

Now, we want to place this coil in the center at top of the tunnel. Like this:
Our reactor-container is 300px x 300px , so the center is at 150px from top and left. The tunnel is
220px wide, so its radius will be 110px . This gives us the top offset of the coil: 150px - 110px .

We can keep left of the coil to 150px , but since our coil is 30px wide, it will shift the middle of the
coil by 15px to right, that’s why we need to subtract 15px from 150px to get the left offset of the
coil.

We can either calculate these ourselves and put the value, or we can use the CSS calc() function.
Let’s use the CSS calc() function to calculate the top and left properties of the coil:

CSS

.coil-1 {
position: absolute;
width: 30px;
height: 20px;
top: calc(50% - 110px);
left: calc(50% - 15px);
background-color: #073c4b;
box-shadow: 0px 0px 5px #52fefe inset;
}

As you can see, the calc() function takes a mathematical expression as its argument and solves
it.

Now we need eight such coils but they must lie on the tunnel. To do that, as discussed, we can
simply place the eight coils at this same place, then transform their origin to the center of the
reactor, and rotate each coil by an increment of 45 degrees.

We need to update the coil’s origin because by default it is set to the center of the coil; we want it at
center of the reactor:
We will use transform-origin property to set the origin of the coil:

CSS

.coil-1 {
position: absolute;
width: 30px;
height: 20px;
top: calc(50% - 110px);
left: calc(50% - 15px);
transform-origin: 15px 110px;
background-color: #073c4b;
box-shadow: 0px 0px 5px #52fefe inset;
}

The first value, 15px , in transform-origin is the x-offset (horizontal distance) from the top-
left corner of the element, and the second value, 110px , is the y-offset (vertical distance) from
the top-left corner of the element.
The coil’s origin is now at the center of the reactor, let’s rotate it by 45 degrees using the CSS3
transform property and see what happens:

CSS

.coil-1 {
position: absolute;
width: 30px;
height: 20px;
top: calc(50% - 110px);
left: calc(50% - 15px);
transform-origin: 15px 110px;
transform: rotate(45deg);
background-color: #073c4b;
box-shadow: 0px 0px 5px #52fefe inset;
}

Great! That’s exactly what we want.

Before creating all the eight coils, let’s create a coil container div that will contain all the eight coils:
HTML

<div class="fullpage-wrapper">
<div class="reactor-container">
<div class="tunnel circle abs-center"></div>
<div class="core-wrapper circle abs-center"></div>
<div class="core-outer circle abs-center"></div>
<div class="core-inner circle abs-center"></div>
<!-- the coil container -->
<div class="coil-container">
<div class="coil coil-1"></div>
</div>
</div>
</div>

You will notice we also added a class "coil" to the "coil-1" element. We will keep all the common
styles for coils in the "coil" class, and the individual coil element classes will only have their angle of
rotation:

CSS

.coil-container {
position: relative;
width: 100%;
height: 100%;
}

.coil {
position: absolute;
width: 30px;
height: 20px;
top: calc(50% - 110px);
left: calc(50% - 15px);
transform-origin: 15px 110px;
background-color: #073c4b;
box-shadow: 0px 0px 5px #52fefe inset;
}

.coil-1 {
transform: rotate(45deg);
}

The output will remain same.

Now, let’s make all the eight coils inside .coil-container :

HTML

<div class="fullpage-wrapper">
<div class="reactor-container">
<div class="tunnel circle abs-center"></div>
<div class="core-wrapper circle abs-center"></div>
<div class="core-outer circle abs-center"></div>
<div class="core-inner circle abs-center"></div>
<!-- the coil container -->
<div class="coil-container">
<div class="coil coil-1"></div>
<div class="coil coil-2"></div>
<div class="coil coil-3"></div>
<div class="coil coil-4"></div>
<div class="coil coil-5"></div>
<div class="coil coil-6"></div>
<div class="coil coil-7"></div>
<div class="coil coil-8"></div>
</div>
</div>
</div>

...and give different rotations to all the coils (in increment of 45 degrees):
CSS

.coil {
position: absolute;
width: 30px;
height: 20px;
top: calc(50% - 110px);
left: calc(50% - 15px);
transform-origin: 15px 110px;
background-color: #073c4b;
box-shadow: 0px 0px 5px #52fefe inset;
}

.coil-1 {
transform: rotate(0deg);
}

.coil-2 {
transform: rotate(45deg);
}

.coil-3 {
transform: rotate(90deg);
}

.coil-4 {
transform: rotate(135deg);
}

.coil-5 {
transform: rotate(180deg);
}

.coil-6 {
transform: rotate(225deg);
}

.coil-7 {
transform: rotate(270deg);
}

.coil-8 {
transform: rotate(315deg);
}

Our reactor is almost ready.

Animating the Coils With CSS3


Animations
In Iron Man’s Arc reactor, the coils don’t move but they will in our reactor. We will animate the coils
to rotate along the tunnel and will use CSS3 animations for this—no JavaScript.

To create an animation, you need to know the initial and final states of the object you are going to
animate. We define these initial and final states in CSS by using @keyframes at-rule:

CSS

@keyframes reactor-anim {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}

We want the element to be at 0 degrees and animate it until it reaches 360 degrees. And we named
this animation as "reactor-anim."

The element we want to animate is .coil-contailer . Notice, we didn’t define which object to
animate yet, we have only defined the initial and the final state and name of the animation.

We need to link the element to the animation in order to take effect. We do it by using animation-
name property on .coil-container :

CSS

.coil-container {
position: relative;
width: 100%;
height: 100%;
animation-name: reactor-anim;
animation-duration: 3s;
}
Notice, we also gave the duration of animation using animation-duration property. This defines
how much time it should take to go from the “from” state to the “to” state defined using the
@keyframes at-rule.

Embedded Pen Here

We need to change two things here: we want the animation to go on infinitely and we want a linear
animation. You can see the animation is slow at the beginning, then fast, then again slow at the end
—this behavior is defined by the timing function of an animation.

Let’s make these changes:

CSS

.coil-container {
position: relative;
width: 100%;
height: 100%;
animation-name: reactor-anim;
animation-duration: 3s;
animation-iteration-count: infinite;
animation-timing-function: linear;
}

We used animation-iteration-count property to set the animation to infinite , and


animation-timing-function to make the animation linear , the default value of animation-
timing-function is ease .

Embedded Pen Here


We can combine all of these animation properties...

CSS

animation-name: reactor-anim;
animation-duration: 3s;
animation-iteration-count: infinite;
animation-timing-function: linear;

...into one shorthand property like this:

CSS

animation: 3s infinite linear reactor-anim;

Final Touches to the Reactor


Container
Our reactor is ready, now let’s make some final changes to the .reactor-container . First, we will
need one dark circle behind the reactor:

HTML

<div class="fullpage-wrapper">
<div class="reactor-container">
<!-- dark circle behind the reactor -->
<div class="reactor-container-inner circle abs-center"></div>
<div class="tunnel circle abs-center"></div>
<div class="core-wrapper circle abs-center"></div>

You might also like