Build a HTML5/CSS3 Website Layout Without Images – Part 2

by in Tutorials on 3rd Jun 2010 · Comments

In the first part of this article - Build a HTML5/CSS3 Website Layout Without Images – Part 1, we have finished explaining all the HTML5 elements used in the code of our demo's index.html page and today we will discuss the CSS properties used to make it pretty.

Build a HTML5/CSS3 Website Layout


Here is a reminder of how the layout will look after we are finished making use of all the CSS3 properties:

Final HTML5 / CSS3 Sample

CSS3 – Beautifying Our Page

With our HTML foundation laid out, it’s time to make the page pretty with some neat CSS3. I will concentrate on the CSS3 properties, keeping the comments about the rest of the CSS to a minimum. But, as always, if there is anything that is unclear, please post a comment and I will talk more about the issue in the comments.

CSS Reset

One thing that helps a great deal in making our pages look consistent in different browsers is Eric Meyer’s CSS Reset. I have slightly modified the reset to exclude the HTML elements that are absent from the HTML5 spec for various reasons.

basefront, big, center, font, s, strike, tt, u, frame, frameset, noframes, acronym, applet, isindex and dir are no longer part of the HTML spec.

I have added the HTML5 elements that we have used to the reset and also set their display properties to block. That will instruct the browsers to treat them as block-level elements.

The following elements are new additions to the CSS reset: header, nav, article, aside, footer, hgroup and section

Of course, for other pages/websites you would also include any other used HTML5 elements in the reset.

@font-face Declarations

In order to make our demo page a little more distinguished, we will use two fonts that are not web safe. The fonts are HighlandGothic and Colaborate and both are freely available as handy @font-face kits on the Font Squirrel website.

The @font-face CSS declarations work by creating a new font family that you can use on the page. After declaring the font family name, actual font files have to be referenced and here is where things get complicated because different browsers support different font formats.

Font Format Table

As you can see from the table above, the shortest way to covering all of your bases is to include a TTF (TrueType Font) or an OTF (OpenType Font) and an EOT (Embedded OpenType) version of the font you wish to embed. You are most likely to find a font you wish to embed in TTF and/or OTF formats, and Font Squirrel comes to the rescue when you have to convert them to EOT (and one or both of the other formats) with their @font-face kit Generator. The generator lets you convert your fonts into all of the required formats depending on your needs, it also provides an option to build Cufón files.

@font-face {
	font-family: 'Colaborate-RegularRegular';
	src: url('fonts/ColabReg-webfont.eot');
	src: local(' '),
	url('fonts/ColabReg-webfont.woff') format('woff'),
	url('fonts/ColabReg-webfont.ttf') format('truetype'),
	url('fonts/ColabReg-webfont.svg#webfont') format('svg');
}

Note that the sources in the second src property are each on separate lines for better readability; I have kept them on a single line in the actual CSS file.

The syntax for the @font-face declaration I have used here is based on Paul Irish’s Bulletproof @font-face syntax. I will not go into much detail here as Paul has explained his reasoning in the article. So, after defining the font family name, we first reference the location of the EOT font file that will be served to Internet Explorer. After that, we repeat the src property and since Internet Explorer doesn’t understand the local definition, the font files referenced in the second src descriptor won’t be loaded by IE. Regarding the order of the different font formats in the second src property, here is what the W3C spec has to say about it:

When a font is needed the user agent iterates over the set of references listed, using the first one it can successfully activate.

So, considering that the browser will use the first format it supports, the order is WOFF → OTF/TTF → SVG. If knowing that WOFF stands for Web Open Font Format isn’t enough to prove to you that it is superior to OTF/TTF and SVG, check out this article. Seriously, though, one advantage is that it is compressed, another is that it can contain metadata detailing the font’s origin and more. The reason SVG fonts are put at the end is the fact they are most likely derivative: converted from an OTF or TTF font file and it is quite possible that there have been some losses during the conversion.

Displaying the text on our page with embedded fonts is quite simple, all we have to do is list the font family name assigned in the @font-face declaration in the font(-family) property of the desired CSS selectors. For example, we have used the HighlandGothic font for the website’s logo and the CSS declaration for that element looks like this:

hgroup h1 {
	font: 40px/54px HighlandGothicLightFLFRegular, "Lucida Sans Unicode", "Lucida Grande", sans-serif;
	color: #970000;
	text-shadow: -1px -1px 0 #650000, 0 0 10px rgba(255,255,255,0.7);
}

