October 3rd in Articles, CSS3 by .

Tabs And FAQ’s With The CSS3 :target Pseudo Selector


Cascading Style Sheets are one of the core web technologies that are going through some big changes. The CSS specification has become modular consisting of around 26 modules that range from the new selectors to web fonts and media queries. One of the new selectors I stumbled on is the new :target pseudo selector. In this article I will be looking at how we can put this selector to use as we build a stylish FAQ widget. Through the course of the article I will also look at some of the HTML5 sectioning content tags as well as some other CSS3 goodness.

To get started create a new HTML document:

<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="utf-8" />
		<title>FAQ</title>
	</head>
	<body>

	</body>
</html>

Next we need to create the basic structure of our document. For this I am going to be using the new HTML article and section tag. There exists much confusion over when to use article and when to use section and whether both should even be, or will remain, in the HTML5 specification but, as both are still in the specification I am going to make use of both here and I will explain why. Add the following to your HTML document:

<article id="faq_container">
	<section id="questions">

	</section>
	<section id="answers">

	</section>
</article>

If you read the HTML5 specification the difference between article and section is explained as follows:

article: The article element represents a self-contained composition in a document, page, application, or site and that is intended to be independently distributable or reusable, e.g. in syndication.

And for section:

section: The section element represents a generic section of a document or application. A section, in this context, is a thematic grouping of content, typically with a heading.

With the above I believe you can gather why I marked up the FAQ widget the way I did. The FAQ widget can most definitely be both redistributable and reusable as a unit and I therefore used the article tag as my container for the entire widget. Inside the container we have the questions and answer sections. These are not independently distributable so cannot be seen as independent units but, can definitely be seen as thematic grouping of content. I also believe the same can be said of each individual answer and therefore I marked them up as such.

Add the following into the answers section:

<section class="faq" id="faq1">
	<h1>FAQ 1</h1>
	<p>Augue eu eros pid cum in. Placerat lundium mid pulvinar a integer? .....</p>
</section>
<section class="faq" id="faq2">
	<h1>FAQ 2</h1>
	<p>Ultrices in cum cras cursus? In?....</p>
</section>
<section class="faq" id="faq3">
	<h1>FAQ 3</h1>
	<p>Augue. A nec, nascetur tincidunt a ac placerat nisi! Montes nisi! ....</p>
</section>
<section class="faq" id="faq4">
	<h1>FAQ 4</h1>
	<p>Arcu hac mid, duis aenean, dolor penatibus cras ac integer enim, ....</p>
</section>

I have shortened the Lorem Ipsum text above drastically for the sake of space but, to really see the effect of the widget we are building here, I would suggest you fill them up with a decent amount of dummy text. So we are almost ready to add the CSS magic, just one last thing. Inside the questions section add the following:

<ul>
	<li><a href="#faq1">Question 1</a></li>
	<li><a href="#faq2">Question 2</a></li>
	<li><a href="#faq3">Question 3</a></li>
	<li><a href="#faq4">Question 4</a></li>
</ul>

A simple unordered list will make up our FAQ’s menu.

The :target Pseudo Selector

Before we jump into styling the widget with CSS, let’s first look at the :target pseudo selector. If you look at the above code you will notice that the links in our navigation are simple anchor links that would usually jump to the area in the current document that matches the id specified in the href attribute. We could also say that the value of the href attribute specifies the ‘target’ of the link. This is then where our new selector comes into play.

Currently the demo page is a standard HTML page and, depending on the size of the browser window, clicking on the various links will jump the page to that FAQ. Let’s make this a little more interactive. Create a new CSS files and add it to the head of your document:

<link rel="stylesheet" href="css/target_widget.css" />

Next, add the following to your CSS file:

.faq {
    display: none;
}
.faq:target {
    display: block;
    margin: .5em;
}

Opening the demo page now will demonstrate how useful this selector can be. Instead off displaying all of our content, we start off with just our links and as you click on the various links, only that part of the document is displayed to the user. This usually takes a couple of lines of JavaScript using jQuery and a bunch more if you wrote it in plain vanilla JS. With this new interactive feature of our FAQ let’s add some more style to really make it interesting.

Styling the Widget

Some off the first things we want to do is add some basic styling to the body of our document and ensure that the new HTML5 tags we are using is set to block. Why do we need to do this? Well before these new tags are added to the browsers internal style sheet, here is Firefox’s for example, they will be inline and they really need to be block:

body {
    background-color: #0a0c10;
    font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;
}
article, section {
    display: block;
}

Next, let’s style or FAQ widget and use some CSS3 to make it just that little more special. Add the following to your style sheet:

