CSS tutorial

Navigation

Skip navigation.

Site search

Site navigation

CSS tutorial

Printing

Other tutorials

Table of contents

Introduction

CSS is a formatting language, used to provide more customised web pages and make it easier to make multiple pages use the same style. The acronym stands for Cascading Style Sheets. All current browsers can handle CSS, and it is the best Web page formatting language produced to date. Some very popular browsers do not handle it as well as they should (see the section on browser problems) but largely support is good and developers are tending to use it much more often.

Using CSS, you can define colours, backgrounds, borders, margins, alignment, fonts, sizes and loads of other things for almost any part of your web pages.

The word cascading describes many of the features of CSS. Firstly, it means that many stylesheets can be used and will be merged by the browser to provide a computed style for each element. If styles defined for one element oppose each other, the later one will be used, unless another one more specifically refers to the element (for example, if all paragraphs are made red, but a paragraph that is in a <div> is made blue, the blue will override the red for paragraphs in a div, as it more specifically refers to the desired element). Cascading also means that each object inherits some styles from its parent object or parent class. The parents are not the same as the parent objects in JavaScript but use a similar idea. The objects are refered to by their element tag. The highest object in the structure is the html element. If any elements do not have their own CSS defined but the html element does, then the cascading behaviour means they will inherit from the html element. So, if in the html element we define the text colour to be white, then any tables will also have white writing in them.

Each element can be in a class. For example, if we define the 'p' tag to have a text colour red then every paragraph will be red. But if we then define a class of paragraph called mybold where the text is bold and we create a paragraph of class mybold, it will have bold text. But remember that style sheets cascade and elements inherit from their parent class, so the text in the paragraph of class mybold will also be red. If we define the class mybold to have blue text then the blue will override the red and the text in the paragraph of class mybold will be blue.

One of the features of CSS is that if the browser does not understand something, it will ignore it and move on to the next attribute. It will not display warnings. This can make things easier in some circumstances, since you can apply styles without having to worry that a browser might ignore the entire stylesheet, because it should only ignore the parts it does not understand (although there are a few exceptions). However, it also means that it can be difficult to work out if a browser will correctly apply a rule or not. For example, you may want to apply display:table-cell;width:25% to an element if it understands it, and width:100% if not. Unfortunately, CSS does not provide any way to test for support of a property.

Opera has some of the most comprehensive CSS support of any browser. It has fairly complete support for CSS 1 and 2.1 (including 6 separate media types), as well as several parts of CSS 3. The KHTML/WebKit engine browsers like Safari, Chrome and Konqueror also have fairly complete support for CSS 1, largely complete support for CSS 2.1 (but only for screen and print media), and large parts of CSS 3. After that are Gecko engine browsers like Mozilla/Firefox, which supports CSS 1 and CSS 2 (only for screen and print media), and some parts of CSS 3. They also have support for many CSS extensions. Last of all is Internet Explorer. When comparing the same version numbers, IE on Mac supports some parts that the Windows version does not, but both are fairly old and incomplete. They support CSS 1, and selected parts of CSS 2, and manage to pack more bugs into their support than most of the other browsers. Internet Explorer 7 supports more of CSS 1 than IE 6, and has fixed some of the CSS 2 handling. Internet Explorer 8 has finally made a proper advance to support most of CSS 2.1, but is still nothing like as good as the other browsers when it comes to more advanced CSS. Internet Explorer 9 is much closer to the other browsers, supporting CSS 2.1 (screen and print media only), and some of the more popular CSS 3 modules.

This tutorial is not intended to teach you all of the many possible styles that you can apply, it is intended to teach you the syntax expected with CSS.

Adding CSS to a page

When using CSS, it is important to make sure that browsers use their most standards compliant response. You will need to ensure that your DOCTYPE triggers standards mode rendering for these browsers, or they will assume your code is relying on some mistakes of older browsers, and will try to replicate some them to various degrees, which can produce unpredictable results.

There are two ways to include CSS on a page. One is by loading it from an external file, and one is by embedding it directly in the source code of the page. One of the most useful features of CSS is the ability to share the same styles across many pages, so that all pages can be changed by modifying a single file. To do that, you will need to keep the CSS in a separate file. This also allows you to keep the clutter out of your document, and helps avoid several other problems, so even if you only intend to use the CSS on one page, you may want to include it in an external file anyway.

To use an external file, you would usually name the file something.css (choose an appropriate name), and then use the LINK tag to tell the page to use it. Inside the head of a document put this:

<link rel="stylesheet" type="text/css" href="something.css">

To embed CSS directly into a web page, use the STYLE tag, and set the type to 'text/css':

<style type="text/css">
/* CSS goes here */
</style>

Note that CSS should only ever be included in the head of your document, unless you use inline style attributes on individual elements.

Using comments

Comments allow you to leave notes to yourself and other people in your CSS, and are useful as a reminder of what the styles are being used for and why. CSS only supports block comments, and these can span multiple lines. The slash-asterisk indicates a comment start. Everything after it will be ignored by the CSS engine until an asterisk-slash is encountered.

p { color: green; }

/* This is a
block comment */

div { position: relative; }

Commenting out your CSS

This is not needed any more. All current browsers are aware of style tags, and how to treat their contents, since they have been part of HTML since HTML 3. Browsers that do not understand HTML 3 or CSS (these are virtually never used now) will display the CSS as if it was the content of the page. You can hide the CSS from them by commenting out your CSS with standard HTML comments. Browsers that understand CSS will simply ignore these comments, and will just interpret the CSS within them:

<style type="text/css">
<!--

/* CSS goes here */

-->
</style>

Dealing with XHTML

Note that when I talk about XHTML, I am talking about pages that are served using a content type of application/xhtml+xml - the majority of pages that use XHTML markup are actually served as text/html and as a result are correctly treated as HTML, not XHTML.

The rules in XHTML are different. Style tags are not treated as being special. Their contents are treated as any other part of XHTML, so various selectors can be misinterpreted as part of the markup. To avoid this, it is best to put all CSS in external CSS files so that they do not interfere with the page itself. If you feel the need to put something directly on the page, you can declare it as CDATA (the default for style contents in normal HTML):

<style type="text/css">
<![CDATA[

/* CSS goes here */

]]>
</style>

If you feel the compulsion to comment out your CSS in XHTML, you must use a more ugly structure to contain your CSS. Again, this really is not needed, since browsers that do not understand CSS also do not understand XHTML, but in case you want to use it (maybe you are serving it as XHTML to some browsers, and HTML to others), this is what to use:

<style type="text/css">
<!--/*--><![CDATA[/*><!--*/

CSS goes in here

/*]]>*/-->
</style>

Note: If you (correctly) serve the XHTML as application/xhtml+xml (which IE 8- and many minor browsers do not understand at all) some older Opera versions will ignore the CSS completely if you use these elaborate comments. If you are sending the document as application/xhtml+xml (if you use text/html, then there is no problem), you are already restricting yourself to modern browsers, so you can use the basic CDATA structure, as this will not cause problems in any of these browsers.