Obviously, the HighlandGothic font is listed first, than we list two fallback fonts and finally the generic family name. We also declare the font’s color and, finally, we add a little shadow to the logo which brings us to the next CSS3 property: text-shadow.

The text-shadow Property

Before I move onto this property, just a little disclaimer: the text-shadow property isn’t new to the CSS3, it was first introduced in CSS2 and later removed in CSS2.1.

Well, it can be very useful by letting us forget about Photoshop when we want to add a shadow to some text (and @font-face has already helped us by not having to rely on Photoshop to use non-web safe fonts for our sites).

text-shadow: -1px -1px 0 #650000, 0 0 10px rgba(255,255,255,0.7);

The syntax for the text-shadow property is rather simple: the first two values determine the shadows horizontal and vertical distance, respectively, from the text. The third value sets the amount of blurring applied to the shadow and the last value sets the color of the shadow. We can add more than one shadow to one text element: we just separate each shadow definition with a comma. Another thing worth remembering is that the shadows stack in the order they are defined, the first shadow gets rendered on top.

In our example, the first shadow isn’t blurred and I have moved it one pixel to the left and up so that it produces a faux letterpress effect, which is so underused this days. The second shadow is blurred and it gives the logo a bit of a glow. No doubt you have noticed that the second shadow doesn’t have the color defined with the standard HEX value. This new feature (and a couple of other color features) is the topic of the next section.

Color and Opacity

Before browser vendors started implementing CSS3 features, you could specify color values in CSS in three ways:

  • The HEX value – #ff0000;
  • By specifying the colors RGB (red, green, blue) values – rgb(255, 0, 0) or
  • By using a CSS color name – red.

Of the three choices above I have always used the first because it is the easiest to copy from Photoshop. The RGB values are not very practical because they are not so easy to copy from Photoshop and not easy to remember. I think that the third options was the most impractical and narrowing (remember web safe colors?).

All of the major browsers (except one and there’s a cookie for you if you can guess which one) support the new CSS3 color features and the first one I want to talk about is opacity.

Opacity

Controlling the opacity of the elements on a web page was a long coveted feature for many web designers and finally it is available (well, it’s available if you are not using Internet Explorer). The syntax is ultra-simple:

opacity: X.X;

The opacity value can range from 0 - fully transparent to 1 - fully opaque in .1 increments. That’s pretty straightforward!

Opacity can be quite useful but it does have a drawback which we will discuss while explaining the next CSS3 color feature: RGBA color.

RGBA Color

As you can imagine RGBA is an improvement over RGB and the extra letter stands for alpha. So, specifying the color values with RGBA is basically like specifying the color values in RGB and including the opacity definition within a single property. The syntax is pretty simple:

rgba(255,255,255,0.7);

The first three values in the brackets are the RGB values and the last value represents opacity. So the color, as specified in the example above, is white #ffffff with opacity set to 70%.

I mentioned that using the opacity property to specify transparency has a drawback and I will use our logo to show my point. Imagine that we have specified the text shadow as follows:

text-shadow: -1px -1px 0 #650000, 0 0 10px rgb(255,255,255);
opacity: 0.5;

Text Shadows

I have set the opacity a bit lower to make the differences more noticeable and you can see that by setting the opacity to 0.5, the whole element is now 50% transparent and that is not the effect we were going for. If our logo had had a background image or background color defined those, too, would be 50% transparent. We want only the second text shadow to have transparency but instead the whole element is semi-transparent. So we will make use of the RGBA color:

text-shadow: -1px -1px 0 #650000, 0 0 10px rgba(255,255,255,0.5);

Text Shadows Final

Much better! And, lastly, our final example with the shadow’s opacity set to 70%:

text-shadow: -1px -1px 0 #650000, 0 0 10px rgba(255,255,255,0.7);

Text Shadows Final Background

In my opinion, using the opacity property only makes sense when applied to an image. Otherwise, it is easier and more appropriate to use RGBA or the next feature we will be discussing – HSLA color.

HSL & HSLA Color

The HSL color values are based on the Hue, Saturation, Lightness color model. Here is our text shadow example defined with HSLA colors:

text-shadow: -1px -1px 0 #650000, 0 0 10px hsla(0,0%,100%,0.7);

