How to create a large CCS3 menu with transitions
While playing around with some CSS3 transitions for an image gallery representation, I ended up creating a menu that I really liked, so I decided to write a tutorial around it. Have a look at the demo (or this pen) to see what we’re going to create. After building the horizontal version, it’s very easy to create a vertical menu as well. But we’ll get to that.
Note: All versions should work properly in the latest versions of Chrome, Firefox, Opera, Safari, and Internet Explorer, as well as work without transitions in IE8 & IE9.
So, first of all…
The HTML code
We are going to create our menu as an unordered list of links and images, and place it inside a nav
element with the class menu-container
, as follows:
<nav class="menu-container"> <ul> <li> <a href="#">Home sweet <strong>home</strong></a> <img src="home.jpg" alt="Home sweet home" /> </li> <li> <a href="#">Some cool quote about <strong>movies</strong></a> <img src="movies.jpg" alt="Some cool quote about movies" /> </li> <li> <a href="#">Some cool quote about <strong>music</strong></a> <img src="music.jpg" alt="Some cool quote about music" /> </li> <li> <a href="#">Some cool quote about <strong>games</strong></a> <img src="games.jpg" alt="Some cool quote about games" /> </li> <li> <a href="#">Some cool quote about <strong>books</strong></a> <img src="books.jpg" alt="Some cool quote about books" /> </li> <li> <a href="#">Some cool quote about <strong>art</strong></a> <img src="art.jpg" alt="Some cool quote about art" /> </li> </ul> </nav>
Note: In the demo, there is more HTML & CSS code, but since it’s irrelevant of the actual menu, I’m not explaining it in the tutorial. You can find the whole code in the [download id=”18″ format=”1″].
The CSS code
The idea is that the images are going to be visible, and the anchor tags are going to sit on top of them with an opacity
value of 0, until there is a hover
state. When this happens, the anchor will become visible, and will be expanded a little bit over the image.
To begin with, we will reset some styles of our ul
and li
elements, and we will set the width
of our menu to 100%.
.menu-container ul, .menu-container li { margin: 0; padding: 0; list-style: none; position: relative; } .menu-container { width: 100%; }
The next step is to set the width
of the list items, which will hold the images. We want to use 6 images, so since 100 / 6 = 16.66666666666667, we’ll set the width
to that. We’ll also specify that the width
of each image will expand to the 100% of its container (i.e. the li
element).
.menu-container li { float: left; width: 16.66666666666667%; } .menu-container li img { width: 100%; }
That was the simple part. Now, let’s move to the anchors. I broke the whole CSS code for the anchor tag in 2 blocks, just to explain it easier.
Starting with the first block, the important part is to specify the element’s position
as absolute
(that’s why we earlier set the li
element’s position
as relative
), and its width
and height
values to 100%, to make sure it will cover the image. The box-sizing
values are there to make calculations (e.g. with padding
) easier.
.menu-container li a { position: absolute; width: 100%; height: 100%; -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; padding: 10%; line-height: 1.4em; font-size: 1.5em; background-color: #000; color: #fff; }
We also have to specify that the initial opacity of the element is zero, and the appropriate values for the transitions.
.menu-container li a { filter: alpha(opacity=0); -moz-opacity: 0; -khtml-opacity: 0; opacity: 0; -webkit-transition: all 0.2s ease-in-out; -moz-transition: all 0.2s ease-in-out; -o-transition: all 0.2s ease-in-out; transition: all 0.2s ease-in-out; }
Finally, let’s style the hover
state. We’ll expand a little bit the width and height of the element (10% larger than the image), and use some margin values to center it. We’ll also set its opacity value to 0.8. Remember that this process will be animated due to the transition value we set before.
.menu-container li a:hover { width: 110%; height: 110%; margin-top: -5%; margin-left: -5%; padding: 14%; text-decoration: none; filter: alpha(opacity=80); -moz-opacity: 0.8; -khtml-opacity: 0.8; opacity: 0.8; }
Have a look at the demo (or this pen) to see what we’ve just created. You can also download the [download id=”18″ format=”1″].
But, let’s not stop here. Let’s build a…
Vertical version
Transforming the menu to work vertically is extremely easy. The HTML code remains the same. We will only have to set the .menu-container
to something smaller than 100%, and set the li
element’s width
to 100% (adding a small margin fix if it’s required).
.menu-container { width: 13%; } .menu-container li { width: 100%; float: left; margin-top: -2%; }
Here you go (pen). You can find this version as well in the [download id=”18″ format=”1″].
Removing opacity from text
If you notice, the opacity
value is inherited to the text as well, making it a little transparent. I quite like it that way, but since it’s highly likely that someone will want the text to be completely opaque, let’s create a workaround.
We will add the following before setting the anchor element’s opacity
values (which are still zero).
.menu-container li a { background-color: rgba(0, 0, 0, 0); filter: progid:DXImageTransform.Microsoft. gradient(startColorStr='#80000000', EndColorStr='#80000000'); -ms-filter: "progid:DXImageTransform.Microsoft. gradient(startColorStr='#80000000', EndColorStr='#80000000')"; }
And we will replace the opacity
values of the hover
state with the following:
.menu-container li a:hover { filter: alpha(opacity=100); -moz-opacity: 1; -khtml-opacity: 1; opacity: 1; background-color: rgba(0, 0, 0, 0.7); filter: progid:DXImageTransform.Microsoft. gradient(startColorStr='#80000000', EndColorStr='#80000000'); -ms-filter: "progid:DXImageTransform.Microsoft. gradient(startColorStr='#80000000', EndColorStr='#80000000')"; }
That’s all! This version’s demo is here (pen). As you probably already figured out, you can find this version as well in the [download id=”18″ format=”1″].
For any issues or questions, feel free to post a comment.