#faq_container {
    background-color: #10141b;
    border: 7px solid #fff;
    width: 40em;
    height: 250px;
    border-radius:10px 0 0 10px;
    /* For Mozilla pre Gecko 2.0/Firefox 4.0 http://goo.gl/3haY */
    -moz-border-radius:10px 0 0 10px;
    /* For Webkit Safari 3 - 4 */
    -webkit-border-radius:10px 0 0 10px;
}
#questions {
    position: relative;
    float: left;
    width: 10em;
    font-size: 1em;
}
#answers {
    position: relative;
    float: left;
    background-color: #e4e8ef;
    color: #333;
    width: 30em;
    height: 250px;
    overflow: auto;
}

Looking at the code above, everything is pretty stock standard stuff you have probably done a multitude of times before. One thing that might have caught your attention though, is the border-radius property. The border-radius property, introduced in CSS3, is giving web developers the ability to create smooth, rounded corners, something that has been a real pain up to now, with no additional images, HTML or hacks. With literally that one line of CSS you are all set with full support in Opera 10.5+, Safari 5, Chrome and believe it or not, Internet Explorer 9.  To add support for Safari 3 – 4  as well as Firefox 1 and up all you need to add is the last two lines. For version of Internet Explorer prior to to version 9, you are stuck with the old techniques unless, you employ the use of CSS3Pie.

If you open the demo now you will see that, apart from the links, we have a pretty decent looking widget. Before we dive into much more, let’s just add some basic styling for paragraph tags inside our section tags:

section p {
    margin-top: 0;
    line-height: 150%;
}

With that let’s style our links. Add the following to your CSS file:

#questions ul {
    margin: 0;
    padding: 0;
    list-style-type: none;
}

#questions li {
    display: block;
    background-color: #08232b;
    color: #fff;
    border-top: 1px solid #3c4c66;
    border-bottom: 2px solid #000;
}

#questions a:link, #questions a:visited {
    display: block;
    color: #fff;
    padding: .7em .5em .7em 1.2em;
    text-decoration: none;
}

#questions a:hover, #questions a:focus {
    background-color: #3c4c66;
}

With this our FAQ widget is done. Before closing out this, let’s look at an alternative use for the :target pseudo.

Tabbed Interface

In this next section we are going to change the way the FAQ’s are styled. We are going to change the widget into a tabbed interface. Create a new CSS file called target_tabbed.css and replace the current CSS file in your HTML with this one. Next add the following to the new CSS file:

body
{
	background-color:#fff;
	font-family:Verdana, Geneva, Arial, Helvetica, sans-serif;
}
#questions ul {
    margin: 0;
    padding: 0;
    list-style-type: none;
}

#questions li {
    position: relative;
    float: left;
}

#questions li a {
    display: block;
    margin-right: .2em;
    padding: .5em .7em .5em .7em;
    border-top-right-radius: 10px;
    border-top-left-radius: 10px;
}

#questions li a:link, #questions li a:visited {
    background-color: #333;
    color: #fff;
    text-decoration: none;
}

#questions li a:hover, #questions li a:focus {
    background-color: #edecec;
    color: #333;
}

#answers {
    clear: left;
    display: block;
    margin-top: -10px;
}
.faq {
    display: none;
    border: 2px solid #333;
    width: 60em;
}
.faq h1 {
	font-family: 'Vollkorn', arial, serif;
	margin:0;
}
.faq:target {
    display: block;
    padding: .5em;
}

Nothing in the HTML structure of our document structure is going to change just our CSS. Go ahead and open up the tabbed demo. There is a little caveat with regards to the :target pseudo selector and I look forward to reading the comments and see if someone can pick up on what that is.

  • Anonymous

    As mentioned on Reddit: The caveat I hinted to in my post is that if you, for example, linked to the FAQ page without linking directly to one of the anchors/targets, you would find that the right container, or the content beneath the tabs, are empty until you actually clicked a link.

    Have you found a work around for this? I tried the CSS3 not() selector but, that does not quite the trick.

    So, if the content you wish to display is not of a primary nature, shown entirely based on a user action, then you are good to go but, if you want to have at least the first item visible on load, you will either have to link to the first anchor or, use JavaScript or another solution.

  • Bernardes Claudio

    It’s pretty cool, but how prevent a jump to the anchor ?

    • Anonymous

      Hey Bernardes, in which browser and version are you experiencing this?

  • Pingback: CSS Summit 2011 – Notes from Day 2

Performance Optimization WordPress Plugins by W3 EDGE