No replies
Hugo's picture
Last seen: 8 years 11 weeks ago
Joined: 2004-06-06
Posts: 15668
Points: 2806

This is a topic that crops up quite frequently so it seems to make sense to explain it once more for the record Smile

There are variations to this approach, but this version will serve adequately as a general example people can follow.

A very common requirement of web site page navigation is the ability to distinguish the page being viewed by the means of highlighting the nav link of that particular page, often achieved by adding a distinct coloured background often the same as would be seen if one hovered a link but which in the case of the current page is set permanently to the background colour.

Scripting this requirement is usually the preferred method of achieving this aim, but it is also possible to do using CSS alone, and it is this that I wish to demonstrate here as it's a very simple technique yet it repeatedly crops up in posts on the forum.

The technique pivots around one essential aspect and that is of identifying each page with a unique ID or token, every page must carry it's own unique 'name' this can be a class token or fragment identifier, these are placed on either the html tag or body tag as representatives of the top most parent/ancestral elements in a page, they are placed on these elements due to the manner in which we target rules using the descendent selector method and which will be explained later on.

My preference is to use IDs for the page names as these are unique to a page they won't possibly appear elsewhere in that page to cause issues, and for the sake of this guide we'll use the body tag to hold these IDs; we'll also imagine two pages 'about.html' and 'contact.html'.

The first stage is to identify the pages, so to the body tag on each page we add:

<body id="about-us">

<body id="contact-us">

Next and taking - as an example - a bog standard piece of ul li markup we ensure that each navigation item has a class:

  <li><a href="#"home</a></li>
  <li class="about"><a href="#">about</a></li>
  <li class="contact"><a href="#">contact</a></li>

The class is placed on the li element rather than the anchor itself as it allows us the greater range of style targeting, with the class on the li we can either style the li element by referring to it's class or we can style the anchor by targeting it via descendent selectors i.e
 li.about a {}
Now we get to the bit that seems to trip people up; we need to style these links and we need intelligence at work as the the CSS and HTML alone need to work out what page is being displayed and therefore which link needs to be highlighted; now CSS is not a dynamic language it's a simple declarative language that applies styling it's not scripting, so it can't apply any logic or dynamic structure itself, however there is a means we can use to achieve our desire and that is in the use of descendent selectors and grouped selectors.

We will imagine that the styling we wish to apply to highlight a link is to change the text colour, this is by way of keeping things simple.

So our ruleset to handle the link highlight looks like this:

#about-us .about,
#contact-us .contact {

So how does this work? As was stated at the beginning each page has one unique ID no other page has this ID so it represents a unique condition and it is this condition that we are going to use to establish what page we are actually showing.

Now that we can tell what page is being shown by it's unique Identifier we can apply some pseudo logic to the equation; we know that if we are looking at the 'about-us' page we want the .about class element to be styled, but we do not want the .contact class element to take the styling, and the means to achieving this is to use some pseudo logic that CSS can provide; looking back at the ruleset we can see a descendent selector at work in the form of  #about-us .about what this set of selectors is saying is apply the property and value color:red to an element that has the class .about and which has a parent or ancestor element called #about-us in other words we state an explicit set of conditions that must exist in order for this ruleset to be applied and this set of conditions can only exist once due to the fact that the ID #about-us will only ever appear on one page thus the link .about can only take the styling when it sees an ancestral element with an id #about-us; the ruleset has now found a matching condition.

The other part of the rulesets feature is to apply the styling to all the links that we have, and to do this we use grouped selectors.

We need the other links to take the styling when they too find a matching condition and we achieve that by grouping further descendent selectors into that ruleset. We group selectors by ending each separate selector group with a ',' comma on all but the last group in the set, this way we can state all the unique descendent selectors on the same ruleset and they can apply the same properties as and when their matching conditions are met.

So to explain again:

#about-us .about,
#contact-us .contact {

if you are viewing the 'about' page then the first selector group is matched but the second can't be as #contact-us doesn't exist on the page, now navigate to the #contact-us page and the selector group #contact-us .contact is matched as the body tag now has the id #contact-us, the 'about' link is now deselected as the #about-us body ID no longer exists on the page.

Before you make your first post it is vital that you READ THE POSTING GUIDELINES!
Please post ALL your code - both CSS & HTML - in [code] tags
Please validate and ensure you have included a full Doctype before posting.
Why validate? Read Me