The code above will produce a shadow effect identical to the one we achieved using RGBA colors. The values in the brackets correspond to hue, saturation, lightness and opacity, respectively. A couple of things to note: saturation and lightness are expressed in percent values and hue is a non-dimensional number (it does not have a unit associated with it, like percent or pixels; in Photoshop, hue is expressed in degrees). Also note that it is necessary to include the percent sign even if the value of saturation or lightness is zero. If you omit the percent sign, the browser will not recognize the syntax and it will not assign a color to the element.

Color of the Element

When working with CSS color values, I prefer the HEX values but I usually use RGBA values when I have to add transparency. However, using HSLA values might make more sense because it is the closest to human perception of color. When using HSL, you can directly control the color’s hue, saturation and lightness. That makes fine-tuning colors and finding just the right one a lot easier by just using CSS because you know what each value changes and you do not have to jump to Photoshop to tune the colors and then copy them to CSS as HEX or RGB values.

The border-radius Property

The next CSS3 feature I want to talk about is a long-desired one (though, to be fair, this feature has been around for a while but was not widely supported) – rounded corners. For a long time web designers had to use images or JavaScript to apply rounded corners to page elements, but now we can do that with only CSS. The browser support for the border-radius property is very good, only IE doesn’t support it (but the IE9 preview does, so that’s likely to change soon).

We will use main navigation element to show how the border-radius property works and later use the nav element again to explain a few other cool CSS3 properties that make it look so slick.

The W3C spec defines the following syntax for border-radius:

border-radius: 20px;

Border Radius

Couldn’t be more straightforward and it looks great in Opera and IE9 – we will see a nice twenty-pixel rounded border on the nav element. However, stopping here would exclude two browsing engines: Gecko (Firefox) and Webkit (Safari, Chrome). In order for the nav element to have rounded corners when viewed in one of those browsers, we will have to add two more properties:

-moz-border-radius: 20px;
-webkit-border-radius: 20px;

The W3C spec recommends that the features in development stages be prefixed with vendor-specific prefixes so that they apply only to the specific browsers. Following that recommendation, Mozilla and Webkit have included the prefixes -moz- and -webkit-, respectively. So each prefix is, in a way, like an HTML conditional comment for Internet Explorer – by including the prefix, we know exactly which browser(s) will be targeted.

Opera has a policy of not implementing features that are not final in the W3C specs but I suppose that they feel that the border-radius property (also text-shadow) is close enough to being finalized so they have included support for it, albeit without a vendor-specific prefix (-o-).

Another advantage using the border-radius property has over using images is the fact that the effect is scalable. Here is a screenshot of the page zoomed in at 300%:

Smooth Borders

Smoooooth! I suppose that you can imagine how jagged those edges would be if zoomed in on an image.

CSS3 Gradients

Another new feature that makes our site pretty is the linear-gradient property. I have used the linear gradient several times throughout the website and it is a bit trickier to use because each browser implements it differently (if at all). I have split this section into subsections dealing with each of the four major browser rendering engines.

Gecko – Mozilla Firefox

We’ll start with Firefox’s implementation:

background-image: -moz-linear-gradient(top, #ca0000, #970000);

Mozilla have used the W3C recommended syntax plus the vendor prefix and the first value within the brackets represents the angle of the gradient-line (along which the gradient is rendered). It can be defined with a background-position value (like in our example) or with an angle in degrees – if we wanted to draw a gradient like the one in the example above, we would use an angle of -90deg. Please note that you can omit the angle value and it will default to top.

The next two values within the brackets are color stops definitions and you can use any color system to define them (HEX, RGB(A), HSL(A)). Also, you are not limited to two color stops. For more info on the -moz-linear-gradient syntax, check out Mozilla’s reference on it.

Webkit – Safari & Google Chrome

Let us see the syntax that will tell Safari and Chrome to render the gradient:

background-image: -webkit-gradient(linear,left top,left bottom,color-stop(0, #ca0000),color-stop(1, #970000));

Webkit obviously uses a different syntax but still includes a vendor-specific prefix. The first value within the brackets defines the type of gradient that we wish to render: linear or radial. The next two items define the start and stop points of the gradient-line; you can use numbers (pixels), percentages or keywords (top, bottom, left, right). Finally we have color stops and, of course, there can be more than two. Color stops have two arguments: the stop value (a percentage or a number ranging from 0 to 1) and a color value (again, all valid CSS color systems are accepted).

Trident – Internet Explorer

Our nemesis, Internet Explorer, doesn’t support CSS gradients but we can use a DirectX filter to render a gradient onto the element’s background:

-ms-filter: "progid:DXImageTransform.Microsoft.gradient(GradientType='0', StartColorStr='#ca0000', EndColorStr='#970000')";

So, we have three parameters here:

  • GradientType – controls the orientation of the gradient: 0 is vertical and 1 is horizontal;
  • StartColorStr – defines the start color of the gradient and you should use the HEX format (I couldn’t make it to work properly with RGB(A) or with HSL(A));
  • EndColorStr – defines the end color of the gradient and, again: use the HEX format.

I have put all of the DirectX filters in a separate CSS file which I have referenced in the head of our index.html file:

<!--[if lt IE 9]><link href=ie.css rel=stylesheet /><![endif]-->

A couple of notes here:

  • It might seem strange that I am putting the IE specific styles into a separate style sheet since there are other browser specific styles in the main style sheet. Well, IE is the only browser that we can target with conditional comments so that we can serve a style sheet only to it. Also, there are a lot of DX filters in use and we want our CSS to validate, don’t we? Another reason for moving it is the reduced file size of the main CSS file. An extra HTTP request is made when the page is accessed with IE but I believe that keeping our main style sheet clean and valid is worth it.
  • I have only tried to make the page look decent (read: look as close to the rendering in modern browsers) in Internet Explorer 8, I haven’t bothered with IE6 & IE7.
  • IE9 is still in development and at the moment seems to support rounded borders, CSS pseudo-elements and that’s pretty much it (of the features used for our demo page). I felt that we shouldn’t spend time on it without knowing which features will be supported in the final version.
Presto – Opera

Opera has no support for CSS gradients and it doesn’t support DirectX filters but there is a workaround – the box-shadow property. I will explain in the next section how the box-shadow property works and then show how it can be used to mimic gradients.

The box-shadow Property

This is another property that has been used extensively on our demo page. The box-shadow property’s syntax is quite similar to the text-shadow property’s syntax. Here is the code for the outer shadow of our main navigation:

box-shadow:  inset 0 0 15px #900, inset 0 35px 35px -18px #ca0000, 0 0 20px #446b6b;
-moz-box-shadow: 	inset 0 0 15px #900, 0 0 20px #446b6b;
-webkit-box-shadow: 0 0 20px #446b6b;

One difference that you have surely noticed is that we have to use the vendor prefixes for Gecko- and Webkit-based browsers, while the default box-shadow property works in Opera. We can also specify multiple shadows and the stacking order is identical to the order for the text-shadow property. We have two new options that are specific to the box-shadow property: that is the inset keyword and the spread radius value.

First, let’s take a look at the inset keyword – its presence specifies that the shadow should be drawn inside of the element rather than outside its edges.

Shadow

I am sure that you can see the inner shadow around the edges (gotta love that zoom). This screenshot is taken in Opera and it would have looked pretty much the same in Firefox. But Google Chrome currently has a bug that prevents it from rendering inset shadows properly.

CSS Shadow

As you can see, the background color bleeds to fill the entire square shape of the element. That is one reason for not including that inset shadow in the -webkit-box-shadow property. The other is the fact that Safari currently doesn’t support inset shadows.

Finally, we come to the other inset shadow in the property that targets Opera; the shadow that will emulate a gradient:

inset 0 35px 35px -18px #ca0000

So, we have the inset keyword; two values that determine the shadow’s position; the spread radius; shadow’s size and the shadow’s color. The spread radius causes the shadow to expand if it is a positive value and it contracts for a negative value. Note that the shadow expands/contracts in the direction that is perpendicular to the shadow’s edge. Now, for inset shadows, a positive spread radius will cause it to contract and vice versa.

The idea here is to have an inset shadow that will be bigger than the element (hence the negative spread radius) and we will push it down so that it covers the bottom half of the nav element giving us the illusion that a gradient is applied. If you compare the two images above (from Opera and Chrome) you will see that the effect is quite similar, even when zoomed in.

This workaround does come with a caveat: using a negative spread radius for an inset shadow will cause Opera to expand the element’s width thus making it wider than it appears. It doesn’t really matter if it is a small object or not on the edges of the layout. I mention the edges because it will make the layout wider than the 960 pixels set by CSS and a horizontal scrollbar will appear if you are on a lower resolution (a resolution that shouldn’t make your browser display horizontal scrollbars for a layout that’s 960px wide, like 1024x768).

Note that the same thing happens in Firefox but we don’t need this type of gradient emulation in Firefox. So, if you know that your visitors have large monitors with high resolutions, don’t worry about it.

CSS3 Animations & Transitions

The cool animations that you can see on the demo page are all done with pure CSS, no JavaScript was involved. In this section, I will go through the page and talk a little about each of the animations.

The Expanding Submenu

Our main navigation has a submenu that slides down when you hover over the Services menu item. Before we dive into the animation specifics, just a few words about the styling of the submenu.

Because I wanted the submenu to expand vertically and not simply appear, I have set the submenu’s height to 0 and its z-index to -1. The submenu link’s height and line-height are also set to 0:

nav#global ul li #subMenu {
	height: 0;
	z-index: -1;
	[…]
}
nav#global ul li #subMenu li a {
	height: 0;
	line-height: 0;
	[…]
}

When the Services menu item is hovered, we apply the following styles:

#services:hover > #subMenu { z-index: 2 }
#services:hover > #subMenu li a { height: 40px; line-height: 40px }

We have used the > (child) selector to tell the browsers that when the Services menu item is hovered, the submenu should move up the z-index and the links in the submenu should regain full (line-)height.

That’s all nice, but what about the animation? Well, the animation is achieved by adding the transition property to the item that triggers the animation. In our case, the trigger is the link inside of the list item with the services id:

#services a {
	transition: all 0.3s linear;
	-o-transition: all 0.3s linear;
	-moz-transition: all 0.3s linear;
	-webkit-transition: all 0.3s linear;
}

