How to build an Acid Test
In this article I'll explain how to build an Acid Test on a CSS feature. The test will focus on the box model. We start from the following picture:
Figure 1. A smiling face
The result we want to achieve is the following:
Figure 2. The reference image
Table of contents
- The markup
- Positioning and initial formatting of the face
- The top of the face
- The forehead of the face
- The eyes
- The most part of the face
- The smile of the face
- The final section of the face
- Download examples
The markup
When providing a test that will be used by browsers vendors, there are some simple rules to follow before writing down our markup. Let's start by viewing a prototype of a test page.
Listing 1. Page format for a test
<?xml version="1.0" encoding="utf-8"?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><title>CSS 2.1 Test Suite: Acid Test on the box model </title><link rel="author" title="Gabriele Romanato" href="mailto:gabriele.romanato@gmail.com"/><link rel="help" href="http://www.w3.org/TR/CSS21/box.html"/><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><meta name="flags" content="Valid" /><meta name="assert" content="UA should support the specified properties"/><style type="text/css" media="screen"></style></head>...omission...
Some considerations:
- The markup must be valid and should have an XML prolog.
- The title of the page should be self-evident and clear.
- The
linkelements must provide two kinds of information:- the author of the test (email or contact page)
- the relevant section of the specifications that's being tested.
- The
metaelements must provide two kinds of information:- the type of the test (Flags)
- what User-Agents (browsers) must do to pass the test (Assert).
- The relevant styles should be embedded in the page itself.
Furhermore, the test should be provided in two different formats: application/xhtml+xml (XHTML 1.1) and
text/html (XHTML 1.0).
Positioning and initial formatting of the face
Our image is virtually divided into 15 rows, since its original dimensions are 150 x 150 pixels. So we're going to format one row per time, after setting the global dimensions of the main container.
Listing 2. Positioning and initial formatting of the face
#face {font-size: 10px;width: 15em;margin: 2em auto;background: white;color: black;}.row {margin: 0;}
We've set a font size of 10 pixels so that 15em will be equal to 150 pixels. Then we've centered the face on the page through its horizontal automatic margins.
The top of the face
Since we're working with the box model, we won't use any declaration of width or height. Instead, we'll use only margins, padding, and borders to create our face. Here are the first styles:
Listing 3. The top of the face
#top {margin-left: 5em;margin-right: 5em;background: black;padding: 0.5em 0;}
Our box will have a width of 5em, since it has its horizontal margins set to 5em (so 15em - 5em - 5em = 5em). Since we don't use an explicit height here, we have to set some vertical padding to make the background color appear. Our rows should be 1em high, so we set the vertical padding to 0.5em.
The forehead of the face
The following three boxes draw the forehead of our face.
Listing 4. The forehead of the face
#forehead-1 {margin-left: 3em;margin-right: 3em;background: yellow;padding: 0.5em 0;border-left: 2em solid black;border-right: 2em solid black;}#forehead-2 {margin-left: 2em;margin-right: 2em;background: yellow;padding: 0.5em 0;border-left: 1em solid black;border-right: 1em solid black;}#forehead-3 {margin-left: 1em;margin-right: 1em;background: yellow;padding: 0.5em 0;border-left: 1em solid black;border-right: 1em solid black;}
The technique is very similar to the one above. The only difference here is that we've used horizontal borders to draw the outline of the face.
The eyes
The styles for the eyes allows us to use also negative margins, as shown below.
Listing 5. The eyes
#forehead-4 {margin-left: 1em;margin-right: 1em;background: yellow;padding: 0.5em 0;border-left: 1em solid black;border-right: 1em solid black;}#eyes-1 {margin-left: 2em;margin-right: 2em;border-left: 2em solid black;border-right: 2em solid black;padding: 0.5em 0;}#head-1 {background: yellow;padding: 0.5em 0;border-left: 1em solid black;border-right: 1em solid black;}#eyes-2 {margin-left: 3em;margin-right: 3em;border-left: 2em solid black;border-right: 2em solid black;padding: 0.5em 0;margin-top: -1em;}
We've used a negative top margin to fix a side effect of the vertical padding used on each element. In fact, since the box that draws the second row of the eyes is contained inside another element, we have a gap of 1em, that is, the sum of the padding of the parent and its in-flow child.
The most part of the face
The following styles are really simple:
Listing 6. The most part of the face
#head-2, #head-3, #head-4 {background: yellow;padding: 0.5em 0;border-left: 1em solid black;border-right: 1em solid black;}
Again, we've used horizontal borders to draw the outline of the face.
The smile of the face
The tecniques described below are very similar to those used for the eyes.
Listing 7. The smile of the face
#head-5 {background: yellow;padding: 0.5em 0;border-left: 1em solid black;border-right: 1em solid black;}#smile-1 {margin-left: 2em;margin-right: 2em;border-left: 1em solid black;border-right: 1em solid black;padding: 0.5em 0;}#head-6, #head-7 {background: yellow;padding: 0.5em 0;margin-left: 1em;margin-right: 1em;border-right: 1em solid black;border-left: 1em solid black;}#smile-2 {margin-left: 2em;margin-right: 2em;border-left: 1em solid black;border-right: 1em solid black;padding: 0.5em 0;margin-top: -1em;}#smile-3 {margin-left: 3em;margin-right: 3em;padding: 0.5em 0;background: black;margin-top: -1em;}
We've used again negative margins to fill the gap caused by the vertical padding used on each element. The smile is actually made up of three different nested boxes per single row.
The final section of the face
We use some of the styles just seen above.
Listing 8. The final section of the face
#head-8 {margin-left: 2em;margin-right: 2em;padding: 0.5em 0;background: yellow;border-left: 1em solid black;border-right: 1em solid black;}#head-9 {margin-left: 3em;margin-right: 3em;padding: 0.5em 0;background: yellow;border-left: 2em solid black;border-right: 2em solid black;}#bottom {margin-left: 5em;margin-right: 5em;background: black;padding: 0.5em 0;}