Monthly Archives: October 2011

Different Colors Based on Position in List

The final change I want to make to the navigation menu, which was previously discussed in the last two posts, is to add a different color to each menu item.

Menu with different colors for border

Menu with different colors for border

On a static website which doesn’t change, this is easy. You can add a class (or an id would work also) to each item, then style each one independently.

HTML

    <ul id="nav">
      <li class="home"><a href="#">Home</a></li>
      <li class="tutorials"><a href="#">Tutorials</a></li>
      <li class="about"><a href="#">About</a></li>
      <li class="news"><a href="#">Newsletter</a></li>
      <li class="contact"><a href="#">Contact</a></li>
    </ul>

CSS

.home a { border-color: #636393; } 
.tutorials a { border-color: #B5222D; } 
.news a { border-color: #D4953C; } 
.about a { border-color: #609491; } 
.contact a { border-color: #87A248; } 

But on a dynamic site where the menus can change, such as a WordPress site, that does not work. You need a way to make the first item to be purple, the 2nd item to be red, the third item to be teal, etc.

With CSS3, there is a simple way to do this. If you use the pseudo-selector nth-child, you can specify each li item individually, then target the anchor tag inside.

li:nth-child(1) a { border-color: #636393; }
li:nth-child(2) a { border-color: #B5222D; }
li:nth-child(3) a { border-color: #D4953C; }
li:nth-child(4) a { border-color: #609491; }
li:nth-child(5) a { border-color: #87A248; }

Basically, this is saying the anchor (a) tag inside of the first li in a list, should be #636393, and then the 2nd, 3rd, 4th and 5th are also specified.

This is simple and works in the latest version of all modern browsers, including IE9! Unfortunately it does not work in IE8 and below. Many times, I am willing to let that slide, because I don’t consider the CSS3 enhancement crucial to the design. In this case, however, the color of the menu items is very important to the design and I wanted a solution that would work everywhere.

This problem can be solved by using javascript, but I wanted to see if there was a CSS only solution to my problem. I discovered a clever trick while I was searching for the answer. I really would like to credit the person who inspired this solution, but I lost the link to the blog post, so I can’t do that unfortunately.

li a { border-color: #636393; }
li+li a { border-color: #B5222D; }
li+li+li a { border-color: #D4953C; }
li+li+li+li a { border-color: #609491; }
li+li+li+li+li a{ border-color: #87A248; }

See all three solutions in the demo. (They all look the same, you need to view source to see the code differences.)

Explanation

This solution is using the Adjacent Sibling Selector. Supposedly this selector only works in IE8, but I found this solution to work just fine in IE7 also. It does not work in IE6.

The first line of the CSS will style all of the borders to the first color (#636393). The second line of CSS will take every list item is adjacent to a list item (follows it) and make them all the 2nd color. It will skip the first one, because it is not adjacent to a previous list item.

The third line will take every list item that is adjacent to a previous list item, which is also adjacent to a previous list item. This will prevent the 1st and 2nd list items from getting targeted.

Etc.

The order of the CSS is very important. In reality, the 5th list item has it’s border-color set 5 different times. Because of the cascade, the last line is the one that sets the 5th color.

Browser Support

Solution 1 will work in all browsers, but doesn’t work with a dynamic site where you are not able to specifically create class names.

Solution 2 will work in the latest version of all modern browsers, but not in earlier versions of IE.

Solution 3 works in all browsers, including IE7 and IE8. The transitions, presented in the last post, do not work in IE.

The entire navigation I’ve presented here will work horribly in IE6, so if you want to make it work there, you will need a special IE6 style sheet. I may try to do a post on that later.

Menu with Transition

In this post I am continuing the discussion of how I styled a navigation menu with transitions. The first post in the discussion is here: Vertical Navigation with a Border.

The problem I want to discuss next is how the transition caused some moving of the text, and the menu to look just a bit jumpy. I also want to demonstrate the reason you will normally add the transition properties to your normal state and not the hover state.

ul li { 
	list-style: none; 
	height: 44px; 
} 
ul li a { 
	width: 100px; 
	height: 40px; 
	line-height: 53px; 
	border-bottom: 4px solid #999;  
	padding-left: 5px; 
	color: #333; 
	text-decoration: none; 
 	display: block;
	-webkit-transition: .2s all linear;
	-moz-transition: .2s all linear;
	-o-transition: .2s all linear;
	transition: .2s all linear;			
} 
ul li a:hover { 
	border-bottom: 35px solid #999;
	height: 9px; 
}	

Explanation

The transition is added with this part of the code:
-webkit-transition: .2s all linear;
-moz-transition: .2s all linear;
-o-transition: .2s all linear;
transition: .2s all linear;

The sliding up and down of the border will take place over .2 seconds. The transition will occur on all properties that change (at least all properties that take a transition.) The easing is “linear”. Any of these values can be adjusted to personal design.

If you look at the first two menus in the demo, both have a slight shift vertically when you hover over a menu item. It appears that the transition of the border-size is not happening at exactly the same rate as the transition of the height. So the box size of the anchor tag (height + border, in this case) is not a static number.

This problem is easily solved by giving a height to the parent of the anchor tags, which in this case is the “li” tag. By setting the height to 44px, the problem is solved.

You will also notice on the demo page, on the first menu, what happens when you put your transitions on the hover state – the transition only occurs in one direction.

Browser Support

The transition will work in all of the latest versions of modern browsers, except Internet Explorer. I consider this “icing” and not necessary to the design, so I am okay with that difference. However, if you really wanted it to work in every browser, you could use javascript to make this work.