The transition property tells the browser that the element’s properties should be animated over the period of 0.3 seconds and that the transition should have a linear timing function. I don’t want to go into more details here because there are a lot of options as you can see in the spec. Feel free to play around with the values until you get an effect that feels best to you.

Just a note about the vendor prefixes: for this property to work, we have to include a prefix even for Opera. The support for this feature is a bit more limited: Internet Explorer doesn’t support it (surprise!) and Firefox won’t support it until the next version comes out (that would be 3.7; you can download a nightly build, though). So, the first (prefix-less) and the third (-moz-) transition properties are there for future-proofing the style sheet.

Sliding Links

The CSS3 transitions are also used to push the links in the Blogroll and the Popular Posts section as well as the link to the @TheBlackAdder Twitter account a little to the right. That is achieved simply by adding a left margin to the hover states of the links.

Continue Reading Buttons

Another element that was animated with the transition property is the Continue Reading button that appears in the footer of the article elements. This time, the left padding of the button was decreased for the :hover state so that the generated :before element can slide closer to the button text.

The Twitter Balloon Quote

The Twitter balloon quote has a different animation. The scale transformation was used to increase its size when you hover over it.

blockquote:hover {
	transform: scale(1.05);
	-o-transform: scale(1.05);
	-moz-transform: scale(1.05);
	-webkit-transform: scale(1.05);
}

The syntax couldn’t be simpler: just specify the amount of scaling and you are good to go. If you want to scale up, use a number larger than 1; if you want to scale down, use a number smaller than 1.

The style of the Twitter balloon quote is based on one of Nicolas Gallagher’s excellent pure CSS speech bubbles.

The Rotated Years

Similar to the scale transformation, the rotate transformation was used for the year segment of the publish dates in the article sections:

.year {
	transform: rotate(270deg);
	-o-transform: rotate(270deg);
	-moz-transform: rotate(270deg);
	-webkit-transform: rotate(270deg);
	[…]
}

Note that the transformations were applied to the default state of the elements with the year class. This way, the rotation is done as soon as the style sheet is loaded.

Last Words

So, that’s the second part of the article. There were a lot of elements to cover and I hope that everything was clear. If not, please post a question in the comments and I will do my best to explain.

Thank you for reading and I look forward to any questions and comments.

Useful links

Marko is a freelance web designer & developer based in Serbia. He is always trying to improve his skills and create a better user experience for his clients. These days he is getting into writing and getting closer & closer to getting his degree in mechanical engineering.