One of the benefits of being a web development teacher is that I can be inspired by the work of students. That was the case recently in the site of Kalina Whyte, a student in my 2nd year Web Communications class. The navigation she created for the first revision of her portfolio was well-designed, and inspired me to push it further, creating the result you can see here. All of the photographs shown are by Kalina, and used with her permission, with the exception of the “Contact” mail image, which is by Peter Lee and licensed under Creative Commons.
Kalina’s navigation bar was essentially what you see in the default state: static and unchanging. I thought it could be brought to life with a little CSS. The approach I used has a lot of similarities to the basic CSS image gallery I’ve demonstrated earlier, with a few differences: I’ve simplified the markup to just a plain series of links with images inside them, within a nav
element:
<nav id="k-nav">
<a href="#">Home
<img src="watch.jpg" alt="Photograph of a watch"></a>
<a href="#">About
<img src="kalina-whyte.jpg" alt="Photograph of Kalina Whyte">
</a>
<a href="#">Portfolio
<img src="rocks.jpg" alt="Photographs of rocks">
</a>
<a href="#">Contact
<img src="mail.jpg" alt="Photograph of air mail envelopes">
</a>
</nav>
I wanted the navigation to do two things: have the blue bar to the left of every link grow during a hover, and have the image at the top change with a fade-in. The initial CSS is:
nav#k-nav {
border-radius: 20px;
background: #3F3935;
float: left;
padding-top: 300px;
padding-bottom: 40px;
width: 300px;
position: relative;
}
nav#k-nav a {
display: block;
color: #CFCECE;
text-decoration: none;
border-left: 8px solid #356374;
text-transform: uppercase;
padding: 8px;
padding-left: 20px;
border-bottom: 1px dashed #000;
text-shadow: 2px 2px 2px rgba(0,0,0,0.6);
transition: .7s all linear;
}
The bar on the left side of each link is created by changing the left border; animating it on hover is therefore pretty easy. We already have the transition set up in the declaration for the links (to which you’d have to add vendor prefixes for browsers that require them), so all we need to do is indicate the change:
nav#k-nav a:hover {
border-left-width: 20px;
}
The tricky part is the images. The first thing to do is get them into the correct place: you’ll notice that I placed position: relative
on the <nav>
itself, in order to achieve this next step:
nav#k-nav a img {
width: 250px;
border-radius: 50%;
overflow: hidden;
position: absolute;
top: 25px; left: 25px;
opacity: 0;
}
That stacks the linked images at the top of the <nav>
element. They’re invisible, due to the fact that opacity
is set to 0
, and circular, due to the border-radius
and overflow: hidden
.
Next, I want to make the associated image show up when the user hovers over the correct link, which is also very easy:
nav#k-nav a:hover img {
opacity: 1;
}
The complication comes from the fact that I want to have one image show by default, to indicate what page the user is on. For example, let’s say we were on the home page: in that case, I want to have the first image visible by default. I have an additional issue: because absolute positioning stacks overlapping elements like playing cards dealt onto a table, the image of the watch is at the bottom of the pile. I need to raise that to the foreground:
nav#k-nav a:first-child img {
z-index: 1;
opacity: 1;
}
(Typically this would be done in an embedded style sheet, as you’d wish different images to be visible on different pages.)
That works, but immediately makes the other navigational images invisible, as they are now underneath the watch image. We’ll change the :hover
declaration above to compensate:
nav#k-nav a:hover img {
opacity: 1;
z-index: 2;
}
Finally, we need to animate the transition of the fresh images and place a border around their outside edge. You’ll find that simply setting a border
doesn’t have the visual quality you might want: the photograph may appear to be “pinched” in the browser, with black gaps on its edges. Instead, we’ll use a special derivation of box-shadow
: one with no offset, no blur, only a spread value and a color:
nav#k-nav a img {
width: 250px;
border-radius: 50%;
overflow: hidden;
position: absolute;
top: 25px; left: 25px;
opacity: 0;
transition: .7s all linear;
box-shadow: 0 0 0 3px #000;
}
That’s it! It’s my intention to take this idea much further in future articles: I’d like to thank Kalina for the original inspiration.
Enjoy this piece? I invite you to follow me at twitter.com/dudleystorey to learn more.
Check out the CodePen demo for this article at https://codepen.io/dudleystorey/pen/LzfAg