General syntax

Firstly define the element the CSS is written for. Then use { and after putting in the styles, close it with }

This might look like this:

body { styles go in here }

In this case, the 'body' is known as the selector. This can get more complicated, and can include many different selectors.

For several elements to use the same style, you can separate them with commas:

p, div, span { styles go in here }

The syntax for the styles follows this pattern:

name_of_style_attribute: value;

You can include as many styles as you want inside the { and } curly braces. Occasionally, there may be more than one value for a single style, for example with the border attribute:

border: 3px double red;

To define styles that should only target elements with a certain class, put a fullstop then the name of the class, after the element. This might look like:

p.nameofclass { styles go in here }

This would also need the class to be written inside the HTML 'p' element tags to which it refers:

<p class="nameofclass">

If we use the syntax without specifying an element name, then every element of class 'nameofclass', not just p tags, will use this style:

.nameofclass { styles go in here }

There are also some pseudo-classes such as :hover. This particular one will only work in some browsers (most notably, Internet Explorer 6-) with 'a' elements. It will be applied when the mouse hovers over the element.

a:hover { color: red; }

The pseudo-classes can be used along with classes, like this:

a.nameofclass:hover { color: red; }

One of the most powerful uses of this pseudo class is to produce menus written only using pure CSS.

If an element has been defined with an ID then it can be given its own style by using the ID selector. Try to restrict this to cases where it is actually needed:

#id { color: red; font-weight: bold; }

You can also target the specific element type, combined with the ID selector:

element_type#id { color: red; font-weight: bold; }

Now for some clever stuff. It is possible to target an element based on what its parent elements are, by writing the name of the parent, followed by a space, followed by the name of the element you want to target. Note that the parent does not have to be a direct parent. It could be anywhere in the chain of ancestors. For example, if you want to assign a style to li elements where one of their parents is a ul whose parents include a td whose parents include a tr whose parents include a table whose parents include the body, you can write this:

body table tr td ul li { styles go in here }

If you also want to assign that style to p elements, you can combine this with the comma, as shown earlier:

body table tr td ul li, p { styles go in here }

Or mix that up however you like. You can also combine it with class selectors. For example, this will match all li elements whose parents include a td of class fish:

td.fish li { styles go in here }

If at any time you define two or more conflicting styles, the more specific one should be used by the browser. If you use an inline style, that should override other styles. There are exceptions to these rules, but I will not go into those here.

All styles will have a default value, and that may be different for different elements (for example, the border style has a default value of 'none', but most browsers use something like '2px groove black' as the default border for a fieldset). If you have styled an element with a generic style, and you want to reset it to its default style for that specific element, you will need to manually set it back to its default value. For example, you could set all paragraphs to have a 1 pixel border, then set paragraphs not to have a border if they are inside a div:

p { border: 1px solid black; }
div p { border: none; }

Some styles can be represented in a number of different ways. For example, the border style can be used to apply a border to all sides of an element:

p { border: 1px solid black; }

It is also possible to specify one border at a time:

p {
  border-top: 1px solid black;
  border-right: 1px solid green;
  border-bottom: 1px solid black;
  border-left: 3em solid black;
}

It is also possible to specify the thickness, colour, and style separately. Each one can accept 1, 2, 3 or 4 values. If one value is specified, all sides will use it. If you specify two, the first will be used by top and bottom, and the second will be used by right and left. If you specify three, the first will be used by top, the second will be used by right and left, and the third will be used by bottom. If you specify four, they will be used by top, right, bottom and left respectively:

p {
  border-width: 1px 2px 3px;
  border-style: solid solid solid double;
  border-color: black green;
}

And this can be done for one side at a time as well. This is generally most useful to specify a normal style, then override it for just one side:

p {
  border: 1px solid black;
  border-right-color: green;
}

These styles are all considered to be as specific as each other, so if you specify the border-right style and then the border style, the right border will be styled according to what you define in the border style.

Fonts

CSS provides a very high level of control over the fonts that a page should use. It is possible to say what font to use, including what fallback fonts to use if the primary font is not available. It is possible to say what size the font should be, what style it should have, what decorations it should have, and what the height of a line of text should be.

Specifying the font

These can be defined specifying several fonts at one time. This is useful as you may specify a font that a person might not have and so at the same time you can specify a font that they do have. Every browser that uses CSS will have at least three fonts defined - monospace (usually Courier or similar), sans serif (usually Arial or similar) and serif (usually Times or similar). There are more but not all browsers will have them.

The font used will be the first one defined, unless the user does not have that font in which case it will be the second, and it will continue until it finds one the user does have. If you do not specify a generic font as the last font in the the chain, and no other specified font is available, it will revert to the browser's default font - typically a serif font.

Fonts are defined using the font-family declaration, and the list of possible fonts are specified in a comma separated list. If the name of a font is made up of more than one word, the name must be in quotes.

Three examples of this might be:

p { font-family: "Times New Roman", Times, serif; }
p { font-family: Arial, sans-serif; }
p { font-family: "Courier New", Courier, monospace; }

Specifying the font size

It is possible to specify fonts in either relative or fixed size. The fixed sizes used are normally pixels or points, such as '12px', but the relative fonts are usually preferred, as they allow the user to use their own preference for font size, and their size can be changed in Internet Explorer for accessibility purposes (other browsers can resize all font size units, while Internet Explorer 7+ can only zoom the entire page if it uses fixed font sizes, and Internet Explorer 6- can do nothing).

The most commonly used relative font sizes are em, % and either smaller or larger. These sizes relate to the font size that would normally have been used for that element (except in cases where the browser itself uses a relative font size as the default for that element, such as with headings). A size of '1em' or '100%' is the default font size. Relative font sizes are multiplied, so if you specify a font size of '12px' on the body, '2em' on div elements, and '2em' on p elements, then a div in the body will have a font size of 24 pixels, and a paragraph in the div will have a font size of 48 pixels.

Font sizes are specified with the font-size declaration:

p { font-size: 0.7em; }

Styling the font

There are three main types of styling that you can apply to text. One is the weight of the font, such as font-weight: bold;. Another is the font style, such as font-style: italic;, and the last is decoration, such as text-decoration: underline;

p {
  font-weight: bolder;
  font-style: oblique;
  text-decoration: underline overline;
}

Specifying the height of a line

The font itself uses more space than its own height. For example, it may have a font size of 12 pixels, but a line height of 15 pixels, meaning that there is a 3 pixel gap between lines of text. Typically, the default line height is about 1.1em (which is relative to the font size being used by the element). You can specify a line height using any of the normal units. To use no gap at all, you could use 1em or 100%.

p { line-height: 1.2em; }

Combining the styles

The font declaration allows several of these styles to be specified at the same time. You can change as many of them as you want, using this syntax:

font: font-style font-weight font-size/line-height font-family

An example of this would be:

font: italic bold 1.2em/1.1em serif;

Colours and measurements

Colours

