HTML5 adds and amends a handful of tags relating to text. Many of the minor amendments, such as differing attributes in existing tags, have already been covered, but this page looks at two new tags — time
and mark
— as well as the re-definition of presentational tags.
time
is used to make dates and times super-semantically rich.
The text sandwiched in the middle of the opening and closing tag can be any format of date of time – the whole precise lot, or just one part, such as a day. It is made more helpful, however, by the datetime
attribute, the value of which should be a machine-readable date and/or time.
<p>Written by Doctor Who on <strong><time datetime="2052-11-21">Thursday 21st November 2052</time></strong>.</p>
Valid datetime
values can take the format of a year-month-day date (as above), of as a “fuzzy” date, such as “2052-11”, of a time, such as “09:30” (always using a 24-hour clock) or a combination, such as “2052-11-21 09:30”. This can also accommodate time zones and durations.
If the textual content of the time
element is already machine readable, you don’t need the datetime
attribute but it is required if it isn’t.
Text can be highlighted, as if with a marker pen, using mark
:
<blockquote>
<p>He wants to play with his <strong><mark>Legos</mark></strong></p>
</blockquote>
<p>The person being quoted is clearly American because, for some odd reason, they pluralise "Lego".</p>
Yes, this is a form of emphasis, literally speaking, but it won’t always be considered emphasis in the original meaning (for example, the person being quoted above isn’t emphasizing “Legos”, the commenter is), hence its inclusion.
Older versions of Internet Explorer are frequently either inept or naughty. Or both. But they are still popular so we don’t want to ignore them.
Conditional comments, which are nothing more than simple HTML comments that IE (up to version 9) happens to take a peep at, are used to throw a chunk of HTML at these browsers and only these browsers. Other well behaved, top-of-the-class browsers will simply see them as unremarkable comments and move along.
This web site currently uses conditional comments to make a handful of amendments for IE 8 and below, including a small extra stylesheet, and the HTML5 Shiv required for these browsers to take notice of some HTML5 elements. Go ahead – view the source.
They have become a commonly used method of latching extra CSS to a document to plaster over holes in these browsers’ display capabilities. So, for example, you might add something like this inside your head
element:
<link href="everything.css" rel="stylesheet">
<strong><!--[if IE]><link href="stupidie.css" rel="stylesheet"><![endif]--></strong>
Everything between \<!--[if IE]>
and <![endif]-->
will be picked up by Internet Explorer. So this will bolt on a CSS file as normal, and then, only if the browser is Internet Explorer (in practice, this will be Internet Explorer version 9 and below), it will also apply an extra CSS file patch.
You can also target specific versions of Internet Explorer:
<!--[if IE 6>
…<!--[if IE 7>
…<!--[if IE 8>
…<!--[if IE 9>
…You can also target all versions that are greater or less than a certain number:
<!--[if IE gt 6]>
… for IE versions greater than 6<!--[if IE gte 8]>
… for IE versions greater than or equal to than 8<!--[if IE lt 7]>
… for IE versions less than 7<!--[if IE lte 7]>
… for IE versions less than or equal to 7There are actually more options than this which are largely totally unnecessary. Take a look at Microsoft’s own take on it if you really feel compelled to find out more.
Conditional comments really are horrible. Necessary, often, at the moment, but horrible. Like all hacks, it is best to avoid them wherever possible. They’re not really there for whacking completely different stylesheets in different browsers, for example. It’s more for small fallbacks so that you can use the scrumptious likes of CSS 3 without compromise. And don’t assume you have to accommodate every stone-age version of IE, either – try and figure out what is sensible for you to support. Are your web site visitors likely to be using IE6? Probably not.
So you think you know how to make a table. Sure, you know the table
, tr
, td
and th
tags, you’ve even got the rowspan
and colspan
attributes in your pocket. You can make a really cute little plywood coffee table, but don’t you want to know how to make one of those polished solid wood, glass top dining tables that can take the weight of an oversized elephant?
Table rows tend to make table columns look rather stupid. They do all the work, as the table is built row by row, leaving the columns feeling quite rejected.
Luckily for those eager columns though, the colgroup
and col
tags have come to their rescue.
These tags allow you to define the table columns and style them as desired, which is particularly useful if you want certain columns aligned or colored differently, as, without this, you would need to target individual cells.
<table>
<strong><colgroup></strong>
<strong><col></strong>
<strong><col class="alternative"></strong>
<strong><col></strong>
<strong></colgroup></strong>
<tr>
<td>This</td>
<td>That</td>
<td>The other</td>
</tr>
<tr>
<td>Ladybird</td>
<td>Locust</td>
<td>Lunch</td>
</tr>
</table>
In this example the styles of the CSS class “alternative” will be applied to the second column, or the second cell in every row.
You can also use the span
attribute in a similar way to rowspan
and colspan
. Using it with the colgroup
tag will define the number of rows that the column group will belong to, for example <colgroup span="2"></colgroup>
would group the first two columns. Using span
in the col
tag is usually more useful, and could, for example, be applied to the above example like this:
<table>
<colgroup>
<col>
<col <strong>span="2"</strong> class="alternative">
</colgroup>
<!-- and so on -->
This would apply “alternative” to the last two columns.
When span
is used in colgroup
, you shouldn’t then use col
tags.
A brief and easy accessibility consideration is to apply a caption to the table. The caption
element defines the caption and should be used straight after the opening table
tag.
<table>
<strong><caption>Locust mating habits</caption></strong>
<!-- etc. -->
A caption will appear above the table by default, although using the CSS caption-side: bottom
will, well, do what you would expect.
The mightier figcaption
would be preferable to caption
if you are marking up a table as the sole content of a figure
element. See the Sectioning page for more.
thead
, tfoot
and tbody
allow you to separate the table into header, footer and body, which can be handy when dealing with larger tables.
Whereas thead
needs to come first, tfoot
can, in fact come before a tbody
(and you can have more than one tbody
, if it takes your fancy) although browsers will render the tfoot
element at the bottom of the table.
<table>
<strong><thead></strong>
<tr>
<td>Header 1</td>
<td>Header 2</td>
<td>Header 3</td>
</tr>
<strong></thead></strong>
<strong><tfoot></strong>
<tr>
<td>Footer 1</td>
<td>Footer 2</td>
<td>Footer 3</td>
</tr>
<strong></tfoot></strong>
<strong><tbody></strong>
<tr>
<td>Cell 1</td>
<td>Cell 2</td>
<td>Cell 3</td>
</tr>
<!-- etc. -->
<strong></tbody></strong>
</table>
There are a number of ways links — the absolutely fundamentally most important interactive element of web sites — can be made more accessible to those people with disabilities.
Users who do not or cannot use pointing devices can tab through links and, as such, links should be in a logical tabbing order. The tabindex
attribute allows you to define this order although if the HTML is linear, as it should be, a logical tabbing order should automatically fall into place.
<ul>
<li><a href="here.html" <strong>tabindex="1"</strong>>Here</a></li>
<li><a href="there.html" <strong>tabindex="3"</strong>>There</a></li>
<li><a href="limbo.html" <strong>tabindex="2"</strong>>Limbo</a></li>
</ul>
In this example (which is used purely as a demonstration – it would be quite dumb, practically speaking), tabbing would jump from “Here” to “Limbo” to “There”.
The good bit of link-accessibility advice is to write good link text. Have the words the a
tags wrap around explain where the link will take the user. If someone is using a screen reader, having the links read out to them as they tab between them, the user will then know what they’re letting themselves in for if they select a link. “Click here” or random words aren’t especially helpful…
If you have a link that isn’t self-descriptive or the link destination could benefit from being explained in more detail, you can add information to a link using the title
attribute.
<p>I'm really bad at writing link text. <a href="inept.html" <strong>title="Why I'm rubbish at writing link text: An explanation and an apology."</strong>>Click here</a> to find out more.</p>
Another tip: Don’t have links open something in a new window or tab. It’s precious to think your page is important enough to stay alive while a user visits elsewhere anyway. We all know how to use the back button. We know how to close windows and tabs, too, but if you can’t see that that’s what has happened…
If you insist on doing this, at least mention it in a link title.
Access keys allow easier navigation by assigning a keyboard shortcut to a link (which will usually gain focus when the user presses “Alt” or “Ctrl” + the access key).
<a href="somepage.html" <strong>accesskey="s"</strong>>Some page</a>
For users who do not use pointing devices, this can be a quick way to navigate. The trouble is that there the user may not know what they are unless they are explicitly stated although some assistive software will tell the user what these are.
To aid tabbing, you can supply links that allow users to jump over chunks of your web page. You might want to allow someone to jump over a plethora of navigation links, for example, so they can just read a page’s main content rather than cycle through all of the links:
<header>
<h1>The Heading</h1>
<a href="#content">Skip to content</a>
</header>
<nav>
<!--loads of navigation stuff -->
</nav>
<section id="content">
<!--lovely content -->
</section>
You probably won’t want this link to be displayed visually – it’s a peculiar link to see for abled-bodied users and screen reader users won’t need to see it (it will be read out). So you can use CSS to render it invisible but it could also be beneficial to those with motor disabilities so you might also want to consider making it visible when it has focus from being tabbed to using the :focus
CSS pseudo class.
Forms aren’t the easiest of things to use for people with disabilities. Navigating around a page with written content is one thing, hopping between form fields and inputting information is another. Because of this, it is a good idea to add a number of elements to the form.
Each form field should have its own explicit label. The label
tag sorts this out, with a for
attribute that associates it to a form
element:
<form>
<strong><label for="yourName">Your Name</label></strong>
<input name="yourName" id="yourName">
<!-- etc. -->
Labels have the added bonus of visual browsers rendering the labels themselves clickable, putting the focus on the associated form field.
Both name
and id
attributs are typically required; the name
for the form to handle that field and the id
for the label
to associate it to.
You can group fields, for example name (first, last, middle, title etc.) or address (line 1, line 2, county, country, postal code, country etc.) using the fieldset
tag.
Within the field set, you can set a caption with the legend
tag.
<form action="somescript.php" >
<strong><fieldset></strong>
<strong><legend>Name</legend></strong>
<p>First name <input name="firstName"></p>
<p>Last name <input name="lastName"></p>
<strong></fieldset></strong>
<strong><fieldset></strong>
<strong><legend>Address</legend></strong>
<p>Address <textarea name="address"></textarea></p>
<p>Postal code <input name="postcode"></p>
<strong></fieldset></strong>
<!-- etc. -->
Most browsers tend to represent field sets with a border surrounding them and the legend caption breaking the left of the top border by default. You can, of course, change this with CSS if you wish.
The optgroup
element groups options in a select box. It requires a label
attribute, the value of which is displayed as a non-selectable pseudo-heading preceding that group in the drop-down list of visual browsers.
<select name="country">
<strong><optgroup label="Africa"></strong>
<option value="gam">Gambia</option>
<option value="mad">Madagascar</option>
<option value="nam">Namibia</option>
<strong></optgroup></strong>
<strong><optgroup label="Europe"></strong>
<option value="fra">France</option>
<option value="rus">Russia</option>
<option value="uk">UK</option>
<strong></optgroup></strong>
<strong><optgroup label="North America"></strong>
<option value="can">Canada</option>
<option value="mex">Mexico</option>
<option value="usa">USA</option>
<strong></optgroup></strong>
</select>
Like links, form fields (and field sets) need to be navigated to without the use of a pointing device, such as a mouse. The same methods used in links to make this task easier can be used on form elements — tab stops and access keys.
The accesskey
and tabindex
attributes can be added to the individual form tags such as input
and also to legend
tags.
<input name="firstName" accesskey="f" tabindex="1">
HTML5 greatly advances form controls, with numerous additional input types
, several new attributes
, and a handful of extra elements
.
Getting this warning in early, in case you quite understandably decide that it would be a waste of time reading the rest of this page, a vast majority of this new gubbins will not yet work fully on all major browsers. Unsurprisingly, Internet Explorer is the main dunce, with next to none of this working in anything lower than IE 10 and even that version fails to support some input
types. All is not fruitless, though — see the note about usage suggestions at the end of HTML5 Forms Pt. 2.
Basic form fields created using the input
element include text, password, checkbox, radio, and submit, which have already been covered in the HTML Beginner section. These types have been extended in HTML5 to accommodate more specific fields:
Used for a search query text box, this performs exactly as a standard text input should.
<input type="search" name="search">
The main intention of the inclusion of this input type in the HTML5 specification is one of style. As well as making your HTML clearer, you can also target this element with a CSS attribute selector:
input[type=search] { background: url(magnifyingglass.png) right no-repeat) }
Other “special” text input types include tel
, for telephone numbers, url
, for web addresses, and email
, for email addresses.
<input type="tel" name="telephone_number">
<input type="url" name="web_address">
<input type="email" name="email_address">
You can use the :valid
and :invalid
CSS3 pseudo classes to style these fields depending on whether their content is considered valid.
input[type=email]:valid { background: green }
input[type=email]:invalid { background: red }
This example will paint an email field’s background green if the entered text is recognized as an email address (such as “[email protected]”) or red if it isn’t (if the user were to type “sausages?”, for example).
A simple text box that also allows a user to directly type in a number, or cycle through numbers (usually using an up and down arrow to the side of the field), can be achieved with type="number"
. A further step
attribute can be added to specify how much is added or subtracted from the number with each increment.
If you also want the number to have a minimum or maximum value, you can further use the min
and max
attributes.
<input type="number" name="quantity" step="2" min="20" max="30">
Once again, if this is supported, the user will be able either to type directly into the field or, if using the arrows, cycle between 20 and 30, two units at a time.
You can use the :valid
and :invalid
pseudo classes in relation to this, too. If the user were to type “12”, for example, that would be invalid, because it isn’t between 20 and 30. If they typed “23” that would also be invalid because it isn’t a multiple of 2.
An alternative to the digits-in-a-text-box approach can be achieved using type="range"
. By default, this should be displayed as a horizontal bar with a slider in the middle of it. The user can then adjust the slider left and right, the far left resulting in a value of “0” and the far right a value of “100”. This range can be adjusted using the min
and max
attributes.
<input type="range" name="temperature" min="15" max="25" step="0.5" value="18.5">
There are several input types for dates and times:
type="datetime"
type="date"
type="month"
type="week"
type="time"
type="datetime-local"
If supported (they aren’t, widely, and they are also inconsistent between browsers), these will prompt the user to enter a date or time in a specific format, either by directly typing it in, cycling through one week/day/hour/minute/etc. at a time, or by selecting from a dropdown calendar.
step
, min
, and max
attributes can be used with dates and times, too, as can the CSS pseudo classes to style according to validity.
Finally, type="color"
is designed to allow a user to select a color, sending a six-digit hex code as its value.
<input name="color" type="color" value="#ff8800">
Continuing from HTML5 Forms Pt. 1, in addition to the multitude of fresh new input types, there are also additional form-specific attributes at your disposal as well as data lists, a sort of text/select hybrid.
As well as those attributes mentioned, both here and in earlier guides, there is a handful of additional attributes:
The placeholder
attribute can be used with text input
fields (and their text-like cousins, such as type="email"
and type="number"
) as well as textarea
elements. It is intended as a hint, rather than a label, for which a label
element should still be used.
<label for="email_address">Email address</label>
<input type="email" <em>placeholder="[email protected]"</em> name="email_address" id="email_address">
You might want focus to land on a form field when a page loads. If you think of a search engine, for example, when you land on its home page you don’t normally need to click on the search box to start typing – you can do so straight away because it already has focus. The autofocus
attribute is a quick way to achieve this effect.
<input name="query" autofocus>
A data list takes the form of a list of suggestions that accompanies a text field:
<input name="country" list="country_name">
<datalist id="country_name">
<option value="Afghanistan">
<option value="Albania">
<option value="Algeria">
<option value="Andorra">
<option value="Armenia">
<option value="Australia">
<option value="Austria">
<option value="Azerbaijan">
<!-- etc. -->
</datalist>
The value of the list
attribute in the input
element (which could be any of the text-like input types) binds it to a datalist
element with the corresponding ID (“country_name”, in this example). As a user types in the text field, if what they type matches the start of anything in the data list, those matches will be shown underneath the text field as suggestions. So, here, if “A” is typed, the 8 countries beginning with “a” are displayed. If “L” is typed after “A”, the list of suggestions will reduce to just “Albania” and “Algeria”, and so on. The data sent when the form is submitted will be whatever is in the text field – it could be something selected from the list or it could be something completely different, inputted by the user.
The good news is that many of the features outlined in these two HTML 5 Forms pages degrade gracefully. Those browsers that don’t support data lists still maintain the text box; unrecognised input
types revert to text inputs, so you can use the likes of search
, tel
, and url
as long as you aren’t relying on their special features; placeholder text simply won’t appear so as long as it isn’t essential, go for it.
HTML5 introduces a swathe of new tags to accommodate the increasingly interactive and multimedia nature of the Web. While there have been numerous ways to embed video, audio, and dynamic imagery in the past, the new web standard attempts to make this easier, more consistent, and more reliable.
The simplest embedded (foreign) content is an image, applied to a web page with the img
element. In the olden days, object
, along with various plugins and proprietary devil dust, was used to bash and smash video and audio into submission. Although not without its (compatibility) problems, there is now a much better method for using various types of media in web pages.
<video src="kitties.mp4" controls></video>
Bam. There you go. Just like that. Simple.
This will embed a video, complete with controls, in browsers that support the HTML5 video
tag and the video content type.
While HTML5 is pushing for a standard framework to play media, the media itself is not standardised across browsers. In practice, this means that it is unlikely all visitors will be able to experience your video (or audio) file. Some support WebM video, for example, while others support MPEG. Don’t lose too much sleep over this, though — see “Alternative content”, below.
The controls
attribute is optional but if you don’t want it – if you really want to take control away from the user – you can just slap in an autoplay
attribute:
<video src="kitties.mp4" autoplay></video>
This will play the video on page load, won’t display any controls, and will most likely annoy the hell out of your visitors. Of course you could, if you were kind, put in both the controls
and autoplay
attributes.
Other basic attributes at your disposal include width
, height
, loop
, and muted
.
<video src="kitties.mp4" width="300" height="200" loop muted autoplay controls></video>
If you insist on using autoplay
, bringing muted
(and controls
) to the party as well is a nice gesture and is a convention that many sites employ. If you have a video in an aside
, for example, it can begin playing but the user can then opt to follow it by de-muting the video via the controls, if they choose, decreasing the likelihood of irritation.
You can specify a placeholder image, which will be displayed before the video is played, with the poster
attribute.
<video src="kitties.mp4" poster="fluffy.jpg" controls></video>
The specified image will stretch or shrink to fit the dimensions of the video, regardless of the original size of the image.
So, yes, there is an opening and closing tag. Whatever could go in between them? Why, fall-back content: content that is displayed if the browser doesn’t understand the video
element. That could be a few words, a chunk of HTML, or a “really funny” and “highly original” Lolcats image.
<video src="kitties.mp4" controls>
<img src="hahahaha.jpg" alt="Hilarious cat and caption saying 'soz'.">
</video>
As already noted, it’s not only compatibility with the tag we need to worry about, but also compatibility with the source video itself. Luckily, more than one video source file can be offered up with the source
element along with indications of the requirements of the file in the value of the type
attribute. The browser will then take the first one it’s happy with.
<video controls>
<source src="kitties.mp4" type="video/mp4; codecs='avc1, mp4a'">
<source src="kitties.webm" type="video/webm; codecs='vp8.0, vorbis'">
<p>Browser no likey HTML 5.</p>
</video>
Here, a browser should figure out if it can handle the “video/mp4” MIME type and if it has the stated codec to decipher it. If it doesn’t, it should move on to the next and try again with the details set out in the second source
element.
Applying audio is just like applying video. Using the audio
tag, the structure is the same as using video
and the attributes src
, controls
, autoplay
and loop
can all be used in the same way.
<audio src="meow_mix.mp3" controls>
Your stupid browser doesn't support HTML 5 audio.
</audio>
Alternative content can also be defined in exactly the same way as with the video
and source
tags.
Much greater control can be exercised over video and audio using JavaScript, with the ability to manipulate aspects of playback and user controls in more detail.
A major addition to HTML5 is the canvas
element. It is designed to provide a canvas onto which JavaScript can be used to paint all manner of dynamic images such as graphs, animated sprites, or daft cat pictures.
<canvas id="wittykitty" width="800" height="450">
<!-- Fall-back content here, just like with video and audio -->
</canvas>
Rounded corners used to be the stuff of constricting solid background images or, for flexible boxes, numerous background images, one per-corner, slapped on multiple nested div
elements. Argh, ugly. Well, not any longer. Now, with simple CSS, you can lavish your designs with more curves than Marilyn Monroe.
Yeah. Border radius. Fear not, though — you don’t have to have borders. The border-radius
property can be used to add a corner to each corner of a box.
#marilyn {
background: #fff;
width: 100px;
height: 100px;
<strong>border-radius: 20px;</strong>
}
And there you have it. Rounded corners, see? Well, you will if you’ve got a sensible browser (see note below).
Of course, if you do want a border…
#ok_a_border_then {
border: 5px solid #8b2;
width: 100px;
height: 100px;
<strong>border-radius: 5px;</strong>
}
Woop.
border-top-left-radius
, border-top-right-radius
, border-bottom-right-radius
, and border-bottom-left-radius
can also be used to target specific corners.
Ever so slightly less horribly wordy, you can also define all corner radii (what a great word) individually with a space-separated list of values, working clockwise from top-left, just like other shorthand properties:
#monroe {
background: #fff;
width: 100px;
height: 100px;
<strong>border-radius: 6px 12px 18px 24px;</strong>
}
By using two values instead of four you target top-left and bottom-right with the first length (or percentage) and top-right + bottom-left with the second. Three values? Top-left, then top-right + bottom-left, then bottom-right.
Are circles a bit too square for you? You can specify different horizontal and vertical radiiii by splitting values with a “/”.
#nanoo {
background: #fff;
width: 100px;
height: 150px;
<strong>border-radius: 50px/100px;</strong>
border-bottom-left-radius: 50px;
border-bottom-right-radius: 50px;
}
You can make parts of your page “pop” by applying shadows to boxes and text.
box-shadow
is the standard CSS property to get you going and it can have a value comprising several parts:
box-shadow: 5px 5px 3px 1px #999
You can also apply shadows to the inside of a box by adding “inset” to the list:
box-shadow: inset 0 0 7px 5px #ddd;
box-shadow
, as its name implies, only has eyes for boxes. Fickle beast. But you can also apply shadows to the outline of text with text-shadow
:
text-shadow: -2px 2px 2px #999;
Similarly to box-shadow:
Note that there is no spread distance or inset option for text-shadow.
text-shadow
has taken a little bit longer for browsers to figure out. Internet Explorer 9 and below won’t understand it so we suggest only using it in non-critical situations.
In earlier tutorials, we have covered HTML selectors, Class and ID selectors, and how to combine selectors to target specific element boxes. Using three itty-bitty characters, you can further pinpoint an element, reducing the need to bloat your HTML with class and ID attributes.
Using an asterisk (“ * ”), you can target everything. You can use it by itself to set global styles for a page, or as a descendant of a selector to set styles of everything within something.
The following, for example, will set the margin and padding on everything in a page to zero and everything within an element with the ID “contact” to be displayed as a block:
<strong>*</strong> {
margin: 0;
padding: 0;
}
<strong>#contact *</strong> {
display: block;
}
Using a standalone universal selector is commonly used to “reset” many of a browser’s default styles. Setting a margin to zero, for example, will kill all spacing around paragraphs, headings and blockquotes.
A greater-than symbol (“>”) can be used to specify something that is a child of something else, that is, something immediately nested within something.
So, with this HTML…
<ul id="genus_examples">
<li>Cats
<ul>
<li>Panthera</li>
<li>Felis</li>
<li>Neofelis</li>
</ul>
</li>
<li>Apes
<ul>
<li>Pongo</li>
<li>Pan</li>
<li>Homo</li>
</ul>
</li>
</ul>
…and the following CSS…
<strong>#genus_examples > li</strong> { border: 1px solid red }
…a red border would be drawn around “Cats” and “Apes” only, rather than around every single list item (which would be the case with #genus_examples li { border: 1px solid red }
). This is because the likes of “Panthera” and “Felis” are grandchildren of “genus_examples”, not children.
A plus sign (“+”) is used to target an adjacent sibling of an element, essentially, something immediately following something.
With the following HTML:
<h1>Clouded leopards</h1>
<p>Clouded leopards are cats that belong to the genus Neofelis.</p>
<p>There are two extant species: Neofelis nebulosa and Neofelis diardi.</p>
…and CSS…
<strong>h1 + p</strong> { font-weight: bold }
Only the first paragraph, that follows the heading, will be bolded.
A further, CSS 3, “general sibling” selector uses a tilde (“~”) and will match an element following another regardless of its immediacy. So, in the above example, h1 ~ p { font-weight: bold }
will style all paragraphs after the top-level heading but if there were any p
s preceding the h1
, these would not be affected.
We already know that colors can be defined by name, RGB, or hex values, but CSS 3 also allows you to paint away with HSL — hue, saturation, and lightness — as well as stipulating transparency.
There are no super special properties at play here — HSL and RGBa (the “a” standing for “alpha”, as in “alpha transparency”) can be applied to any property that has a color value, such as color
, background-color
, border-color
or box-shadow
, to name a mere handful.
RGBa opens up an exciting new dimension to web design, allowing you to set the transparency of a box or text. If you wanted a smidgen of a snazzy background image to peep through a heading, for example, you might use something like this:
h1 {
padding: 50px;
background-image: url(snazzy.jpg);
<strong>color: rgba(0,0,0,0.8);</strong>
}
A standard value of rgb(0,0,0)
would set the heading to pure black but that fourth value, in rgba
, sets the level of transparency, “1” being completely opaque, “0” being completely transparent. So rgba(0,0,0,0.8)
is saying red=“0”, green=“0”, blue=“0”, alpha=“0.8”, which, all together, makes it 80% black.
This doesn’t only apply to text, of course, you could apply a transparent background color to an entire box, a transparent box shadow… anywhere where you can use rgb
, you can used rgba
.
Color names aside, web colors have always been red-green-blue biased, be that through hex codes or explicit RBG (or RGBa). Although mildly less straightforward (especially if your brain is trained to break down colors into red, green and blue), HSL can actually be more intuitive because it gives you direct control over the aspects of a color’s shade rather than its logical ingredients.
It is used in a similar way to rgb
:
#smut { color: <strong>hsl(36, 100%, 50%)</strong> }
Rather than each sub-value being a part of the color spectrum, however, they are:
So the example used here will produce an orange (36°) that is rich (100% saturation) and vibrant (50% lightness). It is the equivalent of #ff9900
, #f90
, and rgb(255, 153, 0)
.
Hey, man, this funky fresh transparency and HSL can be combined?! You’d better believe it. Here’s HSLa:
#rabbit { background: <strong>hsla(0, 75%, 75%, 0.5)</strong> }
You can figure out what that does, right?
hsl
and hsla
are supported by most modern browsers, including IE versions 9 and above.
At-rules encapsulate a bunch of CSS rules and apply them to something specific. They can be used to import other CSS files, apply CSS to a particular media, or embeduncommon fonts.
Each at-rule starts with an apetail, or an “at sign”, if you want to be boring about it (“@”).
Let’s start with the simple @import
rule. This is used to bolt another stylesheet onto your existing one.
@import url(morestyles.css);
This can be used if a site requires long, complex stylesheets that might be easier to manage if they are broken down into smaller files.
@import rules must be placed at the top of a stylesheet, before any other rules.
Advertise Here!On a long-established, well-read, well-respected web development resource.
@media
can be used to apply styles to a specific media, such as print.
<strong>@media print</strong> {
body {
font-size: 10pt;
font-family: times, serif;
}
#navigation {
display: none;
}
}
Values that follow “@media
” can include screen
, print
, projection
, handheld
, and all
, or a comma-separated list of more than one, such as:
<strong>@media screen, projection</strong> {
/* ... */
}
It doesn’t stop there, oh no. CSS 3 allows you to target not only specific media but also variables relating to that media, such as screen size (particularly helpful in targeting phones). Have a gander at the Media Queries page for more.
@font-face
has been around for a long time but was nigh-on useless for much of its life. CSS 3 has polished it up and it is now widely used as a technique for embedding fonts in a web page so that a typeface can be used even if it isn’t sitting on the user’s computer. So you no longer need to rely on “web safe” fonts such as Arial or Verdana. Exciting times.
Jumping in at the deep end…
@font-face {
font-family: "font of all knowledge";
src: url(fontofallknowledge.woff);
}
What this does is create a font named “font of all knowledge” using the font-family
descriptor and links the font file “fontofallknowledge.woff” to that name using the src
descriptor. “font of all knowledge” can then be used in a standard font rule, such as:
p { font-family: "font of all knowledge", arial, sans-serif; }
The font will be downloaded (in this case from the same directory as the CSS file) and applied to paragraphs. If the browser is too decrepit to deal with sparkly new font-faces, it will simply revert to the next, standard, font in the list. Magic!
You can also look for a number of fonts to apply to the rule with a comma-separated list. Checking to see if a font is already present on a user’s computer, removing the need to download it, can also be accomplished by replacing “url” in the src
value with “local”.
And because a font file might contain a whole host of weights or styles, you might also want to specify which one you’re interested in. So the @font-face
rule could end up looking something like this:
@font-face {
font-family: "font of all knowledge";
src: local("font of all knowledge"), local(fontofallknowledge), url(fontofallknowledge.woff);
font-weight: 400;
font-style: normal;
}
Legally speaking, you can’t just throw any old font you feel like up on the Interweb because there are copyright and usage terms to consider, not to mention compatibility and optimization issues.
There are free web fonts out there that you can find, download, upload, and use, though. Hell, you could even create one yourself if you’re mad-scientist clever. There are also web font providers, such as Adobe’s Typekit, that have a large selection of fonts to choose from at a price.
Google Web Fonts has a more limited selection but it’s free to use and makes things super, super (super, super, super) easy. All you need to do is link to one of their external CSS files, which is nothing more than a @font-face
rule, and whammo — you’ve got a darling new font to play with.
What? More selectors? Damn straight. Because someone somewhere really wants you to keep your HTML as tidy as possible. So before you add a class attribute to a tag see if you can simply target it by an attribute that might already be there.
Attribute selectors allow you to style an element’s box based on the presence of an HTML attribute or of an attribute’s value.
Appending an attribute name enclosed in square brackets, to style something that simply contains a certain attribute, you can do something like this:
<strong>abbr[title]</strong> { border-bottom: 1px dotted #ccc }
This basically says “shove a dotted line underneath all abbreviations with a title
attribute”.
You can further specify that you want to style something with a specific attribute value.
<strong>input[type=text]</strong> { width: 200px; }
This example will apply a width of 200 pixels only to input
elements that are specified as being text boxes (<input type="text">
).
This approach can certainly be useful in forms where input
elements can take on many guises using the type
attribute.
You can also target more than one attribute at a time in a way similar to the following:
<strong>input[type=text][disabled]</strong> { border: 1px solid #ccc }
This will only apply a gray border to text inputs that are disabled.
CSS 3 further allows you to match an attribute without being exact:
[attribute^=something]
will match a the value of an attribute that begins with something.[attribute$=something]
will match a the value of an attribute that ends with something.[attribute*=something]
will match a the value of an attribute that contains something, be it in the beginning, middle, or end.So, as an example, you could style external links (eg. “http://www.htmldog.com”) differently to internal links (eg. “overhere.html”) in the following way:
a[href^=http] {
padding-right: 10px;
background: url(arrow.png) right no-repeat;
}
Transitions allow you to easily animate parts of your design without the need for the likes of JavaScript. How dangerous.
At the most simplistic level, think of a traditional :hover
state, where you might change the appearance of a link when a cursor fondles it:
a:link {
color: hsl(36,50%,50%);
}
a:hover {
color: hsl(36,100%,50%);
}
This creates a binary animation; a link switches from a subdued orange to a rich orange when it is hovered over.
The transition
property, however, is much more powerful, allowing smooth animation (rather than a jump from one state to another). It is a shorthand property that combines the following properties (which can be used individually if you so choose):
transition-property
: which property (or properties) will transition.transition-duration
: how long the transition takes.transition-timing-function
: if the transition takes place at a constant speed or if it accelerates and decelerates.transition-delay
: how long to wait until the transition takes place.New Examples Section!See all of this code stuff in action, and play around with it.
Returning to the shorthand property, if a transition is applied like so…
a:link {
<strong>transition: all .5s linear 0;</strong>
color: hsl(36,50%,50%);
}
a:hover {
color: hsl(36,100%,50%);
}
…when the link is hovered over, the color will gradually change rather than suddenly switch. The transition
property here is saying it wants all properties transitioned over half a second in a linear fashion with no delay.
For a transition to take place, only transition-duration
is required, the rest defaulting to transition-property: all; transition-timing-function: ease; transition-delay: 0;
. So you could, for example, simply declare transition: .5s
.
While “all” can be used in transition-property (or transition), you can tell a browser only to transition certain properties, by simply plonking in the property name you want to change. So the previous example could actually include transition: color .5s ease 0
, given only the color changes.
If you want to target more than one property (without using “all”), you can offer up a comma-separated list with transition-property
:
a:link {
transition: .5s;
<strong>transition-property: color, font-size;</strong>
...
Or you can offer up a slew of rules for transitioning each property like so:
a:link {
<strong>transition: color .5s, font-size 2s;</strong>
...
OK, so transition-timing-function
(catchy!) is the least obvious fella. It effectively states how the browser should deal with the intermediate states of the transition.
It follows a cubic Bézier curve. Yeah. Obviously, we know all about them from infant school, but, to get down to it, at the most basic level you can use ease
or linear
.
ease
produces a gradual acceleration at the start of the transition and a gradual deceleration at the end. linear
maintains a constant speed throughout. Other values include ease-in
and ease-out
.
CSS transitions won’t work in Internet Explorer versions 9 and below. Booo. But that won’t matter in cases (which will be most cases) where transitions aren’t essential for a design to work well. It’s just a little something to keep in mind.
As well as plastering a single or tiling background image across parts of your page, you can also apply multiple backgrounds, adjust the size of background images, and define the origin of a background based on levels of the box model.
This is the boogie web designers have been crying out for since Bing Crosbie was topping the charts.
CSS3 allows you to apply multiple background images to a single box by simply putting image locations in a comma-separated list:
background-image: url(this.jpg), url(that.gif), url(theother.png);
More usefully, you can also define all of the other delightful background aspects. If you wanted to style a chunky button-like link with separate background, bullet, and arrow, for example, you could use something like:
background: url(bg.png), url(bullet.png) 0 50% no-repeat, url(arrow.png) right no-repeat;
Easy, right? It’s just the same as using background-image
, background-position
, background-repeat
, background-attachment
, and background
, except you can specify more than one background with the aid of that helpful little comma.
Advertise Here!On a long-established, well-read, well-respected web development resource.
The background-size
property allows you to stretch or compress a background image.
The values can be:
auto
, which maintains the background image’s original size and width/height ratio.100px 50px
(100px wide, 50px high). Specifying a single length, such as 100px
will result the equivalent of 100px auto
.50% 25%
(50% of the width of the background area, 25% of the height of the background area). Specifying a single percentage, such as 50%
will result the equivalent of 50% auto
.auto
, such as 80px auto
(80px wide, automatic height to maintain the image’s original ratio)contain
, which maintains the background image’s original ratio and makes it as large as possible whilst fitting entirely within the box’s background area.cover
, which maintains the background image’s original ratio and makes it large enough to fill the entire background area, which may result in cropping of either the height or width.background-origin
is the remarkably dull kid of the bunch. Not unintelligent, just dull. The kid that the other kids point and laugh at. The property defines where the background area of a box actually starts. If you think of the box model, when you set a background it should, by default, start from the upper-left corner of the padding box. So if you had…
#burrito {
width: 400px;
height: 200px;
border: 10px solid rgba(0,255,0,.5);
padding: 20px;
background: url(chilli.png) 0 0 no-repeat;
}
…the background image should appear in the top left corner, in the padding box, immediately after the inner edges of a green border. You can change this behavior, however, with background-origin
. Its self-descriptive values can be padding-box
(default, as described above), border-box
, and content-box
.
So adding background-origin: border-box
to the previous example will cause the origin of the background image to be tucked up inside the border.
A woeful mega-budget Michael Bay movie about CSS?! Nay, the powerful manipulation of the shape, size, and position of a box and its contents using the transform
property.
By default, CSS boxes, those visual representations of HTML elements, are so square. Rectangular, at least; level, with four straight sides and four boring right angles. But with the use of transform
you can stretch and mold those boxes into all manner of shapes.
This page will only mention the transform
and transform-origin
properties but, in practice, you will probably want to duplicate these with -webkit-transform
and -webkit-transform-origin
to achieve the same results in the likes of Safari and Chrome as well as -ms-transform
and -ms-transform-origin
for Internet Explorer 9, which is the earliest version of IE that will support transforms.
Manipulating a box over two dimensions, transform can be used to rotate, skew, scale and translate a box and its contents.
The following would result in a square orange box with all of its contents — text, images, whatever — obediently standing to attention:
.note {
width: 300px;
height: 300px;
background: hsl(36,100%,50%);
}
But you can spin those soldiers around by adding a further declaration:
transform: rotate(-10deg);
This will turn the box and, importantly, everything in it, ten degrees anti-clockwise.
Skewing allows you to tip the horizontal and vertical so the following…
transform: skew(20deg,10deg);
…will tip over the x-axis by 20 degrees on the y-axis by 10 degrees.
You can also specify one angle, such as skew(20deg)
, which is the equivalent of skew(20deg,0)
.
Obviously, you can change width
and height
properties on a box, but that won’t affect the size of anything inside it. Scaling, however, will multiply not only the width and height, but the size of everything contained in the box as well:
transform: scale(2);
This will multiply the size by two. You can use any positive number, including a value less than “1”, such as “0.5”, if you want to use a shrink ray.
You can also scale the horizontal and vertical dimensions separately:
transform: scale(1,2);
This will leave the horizontal as is (because it’s a scale of 1) and multiply the vertical by two.
You can shift a box horizontally and vertically using transform: translate
:
transform: translate(100px,200px);
Similar to position: relative; left: 100px; top: 200px;
, this will move a box 100 pixels to the right and 200 pixels down.
As well as the values mentioned, if you want to target an individual axis, you can also use skewX
, skewY
, scaleX
, scaleY
, translateX
, and translateY
.
Want to rotate and scale at the same time? You crazy kid. You can do this by simply separating values with spaces, such as:
transform: rotate(-10deg) scale(2);
The order of the values is important – the latter will be executed before the former. In the previous example, the box will be scaled and then rotated. It is, therefore, different to transform: scale(2) rotate(-10deg);
, which will be rotated and then scaled.
Alternatively, you could use the matrix function. matrix
does the whole lot – rotating, skewing, scaling, and translating. It takes six values:
transform: matrix(2,-0.35,0.35,2,0,0);
These values aren’t entirely straightforward and involve maths (or just one math if you’re of the American persuasion) that, if you really want to tackle (there are benefits not only in brevity but also in precision), it may be worth giving the specs a gander.
There’s one important aspect missing. If you are transforming a box, there is a further parameter involved: the origin of the transformation. If you are rotating, for example, it will, by default, turn on the point that is the center of the box; if you had a piece of card, stuck a pin right through the middle of it, and then stuck that to your forehead (don’t do this), the card would spin from the middle. You can change where in the card the pin is stuck with transform-origin
, however:
transform-origin: 0 0;
This example will tell the box to transform (rotate, in the previous example) from the top left, the first “0” being horizontal, the second being vertical. These values could be different, of course — like all other x-y, and you can use the usual center
, top
, right
, bottom
, left
, length and percentage values, including negatives.
And all of that’s just with two measly dimensions. transform
is a leviathan with even greater power that can also be used for three-dimensional magic. On the most basic level, you can use rotateX
and rotateY
, which will rotate “towards” or “away” from you on the x- and y-axis, and there are the likes of translate3d
, scale3d
, and the intimidating matrix3d
, all of which have even greater browser difficulties than their 2D counterparts.
Images showing a smooth dissolve from one color to another are plastered all over the web. However, CSS 3 allows you to place them in your designs without having to create an actual image file.
There is no special property for this; you simply use the <strong>background</strong>
or <strong>background-</strong>image
property and define your gradient in its value. You can create both linear and radial gradients this way.
For an even spread of two colors, fading from one at the top to another at the bottom, a declaration can simply be something like:
background: linear-gradient(yellow, red);
To manipulate the angle of the fading, you slot in “to” and the destination you want the transition to head to. You can head to one side:
background: linear-gradient(to right, orange, red);
Or one corner:
background: linear-gradient(to bottom right, orange, red);
Or any angle that tickles your fancy:
background: linear-gradient(20deg, orange, red);
Note that the “to” is excluded with angles because there isn’t an explicit destination.
And why stop at two colors? Specify as many as you dare:
background: linear-gradient(hsl(0,100%,50%),hsl(60,100%,50%),hsl(120,100%,50%),hsl(180,100%,50%),hsl(240,100%,50%),hsl(300,100%,50%));
To get gradients to work on as many browsers as possible, you will probably also want to use -webkit-linear-gradient
to cover Safari and older versions of Chrome. The values of these must also exclude the “to” part, if used.
CSS gradients won’t play at all with IE 9 and below, but you can still make them, and any other incapable browser, use the traditional method of a good old fashioned image by specifying that first, as a fallback (proceeding declarations will just be ignored).
So, all-in, your gradients might look something like this:
body {
background: #666 url(fade.png) 0 0 repeat-y;
background: -webkit-linear-gradient(right, #000, #666);
background: linear-gradient(to right, #000, #666);
}
Radial gradients, with one color starting from a central point and fading to another color, use a similar syntax:
background: radial-gradient(yellow, green);
You can also specify the shape of the fade. By default it is an ellipse, spreading to fill the background box, but you can force it to be circular, regardless of the shape of the box:
background: radial-gradient(circle, yellow, green);
Using “closest-side”, “closest-corner”, “farthest-side” and “farthest-corner” you can also specify if the gradient is contained by the sides or corners of the box nearest to or furthest away from the origin:
background: radial-gradient(circle closest-side, yellow, green);
And if you wanted to place the origin of the gradient somewhere specific, you can also use “at”:
background: radial-gradient(at top left, yellow, green);
More compatibility notes: additional -webkit-radial-gradient
usage is wise. The order of the parameters needs to be changed here, and, like “to”, “at” is excluded. So:
background: radial-gradient(circle closest-side at 100px 200px , black, white);
Would be accompanied by:
background: -webkit-radial-gradient(100px 200px, circle closest-side, black, white);
If you don’t want a uniform blend across your gradient, you can specify exactly where in the gradient each color kicks in, straight after each color, starting at “0” and ending at “100%” (although lengths can also be used).
So, just to make it clear before tinkering:
linear-gradient(black 0, white 100%)
is the equivalent of linear-gradient(black, white)
radial-gradient(#06c 0, #fc0 50%, #039 100%)
is the same as radial-gradient(#06c, #fc0, #039)
linear-gradient(red 0%, green 33.3%, blue 66.7%, black 100%)
will have the same result as linear-gradient(red, green, blue, black)
That’s because, when the positions are stated in these examples, they evenly space out the colors, which is the default when no color stops are explicitly defined.
So, to get on with that tinkering, you can pull and stretch away with those stops:
background: linear-gradient(135deg, hsl(36,100%,50%) 10%, hsl(72,100%,50%) 60%, white 90%);
A single gradient will fill a box with the previous methods but you can use “repeating-linear-gradient” and “repeating-linear-gradient” to build on the color stops and, well, repeat the gradient.
For basic bars of black-and-white bars, for example:
background: repeating-linear-gradient(white, black 15px, white 30px);
Or something a bit more solid:
background: repeating-radial-gradient(black, black 15px, white 15px, white 30px);
@media
at-rules, used to target styles at specific media, such as screen or print, have already been covered. But this can be pushed to an even greater level of sophistication, enabling you to specify different design choices depending on screen size. A page can then be optimized and laid out completely differently for mobile phones, tablets, and varying browser window sizes.
To recap, if we want to apply some CSS solely to screen-based media, for example, one option would be to slot something like the following in at the bottom of a stylesheet:
@media screen {
body { font: 12px arial, sans-serif }
#nav { display: block }
}
To extend the previous example, not only can screen-based media be targeted, screen-based media of a certain size can be targeted as well:
<strong>@media screen and (max-width: 1000px)</strong> {
#content { width: 100% }
}
This is telling a browser to apply a block of CSS when its viewport is 1000 pixels wide or less. You could use this to do something as simple as making a content area or navigation narrower or you could completely re-arrange a page layout (like stacking page sections on top of one another instead of displaying them in columns).
You can apply more than one @media
rule, so you could have a number of different designs that are browser size dependent:
@media screen and (max-width: 1000px) {
#content { width: 100% }
}
@media screen and (max-width: 800px) {
#nav { float: none }
}
@media screen and (max-width: 600px) {
#content aside {
float: none;
display: block;
}
}
Note that if, for example, a layout area was 600 pixels wide or less, all three of these would be applied (because it would be less than or equal to 1000px, 800px, and 600px).
As well as using a general max-width
on the main content area (the article
elements), this site also has a number of size-dependent CSS rules. If you’re able to do so, try resizing your browser to see the changes take effect.
You could also use “min-width” in place of “max-width” if you want to do things the other way around and apply CSS to sizes equal to or over a certain length.
If you have a hankering for applying CSS depending on the orientation of the browser, fill your boots with something like the following:
<strong>@media screen and (orientation: landscape)</strong> {
#nav { float: left }
}
<strong>@media screen and (orientation: portrait)</strong> {
#nav { float: none }
}
This could be especially useful with mobile devices…
We’re not talking different CSS for each and every brand and model of laptop, phone, and donkey – that would be sinful – but we can, with a relatively clear conscience (as long as we’re sensible), specify the likes of the device’s screen dimensions and its pixel ratio.
A “handheld” media type does exist and it could be used as @media handheld
… but it isn’t widely supported and the distinction of what is “handheld” has become blurred due to the proliferation of all manner of devices with all manner of screen sizes.
device-width
, device-height
, min-device-width
, max-device-width
, min-device-height
and max-device-height
can be used to target the computed resolution of a device:
@media screen and (min-device-height: 768px) and (max-device-width: 1024px) {
/* You can apply numerous conditions separated by "and" */
}
It’s important to keep in mind that a CSS pixel need not be the same as a physical pixel. While a screen may physically be 720 pixels wide, a browser may actually apply CSS assuming that it is 480 pixels wide, for example. This is so that a standard designed web page will more likely fit on the screen. In this example, there is a pixel ratio of 1.5:1: There are 1½ physical pixels to every CSS pixel. A bog-standard desktop monitor will have a pixel ratio of 1:1: One CSS pixel to every physical pixel.
If you want to apply styles only to these devices, you can use something like:
@media (device-pixel-ratio: 2) {
body { background: url(twiceasbig.png) }
}
This would apply to the likes of the iPhone (4 and above), with a pixel ratio of 2:1. You can also use min-device-pixel-ratio
and max-device-pixel-ratio
.
Talking of iPhones, you know the deal: also use -webkit-device-pixel-ratio
, etc, etc…
You might also want to fiddle with a device’s viewport to get it to play how you want. Leaping back over to HTML, the following meta
element will force a device to render a page at the width of the viewport (rather than attempting to show a wider-width design and zooming out, which it will do by default if the page can be wider than the viewport’s width) and also prevent the user from zooming in and out:
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
The benefit of this is that you can control exactly what is applied to what physical screen size. And although it’s painful to remove user controls, if the design is delightfully swell and made just for that diddy little screen, there shouldn’t be a need to zoom.
The HTML Dog web site takes this approach: instead of a small device attempting to render a bigger, fatter web page by shrinking it down, the CSS turns it into a single-column design made specifically for such a device.
You can also apply styles depending on a device’s resolution:
@media screen and (resolution: 326dpi) { /* */ }
@media screen and (min-resolution: 96dpi) { /* */ }
Or on its aspect ratio:
@media screen and (device-aspect-ratio: 16/9) { /* */ }