The link at the top of this page is a plain-jane, run-of-the-mill, vanilla, nothing-special link. But it can be so much more! Let's turn it into something to write home about!
To get started, let's use a bit of positioning to keep that link visible on the page where we can see it as we continue working through this exercise.
header
element, with the following rules:position: fixed;
top: 0;
left: 0;
width: 100%;
height: 200px;
background: #000;
This made a fixed page header, but it's covering our page content. We can fix that.
body
element, and set padding-top
to be the same as our header
height.Now let's center the link in our page header. Instead of using padding or margin to push the link around, let's use absolute positioning. This link is not going to be styled like a standard link, so probably best if we give it a class, rather than just selecting by tag name.
class="launch-button"
to the a
element..launch-button
. Add the following styles:position: absolute;
left: 50%;
top: 50%;
The link is now in the middle of the header... sorta. It's actually riding a bit low and right, because we haven't actually positioned the link's center, we've positioned it's left and top edges. For the link to be truly centered, we need to offset back toward the top by half the link's height, and toward the left by half the link's width. We could try to measure the link and do the math, but it makes more sense to have the browser do the math for us. We'll do so by using a new css property: transform
. The transform
property is used to visually transform an element by skewing, rotating, scaling, and/or translating (moving).
.launch-button
selector:transform: translate(-50%, -50%);
(The two numbers correspond to horizontal and vertical.)The link is now exactly centered... even though we don't know the exact width of either the header or the link itself. It's a useful technique for centering an absolutely-positioned item in its container.
This approach may seem a bit counter-intuitive, because it looks like we asked the link to shift left by 50%, then back right by 50%. So why didn't it go back to it's starting position? The answer is that when we use a percentage as a unit for positioning we're referring to a percentage of the parent container. For transform, on the other hand, percentages refer to the element being transformed. So what we're really doing here is saying "Move from the left side half the width of the header, (left: 50%;
) then move back by half the width of the link ( transform: translate(-50%, -50);
). Similarly, move down from the top by 50% the height of the header, then back up by half the height of the link.
The link has been located in our 'hero' position... time to style it.
Let's get rid of some default 'link' styles, and add some 'button' styles.
.launch-button
ruleset, add:text-decoration: none;
background-color: #aa0000;
color: white;
font-size: 20px;
padding: 15px 30px;
border-radius: 10px;
No surprises here, we've used all these properties before. Let's reinforce the interactive nature of the button by giving it a :hover
state and :active
state.
.launch-button:hover
. Add:background-color: #cc0000;
box-shadow: 0 0 8px #ff0000;
.launch-button:active
. Add:background-color: #750000;
box-shadow: 0 0 2px #750000;
The box-shadow property is one you may not have used. It's very flexible, and can make all kinds of shadows/glows. You can read the docs to learn more, or you can use a box-shadow generator.
Our button now has a fun glow when we hover, and darkens when pressed. It feels like a button... but maybe not a very exciting one.
We've used font-awesome before to add icons. We'll use it here as well... and we're going to use the transform
property to have some fun with them. This page already has the font-awesome library added in the head
, so we're good to go.
a class="launch-button"
element here in the html page, on a line right after the word "launch" but before the closing /a
tag, add the following html:
<div class="rocket">
<i class="fas fa-burn"></i>
<i class="fas fa-rocket"></i>
</div>
The i
tag normally italicizes text, but font-awesome has appropriated it for adding icons. We've added two icons: "burn" and "rocket."
Now, let's put these icons where we want them to go. I'd like to have the rocket sitting to the right of the text, pointing straight up, with the flame coming out the bottom. The div class="rocket"
container will serve as a positioning parent for the icons, and the container itself will also be positioned within the button.
.launch-button .rocket
and set:position: absolute;
This makes it a positioning parent for its descendant elements, in this case, the icons..launch-button .rocket i
, which selects both icons. Set:position: absolute;
top: 0;
left: 0;
The icons are now smashed together in the .rocket
container, absolutely-positioned in the same place. Now let's use transform
to arrange them the way we want.
.launch-button .fa-rocket
and set transform: translate(-50%, -50%) rotate(-45deg);
. This centers the rocket in its container (just like we did the button in the header), and rotates it to point straight up..launch-button .fa-burn
and set transform: translate(-50%, -15%) rotate(180deg) scale(0.3);
. This centers it horizontally, aligning it with the rocket, but leaves it hanging lower vertically, so it's toward the rocket exhaust nozzle. It also rotates it 180°, and makes it smaller.The overall rocket is still in the wrong position. Let's make room for it to live next to the button text using padding, then position it in the space we make.
.launch-button
ruleset, change padding
to 15px 60px 15px 30px;
. We're opening a space on the button's right side..launch-button .rocket
ruleset, add:top: 50%;
Centers the rocket vertically.right: 40px;
Positions the rocket 40px from the right edge, in the gap we made.The flame gets a bit lost, let's use color!
.launch-button .fa-burn
ruleset add color: orange;
.Seems like the rocket should have some interaction on :hover
and :active
too, doesn't it? Let's progressively increase engine power as we approach launch!
.launch-button .fa-burn
, change the value for scale
to 0.1
. The booster will be 'off' by default..launch-button:hover .fa-burn
. Note how this selector works. It's saying "Select elements with the .fa-burn
class that are inside of a hovered .launch-button
. So even though we're styling the flame, this ruleset will be applied when the button is hovered, not the flame icon itself.transform: translate(-50%, -15%) rotate(180deg) scale(0.4);
. We're overriding the default transform to make the flame bigger on hover..launch-button:active .fa-burn
, and set transform: translate(-50%, 25%) rotate(180deg) scale(0.8);
. We're overriding to make the flame still bigger on active. We're also shifting it downward so the whole flame is exposed.Seems like the whole rocket could also get bigger on hover, to make it pop a bit. We'll scale the container that holds both icons, treating our rocket arrangement as a single element.
.launch-button:hover .rocket
to select the .rocket
container when the button is hovered. Add transform: scale(1.3);
.Could we? Make the rocket actually launch? I think we can!
First, let's create an environment to launch into, using a linear-gradient background.
background
with background: linear-gradient(to bottom, #000000 40%,#0560aa 80%,#7cd4ef 100%);
.I used The Colorzilla Gradient Generator to make it easy.
Now, when the button is active, let's push the button back and bring the rocket up and forward.
.launch-button
change top
to 75%
. We're moving the whole button downward to make room for it to launch above..launch-button:active
ruleset, add transform: translate(-50%, -20%) scale(0.7);
. We're pushing the button down and scaling it way back when active..launch-button:active .rocket
ruleset to select the rocket, and add transform: rotate(-15deg) translate(60px, -140px) scale(3.5);
. We're launching the rocket away from the button.That's pretty fun! I feel like the label of the button is a little plain though, and it's strange that there's still a gap next to it where the rocket was. Let's clean it up. We'll start by adding a span
around the word "Launch" so we can style it safely without affecting the icon style.
Launch
becomes <span class="label">Launch</span>
.letter-spacing: 0.1em;
text-transform: uppercase;
color: white;
color: orange;
text-shadow: 0 0 3px rgb(251, 255, 0, 0.5);
.launch-button:active
ruleset, add padding: 15px 30px;
to take away the gap when the rocket is safely away.Note the text-shadow
? It's similar to box-shadow
, but for text. Here's a useful generator.
What's really going to send this thing over the moon (sorry, I'm a dad) is transitioning from one state to the next, instead of just 'jumping' from default to hover to active. CSS lets us do that with the transition
property. Strap yourself in. (I'm on fire!)
.launch-button
ruleset, add transition: transform 0.5s, background-color 0.1s, padding 0.5s, box-shadow 0.1s;
. Note how we are giving a list of properties to transition, each with a duration. So padding
, for instance, will transition over 0.5 seconds..launch-button .rocket
ruleset, add transition: transform 0.5s;
..launch-button .label
selector, add transition: color 0.2s, text-shadow 0.2s;
..launch-button .fa-burn
selector, add transition: transform 0.4s;
.Press the button and marvel at what you have made!
You might think we're done... you might want to be done... but no, we have one final area to explore. Transitions are great, but what if you want an animation to keep going?