Many styles accept colours as values, or part of their values, such as color, background and border. Note that colours use the American spellings, not the British (or other) spellings (color instead of colour, and gray instead of grey). The CSS 3 colours allow either spelling of grey-based colours, but you may find that browsers expect the American spellings.

There are five main ways to specify colours, #rrggbb, #rgb the two rgb( ) syntaxes and actually typing the name of the colour. You can choose which is best for you. For the first two methods, the colours are defined in hex.

#rrggbb
  • rr = 00 to ff for red
  • gg = 00 to ff for green
  • bb = 00 to ff for blue
eg. #b85c4f
#rgb
  • r = 0 to f for red
  • g = 0 to f for green
  • b = 0 to f for blue
eg. #b54
rgb( cr, cg, cb )
  • cr = 0 to 255 for red
  • cg = 0 to 255 for green
  • cb = 0 to 255 for blue
eg. rgb( 184, 92, 79 )
rgb( pr, pg, pb )
  • pr = 0% to 100% for red
  • pg = 0% to 100% for green
  • pb = 0% to 100% for blue
eg. rgb( 72%, 36%, 31% )
Colour names

Firstly, there are the 16 main HTML colours (plus orange) - I put the black backgrounds in so you could see the colours better aqua, black, blue, fuchsia, gray, green, lime, maroon, navy, olive, orange, purple, red, silver, teal, white, yellow

CSS 3 also defines many other colours and most current browsers support them. However, there are still browsers in use that do not. Whether you choose to use them is up to you.

Lastly there are are the system colours, which give the colours specified by the operating system. Support for these depends on what is provided by the operating system and browser. Generally, it is a good idea not to rely on these except in controlled situations.

There is also inherit which inherits the relevant colour from the parent element. Backgrounds can also use transparent.

Now for something totally non-standard but fun all the same, here's how to apply colour styles to your scrollbars in IE 5.5+ and Opera (other browsers will just ignore it).

Measurements

Many styles accept measurements, such as border and font sizes, line and element heights, widths and positions.

Measurements must always be given with units. The following measurement units are permitted.

em
1em is the default font size for that element
ex
1ex is the default lower case font size for that element (as letters like 'x')
px
Pixels, relative to the normal pixel size of a normal computer screen
%
Percentage of defualt size or parent element size
in
Inches ~= 2.54 centimeters
cm
Centimeters
mm
Millimeters
pt
1 point = 1/72 inches
pc
1 pica = 12 points

in, cm, mm, pt and pc will only make sense if the browser knows how many pixels are on the screen and how big the screen is. Often, this is not the case. Not all computers know how big the screen is, as not all screens tell the computer how big they are. In these cases, the browser must make a guess.

This paragraph element has been defined with border: 3px double fuchsia;. It will have a double lined border 3 pixels wide, that will be fuchsia coloured.

Dependence

Some attributes are dependent on others. An example of this is would be the 'left' and 'top' attributes. These will only be used if the 'position' attribute has been set to absolute, relative, or fixed. For example:

div {
  position: absolute;
  left: 10px;
  top: 100px;
}

The Clip and z-index styles can also only be applied to absolutely positioned or fixed positioned elements.

If you fail to specify the styles that these others are dependent on, the browser will simply ignore those styles. As a result, you can specify the left and top positions of any element, but it will not have any effect. If a script later adds the required style, then suddenly all of the styles come into effect together.

There are also a few styles that will force certain other styles to be applied without you specifying them. Examples would be the float or position styles. Applying these to any element will immediately also apply the display:block; style, even if you never apply that style yourself.

Referencing external files

It is possible to use external files as part of your CSS. For example, you may want to apply a background image to an element. This is done using the background-image style, and the related background style. These load images using the url value:

background-image: url(backing.jpg);

The url is relative to the file the CSS is in, so if you are using external CSS files, you can use the same file from pages in any directory, and the CSS will always reference the correct images.

You can also make a stylesheet import another stylesheet using the import rule (note that this is not supported by some old browsers). This also uses the url value:

@import url(somestyle.css);

Once again, this is related to the CSS file.

The url value can use any valid file URL, including accessing files from other servers:

@import url(http://example.com/somestyle.css);

Any @import fule must be at the top of your CSS file, before any normal CSS rules.

Inline style

An element can be given its own style by using the style attribute. This means that irrespective of what is specified in the stylesheets, it will always use these styles. That is not strictly true, since it is possible to make a selector that is considered more specific, but for most purposes, inline styles override stylesheets.

Using an inline style means that you largely lose control from stylesheets, meaning that if you decide to restyle your pages, you will be unable to restyle that part. It is generally not a good idea to use inline style attributes. They are best suited to scripting that creates animation effects, where there is a need to apply certain styles (usually positioning) irrespective of the style.

<div style="position: absolute; left: 10px; top: 100px;">

Positioning

Positioning will work in all '4th generation' browsers (except iCab 2-) using two types of positioning; absolute and relative. Relative positions an element relative to the position it would naturally be in. The space will be left for it. If it is correctly displaced, it can float on top of other elements. Absolutely positioned elements are positioned relative to the top left corner of the document. No space will be left where they normally would be. They will float over other elements.

Positioned elements should be given a combination of top, left, bottom, right, width and / or height properties to allow the browser to work out where to put the element. For the best reliability in old browsers, it is best to position only DIV elements. Newer browsers can position most elements.

Positioning is very useful, especially in DHTML. Absolutely positioned elements inside relatively positioned elements are positioned relative to the relatively positioned element. Got that? This means that they can be inserted into the document like a normal block element (like a paragraph) but can accept styles normally given to absolutely positioned elements.

As an example of the ability of CSS positioning (CSS-p), how about designing page layout without using tables:

div.sideLink {
	/* side link container */
	position: absolute;
	
Warning: Undefined variable $sw in /var/www/vhosts/tarquin-howto/webroot/tutorials/csstut/position.inc.php on line 18
left: 30px; top: 50px; width: 140px; } div.sideLink div { /* borders and padding for the div inside the side link container */ padding: 10px; border: 2px solid #000077; } div.mainPart { /* main container */ position: absolute;
Warning: Undefined variable $sw in /var/www/vhosts/tarquin-howto/webroot/tutorials/csstut/position.inc.php on line 32
left: 200px; top: 20px;
Warning: Undefined variable $sw in /var/www/vhosts/tarquin-howto/webroot/tutorials/csstut/position.inc.php on line 34
right: 30px; } div.mainPart div { /* borders and padding for the div inside the main container */ padding: 10px; border: 2px solid #007700; } div.sideLink div a { /* links in the side link conatiner */ width: 100%; display: block; background-color: #bbbbff; margin-bottom: 2px; } div.sideLink div a:hover { /* hover effect for the links in the side link conatiner */ background-color: #bbffff; }

Div elements of class sideLink will be 30 pixels from the left and 50 pixels from the top of the window. They will be 140 pixels wide. Links within those div elements will be the full width of the element (if the browser supports that). Div elements of class mainPart will be positioned 200 pixels from the right and 20 pixels from the top of the window, and will be sized wide enough to be 30 pixels from the right side of the screen. This will position these elements to the right of the div elements of class sideLink.

Some browsers will position the elements taking their borders and padding into account, and others will not, so the page looks different in different in different browsers. It may be a better idea to put the positioning onto one div, then put another div inside it, to which you assign borders and padding, and make the width 100% of its parent element's width. I have done this here. Both classes of div element will have a 2 pixel thick border, and will leave 10 pixels between the border and the contents.

Try it here: see these positioning styles in action.

Media types

CSS provides an easy way to target browsers on different types of devices, or different uses. For example, the design you produce for a normal desktop browser may not be suitable for a handheld device, or a printer. These are known as media types. There are several media types, and most browsers will generally concentrate on just one or two, depending on what they are designed to be used for. Opera is by far the most versatile, and supports six different media types.

All major browsers use screen media as their default, and will apply screen media when viewing a Web page normally. Most of them also support print media and will use that when printing a page. Projection media is used for fullscreen view in Opera (version 9 and above will fall back to screen media if there is none for projection), and is designed for displaying on projector displays. Handheld media is used on handheld devices, small screens or narrow displays. It is supported by Opera, OpenWave, supposedly by Obigo, and partially by Pocket Internet Explorer, but the user may need to enable it, as the browsers may default to screen media. Some television browsers (including Opera) support TV media. Aural media, renamed to Speech in CSS 2.1, is used when the page is being read by a voice synthesizer. Opera supports speech media when the voice module is installed.

In theory, a browser should only apply one media type at any time. Escape 5 breaks this rule by applying screen and projection media types simultaneously (it never applies handheld, even though it is supposedly designed for devices). WebTV/MSNTV breaks this rule by applying screen and tv media types simultaneously. Pocket Internet Explorer also breaks this rule. It completely ignores inline media declarations, and if specified in a media attribute, it mistakes screen and handheld for each other, and applies both of them at the same time as each other, even if you tell it to use only screen media (desktop). NetFront makes mistakes with @media rules and may apply styles from rules inside all of them, no matter what media types are specified.

Most of the normal styles are available to all media types, but there are some styles that only make sense in some media types. For example, the font-size and cursor styles do not make any sense in speech media. Some styles are only available in certain media types. For example, the page-break-before style is only available in media types that support pages display, such as print, projection, and TV.

If your design does not work well in other modes, you should consider adding different styles for different media types. For example, if your design is suited only to desktop displays (maybe it limits the minimum resolution to 1024x768 or 800x600) you may want to add some styles to make it work on handheld devices, instead of expecting those browsers to reformat your page. If your navigation relies on visual identifiers, such as rollover effects, you may want to add extra styles for handheld devices, which generally do not have a mouse. And you may want to add some extra words to the speech and aural medias to help speech users make sense of it. Similarly, you may want to add extra information to braille media. Or maybe you want to hide your navigation when printing the page.

By default, stylesheets apply to all media types. You can use either of three ways to make styles apply only to specific media types. The first is to use the media attribute of the link or style tag. This accepts media types in a comma separated list:

<link rel="stylesheet" media="screen,projection,tv" href="main.css" type="text/css">
<link rel="stylesheet" media="print" href="print.css" type="text/css">
<link rel="stylesheet" media="handheld" href="smallscreen.css" type="text/css">

You can also use the media type 'all' to signify that the stylesheet is for all media types. This is the same as not supplying a media attribute.

The second way to specify a media type is to use the @media rule. This allows you to add media specific sections inside your stylesheet so you can use a single stylesheet, and still provide styles for specific media types. The @media rule is similar to the media attribute; it accepts a comma separated list. This rule can be put anywhere inside your stylesheet (they can even be nested), and should contain relevant style rules inside curly braces. Any styles not inside a @media rule are applied to all media types:

p { color: green; }
@media screen, projection, tv {
  #foo { position: absolute; }
}
@media print {
  #navi { display: none; }
}
@media handheld {
  #foo { position: static; }
}

The third way to specify a media type is to use the @import rule. This allows you to import a stylesheet but only use it for a specific set of media types. Note, however, that it is not supported in Internet Explorer 7-, and the stylesheet will not be imported for any media type:

@import url(bigscreen.css) screen, projection, tv;

In browsers that have a very high level of CSS support, you can also use CSS media queries to apply different styles, based on the size of the screen, the browser window, or various other features of the device. At the moment, these are supported by Opera, Chrome/Safari 3+, Konqueror 4+, Firefox 3.1+ and Internet Explorer 9+, and hopefully this will be extended to other browsers too. Opera 8 only allows you to check on simple things like (window) width, height, device width, and device height, and it can only do pixel units. Opera 9+ can check the other media features as well, and can use any units. Very few mobile versions of Opera still use the Opera 8 engine.

@media all and (max-width: 500px) {
  #foo { position: static; }
}

Note that ICEbrowser and OpenWave do not treat media queries correctly, and may always apply the styles inside them.

Special notes for handhelds

I will concentrate on handhelds for a moment, since after normal desktop/laptop browsers, handhelds are the most common in use. However, these principles apply to all media types, with the exception of screen.

There is no rule that says you have to create a stylesheet for handhelds. In fact, you should only create a handheld stylesheet if you have a specific idea of how you want your page to look on a handheld device. Handheld browsers have certain limitations, and if you are unwilling to cater to those limitations, just leave well alone, and make your stylesheet target all media types. Many handheld browsers can apply reformatting to pages, to try to make them work, even if you do not do this yourself. In fact, in most cases, the browsers are better at this than you are, and you can help them along by having clean, semantic markup.

The handheld media type is a little bit overloaded. It means several things:

The handheld media type has to represent all of these, and if you create a handheld stylesheet, it must cope with all of these problems. It must not attempt to force any specific widths - this is a fairly common mistake on real pages - a handheld stylesheet must allow the design to work at different screen sizes without the need to scroll horizontally. You can also use media queries to specifically target the problems caused by screen size. They can be adapted to many different screen sizes, and are much more useful and flexible in this respect.

Note that some of the higher resolution PDAs and tablet PCs are not treated as handheld devices. Browsers that run on them may not respond to the handheld media type, and may use screen instead. Some handheld browsers do not support enough CSS to use handheld media, and will always use screen media.

Making a handheld stylesheet can be done one of two ways.

  1. By making sure that the normal stylesheet does not apply to handheld media, and then have a separate stylesheet that applies only to handheld.
  2. By making a stylesheet that applies to all media types, then have a handheld stylesheet that changes only the parts of the full stylesheet that cause problems for handhelds.

Which one you use is up to what suits you and your site best. This site uses the second approach, reducing large fonts, removing margins, floats, positioning, and showing a few extra links to aid navigation. It also uses media queries to help progressively apply some of these changes to various window sizes, so even desktops can have a layout that suits the browser window size.

The mobile browsers

This list is not exhaustive, but it should give you an idea of the state of mobile browsers.

Opera Mobile
  • One of the most popular and common handheld browsers. Installed by default on a very high number of phones and PDAs.
  • Has a very high level of CSS support.
  • Supports media queries.
  • Can use handheld media, if the user chooses to enable that option, and if you specifically target handheld media (so you must actually say 'handheld', and not 'all').
  • In handheld mode, it uses screen media if handheld media is not specifically targetted. The page will then be reformatted to fit the screen, so very little of the CSS will actually be used.
  • Allows the user to enable/disable handheld mode if they want to, so they can see the page rendered as if it were on a desktop.
  • Will not use handheld media on high resolution devices, but can still be targetted using media queries.
  • Can be treated as a handheld browser.
Opera Mini
  • One of the most popular and common handheld browsers. Installed by default on several phones.
  • Designed to run on devices with the smallest screens and lowest capabilities.
  • Has a very high level of CSS support in Opera Mini 4 on high capability devices.
  • Supports media queries.
  • Can use handheld media, if the user chooses to enable that option, and if you specifically target handheld media (so you must actually say 'handheld', and not 'all').
  • Allows the user to enable/disable handheld mode if they want to, so they can see the page rendered as if it were on a desktop.
  • Uses screen media if handheld media is not specifically targetted.
  • In Opera Mini 4 on high capability devices, tries very hard to behave like it is on a desktop (including using a virtual screen width), using a mouse. Text will be wrapped (and their containers extended as needed) to make the text fit the width of the screen.
  • In Opera Mini 3-, or in Opera Mini 4 on low capability devices, or in Opera Mini 4 on high capability devices if the user has chosen the option, the page will then be reformatted to fit the screen, so very little of the CSS will actually be used.
  • Can be treated as a handheld browser.
NetFront/Blazer
  • One of the most popular and common handheld browsers. Installed by default on a high number of phones and PDAs.
  • Has a reasonable but not good level of CSS support.
  • Uses screen media, and cannot be targetted using CSS media types. The page will then be reformatted to fit the screen.
  • Some special custom versions use only handheld media, and will ignore any stylesheets that do not specifically target it, meaning that most pages remain completely unstyled. They also ignore images on many pages. However, these versions are not very common.
  • Has a broken implementation of @media rules; it often applies styles from any media type (such as print media), ignoring the media declaration.
  • Allows the user to disable or alter reformatting if they want to, so they can see the page rendered as if it were on a desktop.
  • Should be ignored as a handheld browser. Treat it as a desktop browser, and hope that its reformatting can be adapted by the user into something readable.
Pocket Internet Explorer
  • Not very popular. Installed by default on Pocket PC and Windows Mobile devices, but is usually replaced with Opera or NetFront, as they generally perform much better.
  • Has a poor level of CSS support.
  • Uses handheld media and screen media at the same time (breaking the rules of CSS). The page will then be reformatted to fit the screen, so very little of the CSS will actually be used.
  • Only understands media="..." attributes, not @media or media in @import rules.
  • Sometimes uses @media blocks, but not reliably - ignored on most pages. May ignore an entire stylesheet if it contains media queries (not normal @media blocks).
  • Allows the user to disable or alter reformatting if they want to, so they can see the page rendered as if it were on a desktop (apart from the obvious CSS limitations).
  • Can be treated as a handheld browser, as long as you only apply the stylesheet in a way it understands, and you only use the method of overriding styles, since it will always apply screen media.
Series 60 Browser and Safari on iPhone
  • Installed by default on the newest Nokia Series 60 phones. Not popular yet.
  • Has a fairly high level of CSS support, as it is based on the Safari engine.
  • Uses screen media, and cannot be targetted using CSS media types. Tries very hard to behave like it is on a desktop (including using a virtual screen width), using a mouse, and virtually no reformatting.
  • Some newer releases support media queries.
  • Should be ignored as a handheld browser. Treat it as a desktop browser, and hope that it works.
Minimo/Fennec
  • Still in very slow development. Not popular.
  • Has a fairly high level of CSS support, as it is based on the Gecko engine.
  • Uses screen media, and cannot be targetted using CSS media types. The page will then be reformatted in Minimo to fit the screen, so very little of the CSS will actually be used.
  • Allows the user to disable reformatting if they want to, so they can see the page rendered as if it were on a desktop.
  • Some newer releases support media queries.
  • Should be ignored as a handheld browser. With Minimo, just hope that its reformatting works.
Konqueror Embedded
  • Still in very slow (virtually non-existent) development. Not popular.
  • Has a fairly high level of CSS support, as it is based on the KHTML engine.
  • Uses screen media, and cannot be targetted using CSS media types (all releases have been based on earlier konqueror versions that did not support them). The page will not be reformatted. Uses a mouse interface.
  • Should be ignored as a handheld browser. The lack of reformatting means that most pages do not work.
OpenWave
  • Fairly popular handheld browser. Installed by default on a number of phones.
  • Has problematic CSS support (seems to have problems mixing class selectors and ID selectors, for example).
  • Does not treat media queries correctly either as a media query, or with CSS error handling (required for browsers that do not support them). It may apply the rules inside them even if the query would not match the current situation.
  • Uses handheld media. The page will then be reformatted to fit the screen.
  • Can be treated as a handheld browser.
Obigo
  • Installed by default on a some phones.
  • Has relatively good CSS support in development versions.
  • Uses handheld media if it is available.
  • May use screen media if handheld media is not specifically targetted. The page will then be reformatted to fit the screen.
  • Allows the user to disable reformatting if they want to, so they can see the page rendered as if it were on a desktop.
  • Can be treated as a handheld browser.
  • Insists that Web developers must pay to test their sites in it.
Deep Fish
  • Still in closed alpha development, not available for testing yet.
  • Possibly related to Obigo, which became part of a partnership deal with the parent company just before Deep Fish was announced.
  • Media types unknown, but the demonstration images seem to use screen media.
  • Uses a virtual screen width instead of reformatting.
  • Probably cannot be treated as a handheld browser.
ThunderHawk/Bolt
  • Not popular.
  • Has a fairly high level of CSS support, as it is based on the KHTML/Safari engine (Bolt is a progression from ThunderHawk, which uses WebKit instead of a custom KHTML fork - since they both use the same server-side solution, ThunderHawk may also switch to WebKit, if it is not already using it).
  • ThunderHawk apparently used handheld media, but I cannot test this. Bolt only uses screen media. Neither currently support media queries.
  • Thunderhawk may use screen media if there is no handheld media, but uses a virtual screen width instead of reformatting.
  • Bolt uses a virtual screen width with only linewrapping instead of full reformatting. Although it claims to have mobile view, this only causes it to request WAP pages, with fallback to regular HTML, instead of using handheld CSS.
  • Should be ignored as a handheld browser. Treat it as a desktop browser, and hope that it works.
  • ThunderHawk insists that Web developers must pay to test their sites in it.
Picsel
  • Not popular.
  • Media types unknown, but the demonstration images seem to use screen media.
  • Uses a virtual screen width instead of reformatting.
  • Probably cannot be treated as a handheld browser.
  • Only delivers to phone manufacturers and network operators, so not available for normal Web developers to test.

As well as the proper browsers, there are some others that are still in use, but are more of a left-over from the early days of mobile browsing.

Limited HTML browsers
These are sometimes installed as the default browsers on phones, but are being replaced with proper Web browsers. They do not understand HTML or CSS well enough for you to target them, and should generally be ignored. If they happen to be able to use your page (which they should if you use semantic HTML), then that is a bonus.
WAP/WML browsers
These are sometimes installed as the default browsers on phones, but are being replaced with proper Web browsers. They choose not to provide access to the full Web, and demand that authors waste time and resources by making an extra version of all of their pages. I ignore these completely.
XHTML browsers
These are like WAP browsers, but are able to use a small percentage of real Web pages, if they use XHTML. They are also being replaced with proper Web browsers. I ignore these as well.

Browsers for handheld development

When developing Web pages, it is beneficial to be able to test them on a handheld browser. However, not everyone has access to a mobile browser, and in addition, the costs of using one are fairly high. It is useful to be able to use a browser on a desktop for testing. Some of the browsers are only available on real devices, but the following browser tools are available for desktops:

Opera
The desktop version has all you need to test Opera Mobile. In the desktop version, use View - Small screen. If your page does not have a handheld stylesheet, this will use Small Screen Rendering to reformat the page in the same way as Opera Mobile. You can resize the window to see how it works at different resolutions. If your page has a handheld stylesheet, it will use that, in the same way as Opera Mobile. You can also use View - Fit to width, to see the reformatting for different sized devices.
Opera Mini
Real Opera Mini, running inside a phone emulator.
NetFront
NetFront with an emulator running on your destop. Experiment with the various reformatting options, but do not get your hopes up. The NetFront emulator has disappeared from their site, and I cannot find anything in their developer downloads. Apparently they no longer want developers to test. If you want to test it, get a Windows Mobile (emulator), and run the NetFront trial download on it.
Pocket Internet Explorer
Pocket IE on a PocketPC emulator running on your destop. Note that the installer is a mess. You will also need the VM network driver. If you have trouble getting the network to work, install ActiveSync, and use that instead.
Series 60 Browser
The latest Series 60 SDK (emulator) contains the Series 60 Browser. You will need to register to download it. Unfortunately it is a time limited trial, and it leaves some registry keys behind that it tries to prevent you from removing - presumably to enforce its time limit. Apparently they do not want Web developers to test in it. Pity.
Safari on iPhone
Use normal Safari. The iPhone install is generally the same.
Minimo
A Firefox extension that applies the Minimo main reformatting stylesheet to any page. It does not apply the site specific hacks that Minimo uses, and cannot simulate other browsers that use the correct handheld media, or media queries (so in other words, it only shows you how Minimo will render a normal Web page, it may be nothing like how the more common handheld browsers will render it).
Konqueror Embedded
Not really worth testing, but you can just use a normal Konqueror install, and make your window very small.
OpenWave
OpenWave with an emulator running on your desktop.

Note, of course, that if you want to test memory constraints, you will need to use an emulator or a real device. To test bandwidth constraints, you will need to use a real mobile device. Note that generic emulators are also available (such as emulators for Series 60 or Windows Mobile devices). These can be used to test other browsers.

Some of the other browsers insist that developers must pay purchase or rental charges in order to test their sites in it. In my opinion, a browser that chooses this approach does not want developers to test in it (they certainly cannot expect every individual Web developer to pay for the privilage of testing someone else's product on their site), and should be ignored.

Special printing tools

There are several tools supporting CSS, whose sole purpose is to convert HTML or XML documents, styled with CSS, into printed documents. These could either print directly, or convert the document into a more printer orientated format, such as PostScript or PDF.

Most of these tools offer lower CSS support than normal browsers, many even lower than the CSS support of Internet Explorer 6, and in most cases, a better result could be obtained by printing from a browser. Examples of these tools would be HTML2PS (usually combined with PS2PDF), or DOMPDF.

There is one exception to this; a program called Prince. It is the only such tool that has better CSS support than most browsers. In fact, its CSS 2.1 print media support is equivalent to Opera's, with several extras from the CSS 3 Generated Content for Print Media module that no browser is capable of supporting. As a result, it is the only conversion tool that I currently recommend, and in fact, the tutorials on this site (including this one) are designed to be printed for private or educational use, with Prince. It is free for personal or non-commercial use, and can be licensed for commercial use.

Browser problems

Browsers support varying amounts of CSS. Support generally increases as new versions are released. Most intentionally implement various bugs (known as quirks) when the Web page triggers quirks mode (depending on the doctype - see my HTML tutorial for details). This is designed to cope with unmaintained legacy content on the Web. You should ensure that your page triggers standards mode to get the most reliable CSS response.

For old browsers, most CSS problems are noticed in Netscape 4. I have found a site that fully documents every bug that Netscape 4 has with stylesheets. It is a very long read. I recommend that you ignore Netscape 4 completely, and style for newer browsers instead (Netscape itself is now using version 9). If you need to ensure that Netscape 4 can still view your pages (you don't), it is best to simply put all of your styles in another external file, and use the @import rule to import it, since Netscape 4 cannot import. Netscape 4 will show an unstyled page.

Out of all the current browsers, Internet Explorer's support is generally the worst. Widely used versions are missing many parts of CSS, and can be very difficult to design for. Most sites will need to cater for older versions of Internet Explorer (the Windows version, at least - the discontinued Mac version is very different, with very different problems). This means restricting styles to CSS 1, and the basics of CSS 2 positioning. If you want to use more advanced styles, you need to make sure that these are purely decorative, and the style still works in Internet Explorer versions that do not support them.

In general, the best way to write is using a browser with a high level of CSS support to check your CSS, then after you have something that works nicely, work out what you will have to change to make it work in versions of Internet Explorer that you still need to cater for. For development, I recommend testing in at least Opera, Mozilla/Firefox and Safari/Chrome (all are available on all major platforms). If you have access to it, you should also test in Konqueror, or some other browser based on the KHTML engine. It will have differences from the related Safari WebKit engine.

Remember that there is usually more than one way to achieve what you need, such as being able to use both float and position to do columns (you can also use display:table; in most browsers, but not Internet Explorer 7-). If it helps, I have written an article on how Internet Explorer causes problems, which includes workarounds for some of the more common problems.

Margin Collapsing

Many Web developers run into margin collapsing without realising what it is, or why it is happening. It takes place on virtually every Web page, and in most cases, it creates the desired effect without causing any undesired side effects. However, when it does cause a problem, it usually appears as strange gaps at the top of elements even when they have their top margins set to 0. The typical response is to use an unrelated workaround of some kind, such as positioning everything. Understanding the cause allows more efficient workarounds to be used, especally those that actually deal with the root cause.

Historically, margin collapsing only exists because older browsers like Netscape 3 used to do it before they had CSS, and when CSS was created, it had to describe that behaviour so it could be implemented in CSS.

The box model

The first thing you need to understand is the CSS box model. In its simplest form, a box is a block element, like a DIV, for example. In the middle of the box are the contents. If the relevant styles are set, even if there are no contents, the content size comes from the height and width styles (you will need to ensure that your DOCTYPE triggers standards mode rendering for some browsers, particularly Internet Explorer, for them to get this part correct). Then outside the contents, but still inside the box, is the padding. Then outside the padding, but still inside the box, is the border. Outside the border is the margin. "Box" is only a word, you do not really need to think about it yet. It is more important to understand where the various margin, border, padding, and content exist in relation to each other.

Almost no elements have padding by default. Some of the rare cases where an element has padding by default would be fieldsets, or in some browsers the padding of the body, and the padding of a DL list. For the sake of this tutorial, it is easiest to assume that no block elements have padding.

Most block elements have a default top and bottom margin, such as paragraphs and headings for example, which may have a top and bottom margin of 1em, which computes to 16 pixels if that is the current font size. This is what creates the gap between two paragraphs. It is also what causes margin collapsing to be so important. This tutorial will assume that paragraphs have a 16 pixel top and bottom margin, but you should be aware that different browsers will have very different default margins, and can also change depending on user settings such as font size.

Take the following HTML:

<div>A</div>
<p>B</p>
<p>C</p>
<div>D</div>

Paragraphs may have 16 pixels top and bottom margins, while DIVs have 0. As a result, the gap between the DIV and paragraph is 16 pixels in each case. The gap between the two paragraphs is also 16 pixels, even though there are two paragraphs, and they may be expected to have 32 pixels between them. This is a margin collapse.

The first and simplest kind of margin collapse

Margin collapsing only happens with top and bottom margins, not left and right, and not at all on inline elements. Margin collapsing happens wherever two (or more) top or bottom margins are touching. The basic idea is that when they touch, instead of getting the sum of the two margins, the bigger one is used, and the other is ignored. So in the case of the two paragraphs, the 16 pixel bottom margin of the first one touches the 16 pixel top margin of the second one. Max(16,16) is 16, so the gap between them is 16 pixels.

Three elements

<p>A</p>
<p style="margin-top:100px;margin-bottom:50px;"></p>
<p>B</p>

The middle paragraph has no contents, so it also has no height (since the CSS does not specify a height for it). However, it is still there. The resulting margins are like this:

16 pixels
A
16 pixels
100 pixels
50 pixels
16 pixels
B
16 pixels

The middle paragraph is 0px high, so its margins are touching. So there are 4 margins touching each other. The gap between A and B is max(16,100,50,16), which is 100 pixels.

Negative margins

Negative margins are special and are dealt with as follows:

  1. Work out what margins are touching.
  2. Ignore all negative margins.
  3. Perform the collapse as if there were no negative margins.
  4. Select the largest of the negative margins, and subtract it from the computed margin from step 3.
<p style="margin-bottom:-5px;">A</p>
<p style="margin-top:100px;margin-bottom:-50px;"></p>
<p>B</p>

Step 1:

16
A
-5
100
-50
16
B
16

Step 2, ignoring the negative margins:

16
A
100
16
B
16

Step 3:

The gap between A and B is max(100,16), which is 100 pixels.

Step 4, subtracting the largest negative margin:

Max(5,50) is 50.

100 - 50 = 50

So the resulting gap between A and B is 50 pixels.

Nested margins

This is the part that causes most problems for Web developers.

<div style="margin-top:10px">
<div style="margin-top:20px">
A
</div>
</div>

There are two margins touching each other: 10 and 20 pixels. The resulting margin will be max(10,20), which is 20 pixels.

The question is; where does the 20 pixels appear:

  1. Before the outer DIV?
  2. Before the inner DIV but inside the outer DIV?

(In other words, if the background of the outer DIV is red, and the background of the inner DIV is white, should any red be visible?)

The answer is quite simple; the resulting margin always appears as far out as possible - outside the outermost element whose margin is taking part in the collapse. Even though the margin that gets "used" is the one from the inner DIV, it appears outside the outer DIV. So it seems to appear in the wrong place.

This is the part that causes the most unexpected effects. A developer might make the background of a container white, make the background of a DIV inside it blue, then put a paragraph or heading inside it. The expectation is for the blue to extend all the way to the top of the container, but it does not. The paragraph may have a default top margin of 16 pixels, and that collapses to the outside of the DIV because it touches the 0 pixel top margin of the DIV, pushing the DIV down, and leaving a strange gap at the top of the blue.

The solution to the unwanted gap, is to make sure the margin collapse cannot happen. The way to do that is to make sure the 0 pixel top margin of the DIV and the 16 pixel top margin of the paragraph cannot touch each other. This is where the box model becomes useful. It is possible to remove the margin of the paragraph, but it is also possible to manipulate the DIV to insert something between the paragraph's top margin, and the DIV's 0 pixel top margin. The way to do that is to add a top padding or top border of at least 1 pixel of height onto the DIV, since they sit between the two margins.

The following example shows the situation described, with a paragraph inside a DIV that has a blue background, inside a white container (with the solid black border). The paragraph has a dashed border so you can see where it is. The white shows through because the paragraph's margin has collapsed through and is applied to the DIV:

Paragraph

The following example shows the same situation, but with a single pixel of top and bottom padding added to the DIV. The result is two pixels taller because of the padding, but the margin remains on the paragraph, and does not collapse through to the DIV. The margin extends to one pixel away from the black border, with the remaining pixel being the DIV's padding:

Paragraph

The following example uses a similar approach, but uses a (dotted red) border on the DIV instead of padding:

Paragraph

Internet Explorer 7-

Internet Explorer 7- gets most of the margin collapsing behaviour correct. However, it does have some issues.

BODY elements never take part in margin collapsing, since they are considered magical, which means sometimes a strange gap does not show up in Internet Explorer when it does in other browsers, when the collapse happens with the top of the BODY. This is usually easy to solve; just prevent the margin collapse for the other browsers, and it works in Internet Explorer too. (Note that the HTML element's margins never collapse in any browser, this is correct behaviour.)

In rare cases, margin collapsing where an inner element has a bottom border and an outer container has a bottom border, can cause the background of an intermediate element to spill into the container in Internet Explorer.

The more problematic bug is caused by Internet Explorer's strange hasLayout behaviour. This is a fundamental bug in Internet Explorer 7- and affects several other things as well, but this article will only deal with margin collapsing. Setting certain styles on an element makes it "have layout" (a concept unique to Internet Explorer, and not compliant with any standards). The most common style that causes a problem is width. When an element hasLayout it suddenly assumes a minimum height of 1em, and if set to something less in Internet Explorer 6, such as 0.5em, it still uses 1em.

An element has layout when one of the following conditions is true:

Height usually does not cause a problem, since setting height will prevent collapsing in other browsers anyway. However, triggering hasLayout on a nested element where the parent has prevented margin collapsing using borders or padding, can cause margins to disappear, or to collapse through the parent irrespective of the padding or borders. Generally, hasLayout is a mess, and it is best to avoid it in places where margins are critical.

The hasLayout issue is dealt with in more detail in another article.

Positioning

When an element has either position:absolute or position:fixed, it is taken out of the flow, and its margins no longer take part in any collapses at all.

<p>A</p>
<p style="margin-top:100px;margin-bottom:50px;position:absolute;"></p>
<p>B</p>

The gap between A and B is max(16,16), which is 16 pixels.

Floats

Float also takes elements out of the flow. The margins of its siblings touch as if it was not there, and they collapse while completely ignoring it, as with positioned elements.

When the float is being positioned, it is initially placed as if it had no top margin at all (so its top margin does not take part in any collapsing), and as if it had no subsequent siblings (so any collapsing between its preceding and subsequent siblings is temporarily ignored). Any margins of preceding elements that are due to take part in a margin collapse have their margins collapsed assuming any siblings following the float do not exist. The float is then placed below that collapsed margin. It is then moved downwards by its own top margin. The float is then ignored, and the normal margin collapse is recalculated assuming the float does not exist, but the subsequent siblings do exist, as described in the paragraph above.

The bottom margin of a float does not take part in any collapsing at all. However, elements that are pushed downwards when they are told to clear the margin of a float (using the clear style), may no longer touch a margin that they normally would, so they will not collapse with it.

If the float contains any non-inline elements that have their own margins, these never collapse with the float's margins.

Other special cases

Elements that have non-visible overflow may take part in margin collapsing with the elements around them, but will not take part in any margin collapsing with any elements inside them.

Further special cases and details of margin collapsing are discussed in the CSS 2.1 specification.

Using borders to produce angled shapes

This is a suppliment to the tutorial, and is here only for illustrative purposes. It is not part of the main tutorial.

These examples will not work in Netscape 4 or WebTV, because they do not allow you to define individual borders, or Escape because it does not handle borders correctly. Internet explorer 4 and 5 may have trouble with some of the examples due to their problems with the box model.

Note that these examples are based on you using the default 'Moosified' style for this page, where the background colour of the body is #f6f6f6. If you use the other styles, the shapes may not work correctly.

Thick borders

A div element with a border

If all four borders are defined as being thick, they should be tapered into each other:

border-top: 20px solid red;
border-bottom: 20px solid #fc0;
border-left: 20px solid blue;
border-right: 20px solid green;

MultiColour Square

All of these examples are done using a <div> element, with no contents:

<div style="style declarations"></div>

The lack of contents makes all points sharp. Some browsers still leave space for the non-existent contents, so we can remove that space by using the following combination of styles:

font-size: 0px; line-height: 0%; width: 0px;
border-top: 20px solid red;
border-bottom: 20px solid #fc0;
border-left: 20px solid blue;
border-right: 20px solid green;

Right side of MultiColour square

If we do not define a border, the other borders stop abruptly, and do not taper into the space that would be used by that border:

font-size: 0px; line-height: 0%; width: 0px;
border-top: 20px solid red;
border-bottom: 20px solid #fc0;
border-left: none;
border-right: 20px solid green;

Top-right corner side of MultiColour square

We get a similar effect by removing two borders:

font-size: 0px; line-height: 0%; width: 0px;
border-top: 20px solid red;
border-bottom: none;
border-right: 20px solid green;

One part of the top-right corner side of MultiColour square

By making one of the two remaining borders the same colour as the background, we are left with a sloping triangle:

font-size: 0px; line-height: 0%; width: 0px;
border-top: 20px solid red;
border-right: 20px solid #f6f6f6;

Or a longer version

Increasing the width makes a longer bar - Note, Microsoft Internet Explorer 4 and 5 take the width as being the full length, including the sloping part, so they cannot display this example. Other browsers take the width as excluding the border, so not the sloping part:

font-size: 0px; line-height: 0%; width: 100px;
border-top: 20px solid red;
border-right: 20px solid #f6f6f6;

Right side of MultiColour square with right border thicker

If we increase the width of the side border, we get a sharper triangle, which is made sharper by being longer:

font-size: 0px; line-height: 0%; width: 0px;
border-top: 20px solid red;
border-bottom: 20px solid #fc0;
border-right: 40px solid green;

Right side of MultiColour square with right border thicker and top and bottom borders thinner

If we decrease the size of the top and bottom borders, we can make the triangle even narrower and sharper:

font-size: 0px; line-height: 0%; width: 0px;
border-top: 10px solid red;
border-bottom: 10px solid #fc0;
border-right: 40px solid green;

Various shapes

By using these various techniques, and setting some of the border colours to the same as the background, we can create a variety of different arrow-based shapes

Down arrow

font-size: 0px; line-height: 0%; width: 0px;
border-top: 20px solid #77c;
border-left: 10px solid #f6f6f6;
border-right: 10px solid #f6f6f6;

Up arrow

font-size: 0px; line-height: 0%; width: 0px;
border-bottom: 20px solid #77c;
border-left: 10px solid #f6f6f6;
border-right: 10px solid #f6f6f6;

Left arrow

font-size: 0px; line-height: 0%; width: 0px;
border-top: 10px solid #f6f6f6;
border-right: 20px solid #77c;
border-bottom: 10px solid #f6f6f6;

Right arrow

font-size: 0px; line-height: 0%; width: 0px;
border-top: 10px solid #f6f6f6;
border-left: 20px solid #77c;
border-bottom: 10px solid #f6f6f6;

Hourglass

font-size: 0px; line-height: 0%; width: 0px;
border-top: 20px solid #77c;
border-left: 10px solid #f6f6f6;
border-right: 10px solid #f6f6f6;
border-bottom: 20px solid #77c;

Sideways hourglass

font-size: 0px; line-height: 0%; width: 0px;
border-left: 20px solid #77c;
border-top: 10px solid #f6f6f6;
border-bottom: 10px solid #f6f6f6;
border-right: 20px solid #77c;

Combining shapes

The div elements can even detect mouse events, so you could use this as a game controller ... just a thought.

This could be done using CSS positioning, but I have used tables here

How about this curve, it is created using the sloping edge technique with stacked floats of various sizes. The length of the div is increased with each float, and the slope is changed by manipulating the thicknesses of the visible bottom and invisible right borders.

Here, the text flows along the edge of the curve in all browsers that can handle borders properly.

Many browsers will float the curve too close to the text so some of the text covers it. To compensate I have included a margin-right style on each div element that increases in lower lines.

Take this for example.

Each line of text floats further and further to the right as is flows down the edge. Most browsers only consider the top-left corner of the text when positioning against the margin, so sharp slopes may still show the problem. Opera considers all parts of the text, so it does not suffer from this.

Using clear, you can place content under the slope, and guarantee it will always be under it, no matter how wide the window gets.

Last modified: 19 March 2011

This site was created by Mark "Tarquin" Wilton-Jones.
Don't click this link unless you want to be banned from our site.