Archive for October, 2011

Different Colors Based on Position in List

Posted on: October 18th, 2011 by Lisa 3 Comments

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

Posted on: October 10th, 2011 by Lisa No Comments

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.

/*****************************************************************************************/

Vertical Navigation with a Border

Posted on: October 7th, 2011 by Lisa No Comments

I have been working a website with vertical navigation with some transitions and different colors on each item. The menu brought up some interesting CSS issues. I am breaking it down into smaller chunks and tackling each issue in separate posts.

I’m starting with the simplest issue and that is setting up the navigation with a small border on the bottom. The goal is to have the border grow behind the text when the user hovers.

Menu on the right showing the hover state. The border on the bottom grows to show which item user is hovering over.

ul li { 
	list-style: none; 
} 
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;
} 
ul li a:hover { 
	border-bottom: 35px solid #999;
	height: 9px; 
}	

Explanation

The code is similar to Horizontal Navigation, except you don’t need to float the individual list items, so it is even more simple.

The important part of the code is:
height: 40px;
line-height: 53px;
border-bottom: 4px solid #999;
padding-left: 5px;
display: block;

display: block changes the anchor tag to a block level element allowing you to give it a height. (Normally anchor tags are inline elements with no height.) The full height of the element is 44px. 40px from the height, and 4px from the border.

If I wanted the text centered in it’s box, I could have used a line-height of 40px, which is a standard technique for centering text vertically. However, I wanted the text close to the border. So I set the line-height to 53px and that centers the text on a 53px box, which ultimately places it closer to the border as I wanted. It isn’t the only solution, I could have messed around with marigns/padding, but this seemed the quickest.

The real issue is the hover state.

ul li a:hover { 
	border-bottom: 35px solid #999;
	height: 9px; 
}

I wanted the border to be a full 35px when hovering, so it comes up behind the text. If I didn’t change the height to be smaller, it causes a problem, similar to what I discussed in this post. However, in this case, the outline solution won’t work because I only have a border on the bottom, and outline goes on all 4 sides. See the demo, first column, for a display of the problem.

Changing the height of the box in the hover state fixes the problem. If I want to grow the border to be 35px, I need to make the height 9px, to make sure the total height remains at 44px. 9px + 35px = 44px. In the regular state: 4px + 40px = 44px. The individual numbers are not important. The important part is the TOTAL box height which = height + border + margin + padding. In my case I have no margin or padding.

In my next post, I will show how adding a transition to the border changing caused a problem and how I fixed it.

/*****************************************************************************************/