Now that we have the markup ready, let us look at how we should be styling it. HTML5 Boilerplate comes with a stylesheet that has the best default styles. If you open main.css
, you will find the following section in between the Chrome Frame prompt
style rules and the Helper classes
section:
This is where we will compose our style rules. Later on, we will look at how you can use some of the style frameworks to make writing this easier with Sass (http://sass-lang.com) or Less (http://lesscss.org/).
Without even writing a line of CSS, you will note that our page looks like the website displayed in the following screenshot:
This default style is thanks to the normalize style rules that are available in HTML5 Boilerplate.
For a very long time, the recommendation was to use reset.css
, which is available at html5doctor.com/html-5-reset-stylesheet/
and resets the margin and padding of every available element to 0
, in addition to making the font size of all headings the same as the body text and without a higher font weight.
HTML5 Boilerplate recommends against this policy. Browsers provide useful browser defaults, which would make your stylesheets smaller as you don't have to redeclare those styles again.
With normalize.css
, you wouldn't be seeing the following kind of clutter in your debugging tools:
Nicolas Gallagher, one of the co-creators of normalize.css
, has written in great detail about why it is better than reset.css
at nicolasgallagher.com/about-normalize-css/
, which is a good read for those still unconvinced about the merits of normalizing CSS.
In Chapter 1, Before We Begin, we briefly saw that HTML5 Boilerplate comes with a bunch of default classes that are useful to work with. You would have noticed that we are using some of these classes in our style rules.
All our helper classes are defined last, so they can override all your other styles when used. Make sure the properties they override are not over-specified elsewhere; you can read more about specificity at www.w3.org/community/webed/wiki/Inheritance_and_cascade#Specificity.
In our project, we want to have a spiffy logo for the Sun & Sand Festival 2012
heading. HTML5 Boilerplate has a handy image replacement class that can be used for this. In the markup, we will simply add a class called ir
to the h1
tag, as shown in the following code:
<h1 class="ir">Sun & Sand Festival 2012</h1>
What this does is apply the styles specified in HTML5 Boilerplate's image replacement class (ir
) to hide the text. All you need to do then is add a background image to the h1
element along with its width and height, so it displays as per your specification as shown in the following code:
header h1 { background-image: url('/img/heading-banner.png'), width: 800px; height: 300px; }
This will result in the heading looking similar to the following screenshot:
Our markup has content, which we want to show only when a user clicks. In our website, we want a Google Map to show, when the user clicks on the Getting Here link. It is very simple to do so by using an iframe
, as shown in the following code snippet:
<iframe width="425" height="350" frameborder="0" scrolling="no" marginheight="0" marginwidth="0" src="http://maps.google.com/maps?f=q&source=s_q&hl=en&geocode=&q=ngor+terrou+bi,+dakar,+senegal&aq=&sll=37.0625,-95.677068&sspn=90.404249,95.976562&ie=UTF8&hq=ngor&hnear=Terrou-Bi,+Bd+Martin+Luther+King,+Gueule+Tapee,+Dakar+Region,+Guediawaye,+Dakar+221,+Senegal&t=m&fll=14.751996,-17.513559&fspn=0.014276,0.011716&st=109146043351405611748&rq=1&ev=p&split=1&ll=14.711109,-17.483921&spn=0.014276,0.011716&output=embed"> </iframe>
But this means, as soon as your page loads in a browser, the browser will attempt to show the map immediately and fetch assets from Google Maps. But we only want this map to show when the user clicks on the Getting Here link. HTML5 Boilerplate provides a class name that you can use for such purposes. We will apply a class called hidden
to make sure these elements do not render until they are explicitly made to display. The hidden
class is used in the following code snippet:
<iframe class="hidden" width="425" height="350" frameborder="0" scrolling="no" marginheight="0" marginwidth="0" src="http://maps.google.com/maps?f=q&source=s_q&hl=en&geocode=&q=ngor+terrou+bi,+dakar,+senegal&aq=&sll=37.0625,-95.677068&sspn=90.404249,95.976562&ie=UTF8&hq=ngor&hnear=Terrou-Bi,+Bd+Martin+Luther+King,+Gueule+Tapee,+Dakar+Region,+Guediawaye,+Dakar+221,+Senegal&t=m&fll=14.751996,-17.513559&fspn=0.014276,0.011716&st=109146043351405611748&rq=1&ev=p&split=1&ll=14.711109,-17.483921&spn=0.014276,0.011716&output=embed"> </iframe>
Do note that this makes the content disappear from screen readers and the browser displays.
Screen readers are devices used to aid in reading a web page for those who are unable to view text on the screen. Victor Tsaran has a great introduction to screen readers in a video available at www.yuiblog.com/blog/2007/05/14/video-intro-to-screenreaders/.
The rule that makes this happen is as follows:
.hidden { display: none !important; visibility: hidden; }
This ensures all screen readers (JAWS and Windows-Eyes being the most popular ones) would hide all elements that have this class name applied to them.
If you want the content to be available to those who use screen readers, you should use the next class that we will be learning about the visuallyhidden
class.
Sometimes, you don't want to render something to the screen, but have it available for screen readers using a Skip Navigation link. This would ensure that those who use screen readers can skip to the meat of the content immediately rather than listen to a list of navigation links. So, let's add this class to our Skip Navigation link that we have in the header, as shown in the following code:
<a class="visuallyhidden" href="#main">Skip Navigation</a>
This makes the link disappear from our screen, but is it available to screen readers. The web page displayed in the following screenshot does not show the Skip Navigation link:
The CSS rule that makes this happen is as follows:
.visuallyhidden { border: 0; clip: rect(0 000); height: 1px; margin: -1px; overflow: hidden; padding: 0; position: absolute; width: 1px; }
A typical solution used to involve having them positioned absolutely with a height
of 0px
, but this would prevent Apple's VoiceOver screen reader from reading the content.
Another solution involves using the text-indent
property to position the text off-screen, but then care needs to be taken when content is written in Right-To-Left language, where this solution would fail.
Using the clip
property would avoid all of these problems, while having the content readable across all screen readers.
Those who extensively use keyboard navigation would also want to skip navigation. But, because it is visually hidden, they would not know that this option exists. For this case, you want this to be available when this element is in focus. Let us add an additional class called focusable
to make this available for our Skip Navigation link that would make this option visible when they make this link active via keyboard navigation.
<a class="visuallyhidden focusable" href="#main">Skip Navigation</a>
The following screenshot shows how the Skip Navigation link is instantly visible when the user switches keyboard focus to it:
In our website, we want a tabbed display of line up over several days, as shown in the following screenshot:
The following is a simplified view of the markup:
<article class="t-tabs t-section" id="lineup"> <nav class="t-tab__nav"> <a class="t-tab__navitem--active t-tab__navitem" href="#day-1">Day 1</a> <a class="t-tab__navitem" href="#day-2">Day 2</a> </nav> <ul id="day-1" class="t-tab__body t-grid t-before-1-6 t-after-1-6"> <li class="t-grid__cell t-unit-1-2"> <a class="t-media--row" href="#"> <img width="100" height="100" class="t-media__aside t-image--artist" src="/img/artist-kidjo.png"> <b class="t-media__body t-title-tabartist t-artist__name">Angelique Kidjo</b> </a> </li> </ul> <ul id="day-2" class="t-tab__body t-grid t-before-1-6 t-after-1-6"> <li class="t-grid__cell t-unit-1-2"> <a class="t-media--row" href="#"> <img width="100" height="100" class="t-media__aside t-image--artist" src="/img/artist-sangre.png"> <b class="t-media__body t-title-tabartist t-artist__name">Oumou Sangre</b> </a> </li> </ul> </article>
The simplest way to do this would be to show only Day 1 and use the hidden
class to hide the rest of the days, as shown in the following code snippet:
<article class="t-tabs t-section" id="lineup">
<nav class="t-tab__nav">
<a class="t-tab__navitem--active t-tab__navitem" href="#day-1">Day 1</a>
<a class="t-tab__navitem" href="#day-2">Day 2</a>
</nav>
<ul id="day-1" class="t-tab__body t-grid t-before-1-6 t-after-1-6">
<!--list content below -->
</ul>
<ul id="day-2" class="t-tab__body t-grid t-before-1-6 t-after-1-6 hidden">
<!--list content below -->
</ul>
</article>
By hiding the elements, we make the dimensions that they occupy vanish to 0. This means the area previously occupied by that content collapses.
As the user clicks on one or the other navigation links for each day's line up, the content for each day will frequently be hidden and shown, which will look jarring, as shown in the following screenshot:
In such a case, we can use the helper class invisible
to make the element not render, but maintain its dimensions; it will not be visible on the screen or be available to screen readers. As you can see in the following screenshot, the TICKETS section does not change its position depending on which tab is active:
We are positioning the image elements on the left-hand side of the artists' names. We do this by floating the images to the left. Luckily for us, we do not have any content that follows the container with floated elements. If we did, then that content would be overlaid on top of the floated element. You can prevent this from occurring by setting a class called clearfix
on the parent container of the floated elements. In our case, to ensure our floated elements never trigger this behavior, we shall add the clearfix
class to the parent element of the artist image element:
<a class="t-media--row clearfix" href="#">
To learn more about how the clearfix
class works, read about it in Appendix, You Are an Expert, Now What?
Now that we have taken care of the basic essentials, let us apply styles to spruce up the page itself to look more like the design we had in mind. The following code snippet shows how to add styles to our page:
html { background: url('/img/waves-bg.png') repeat-x, url(/img/heading-banner-back.png) 50% 100px no-repeat, url(/img/bg-active.png) 50% 72px repeat-x, url('/img/bg.png') #e7dcbb; box-sizing: border-box; margin: 0 1em; font: 100%/1.5 georgia, serif; } body { max-width: 80%; margin: 0 auto; text-align: center; } .t-tabs { min-height: 400px; position: relative; } .t-tab__body { position: absolute; left: 0; right: 0; } .t-tab__navitem--active { position: relative; } .t-tab__navitem--active::after{ position: absolute; bottom: -2em; left: 0; height: 2em; width: 100%; content: ""; border-radius: 0 0 20em 20em; background: #305da1; box-shadow: 0 -0.3em 0 0 #77aec3 inset, 0 0.3em 0 0 #1A9DC8; } /* TICKETS */ .t-tickets__currency { font-family: georgia, serif; text-align: center; position: absolute; transform-origin: 100% 100%; transform: rotate(-90deg) translate(0, -2.1em); } /* MEDIA OBJECT */ .t-media, .t-media--column, .t-media--row, .t-media__body { text-align: left; list-style: none; } .t-media--row .t-media__aside { float:left; margin-right: 16px; } /* Image replaced social media links */ .t-links__item--twitter, .t-links__item--facebook, .t-links__item--flickr { padding: 0.25rem 1rem; display: inline-block; } .ir.t-links__item--twitter, .ir.t-links__item--facebook, .ir.t-links__item--flickr { background-size: contain; background-repeat: no-repeat; width: 1rem; height: 1rem; background-position: center center; display: inline-block; } .ir.t-links__item--twitter { background-image: url(/img/logo-twitter.svg); } .t-title--h1, .t-title--h2, .t-title--navsite, .t-title-tabartist { font-family: FolkSolidRegular, sans-serif; text-transform: uppercase; color: #E4773A; text-shadow: 3px 3px 1px #C84134, 4px 4px 1px #C84134; letter-spacing: 2px; }
When we went through that, you might have noticed that the styles have no typos whatsoever. The kind copy editors have no doubt done a wonderful job, but I realize you have no such assistants when you write your stylesheets! An errant typo could cause us untold trauma as we hunt why a particular style does not get applied. This is why it is important to also automate validation of your styles and use autocompletion to automate as much of your style declarations as possible.
Sublime Text and Vim both have autocompletion of CSS properties available, and you can automate the insertion of the semicolon at the end too! If you have no access to these tools, you can use the online CSS validator at jigsaw.w3.org/css-validator/
to test your CSS.
There is another way to automate writing valid and productive style rules—by using an alternative style language that compiles into CSS. We shall be looking into some of these languages next.
For a very long time, the only way to write stylesheets was to use the syntax that W3C provided for within the specifications that it produced. However, there are a lot of productivity benefits to be gained by using some programming logic to write stylesheets. But browsers could only understand syntaxes that are mandated by the W3C specifications. This means, any style language that uses additional programmable features should be converted to a browser-understandable typical stylesheet (this is called compilation).
One of the earliest style languages designed for this is called Sass. Now, we have a few more, the most popular ones being Sass, Less, and Stylus. In both Sass and Less, valid CSS is automatically valid Sass and Less code. This makes it trivial to port it from CSS to these languages.
Typically, you would be writing your style rules in files named as main.scss
(if you are using Sass), main.less
(if you are using Less), or main.styl
(if you are using Stylus). Using the compilers that come with each of these languages, these files will respectively be compiled to styles.css
.
Using style languages has many merits, such as the following:
However, using style languages also has some disadvantages, as explained in the following points:
If you are interested in learning more about these languages, read on for some good places to get started.
The official website is sass-lang.com
. Chris Coyier has a good introduction video on Sass at css-tricks.com/video-screencasts/88-intro-to-compass-sass/
.
If you are fairly confident in navigating your way with any of these languages, then you could use any of the available ports that we will look at next, to start your projects:
There is a fairly up-to-date port of HTML5 Boilerplate to Sass requiring Compass
, which is a framework on top of Sass at github.com/sporkd/compass-html5-boilerplate
.