January 2007

Back to the project

Summary

Opera 9.0 font inheritance test

Abstract

A couple of months ago Opera 9 was released with high expectations. Indeed it was a big step towards a full compatibility with the CSS standard. However, the new release had some problems that had to be solved. Among them, the font inheritance problem was one of the most discussed.

The problem

This problem is related to Opera 9.0. Opera 9.02, for istance, seems to have solved it. Basically Opera 9 has a user preference called "Fonts" (Tools > Advanced > Fonts), which contains a set of font families for every single element of a web page (see the image). These are default settings that may be changed according to user's preferences. The problem concerns the value propagation mechanism used by CSS, the inheritance. For example:

body {font-family: Arial, sans-serif;}

According to CSS specs, every textual element in that page should be rendered with an Arial font face. But as we can see in the first test, Opera 9.0 displays the headings with a serif face. That's due to the default setting in the "Font" preferences section mentioned above, where the headings are displayed with a serif font face.

In the second test I've also declared the following:

 h1, h2, h3, h4, h5, h6 {margin: .70em 0;}
 

This declaration is used to create an instance of elements in the style sheet without setting their font family explicitly. It doesn't work. So, only for Opera 9.0, a good solution is:

h1, h2, h3, h4, h5, h6 {font-family: Arial, sans-serif;}

Posted by Gabriele Romanato

Conjectures on Internet Explorer

Weird calculations

On July 25, 2005, Chris Wilson wrote:

In IE7, we will fix as many of the worst bugs that web developers hit as we can, and we will add the critical most-requested features from the standards as well.

The bug list is well-known:

For further details see PIE.

These bugs are intended to occur only in certain conditions. But in a complex layout these conditions seem to be related to unpredictable variables that cannot be calculated in advance. The result is evident: the above list can continue ad infinitum, adding each time a new variable to an open set of conditions.

For example, in a page like this we can see some of these variables in action:

An example:

h1 {
 text-align: left;
 text-indent: -33%;
 margin: 2.4em 0 4.5em 0;
 font-weight: 900;
}

/* For WinIE: */
div h1 {text-indent: -7.5em}

/* For others: */
div>h1 {text-indent: -33%}

Here a value of -33% set on the 'text-indent' property makes (literally) the text within the H1 element disappear from the viewport in IE. The descendant selector is then used to fix the problem in IE/Win.

However, another problem still rises: IE7 will be able to understand the last rule, where the child selector is used to resume the original value for non-IE browsers. What happens next? The conflict between ems and percentages ends with the last rule, that finally sets the value on the 'text-indent' property.

Will Trident be able to create the corresponding formatting structure without problems in the presentational process? This is a difficult question. The page mentioned above contains a layout architecture which is simple only at a first sight. The inner structure is more complex for a browser. For example:

html {
 margin: 0 0 0 1em;
}

body {
 text-align: justify;
 text-indent: 0;
 margin: 1em 2em 1em 25%;
 line-height: 1.3;
}

As we can see, the value of the 'text-indent' property (-33%) is greater than the corresponding value set on the 'margin-left' property (25%) for the BODY element. There is a gap equal to 8%. The 'text-indent' property

specifies the indentation of the first line of text in a block. More precisely, it specifies the indentation of the first box that flows into the block's first line box. The box is indented with respect to the left (or right, for right-to-left layout) edge of the line box. User agents should render this indentation as blank space.

What's more,

The value of 'text-indent' may be negative, but there may be implementation-specific limits. If the value of 'text-indent' is either negative or exceeds the width of the block, that first box, described above, may overflow the block. The value of 'overflow' will affect whether such text that overflows the block is visible.

(The boldface is mine)

A width for the block (H1) has not been specified, neither for the H1's containing block. A standard compliant browser will calculate the percentage correctly, since the implicit 'width: auto' declaration has a well-defined meaning for it. But IE will shift the text outside the viewport, according to PIE's definition of "dimensional bug", here applied to the particular case of negative indentation.

Usually we assume that the only properties involved in the positioning process are 'float' and 'position'. This is not actually true. Properties like 'text-indent' (for line boxes inside a block box) or 'margin' (for block boxes) can either affect the positioning of page elements. For example, what about negative margins? In the page mentioned above we can find the following:

.Sidenote {
 text-align: left;
 text-indent: 2em;
 float: left;
 width: 30%;
 margin: 0 0 0 -33%;
 font-size: smaller;
}

/* For WinIE: */
div .Sidenote {
 margin-left: -16.7em;
 width: 15em;
}

/* For others: */
div>.Sidenote {
 margin-left: -33%;
 width: 30%;
}

Here's a lethal mix for IE: floating, negative margins and percentages. The above code is used to create side notes (or "marginalia" in Latin), a common typographical effect. To be honest, there is nothing else to add to the neverending list of IE's problems related to floating. However, the "floating issue" deserves some discussion.

Here the 'float' property is affected by the 'margin-left' property, which is set on a negative value. Note that the value is greater than the corresponding value set on the BODY element. Eric Meyer uses the following example in his famous guide:

img.sideline {
 float: left;
 margin: 10px -15px 10px 10px;
}

p.box {
 border: 1px solid gray;
 padding: 0.5em;
}
p.box strong {
 border: 3px double black;
 background: silver;
 padding: 2px;
}

h2#jump-up {
 margin-top: -15px;
 background: silver;
}

The overlapping of adjacent elements doesn't occur in our case. Simply, IE fails because it is not able to calculate the correct ratio between a containing block and its floated child, when the containing block has no explicit declaration for the 'width' property, and the floated child has a width expressed in percentages. In other words, if the markup is

<p>Text <span class="Sidenote">Side text</span></p>

and the width of the SPAN element is equal to 30% of its parent, what is the width of the P element? The width of the P element is established by its ancestor, namely a DIV without an explicit dimension. At the top of the ladder we find the BODY element, with its 'margin-left' property set on 25% (not counting the left margin of the HTML element). Weird calculations or veritable mystery?

Posted by Gabriele Romanato

Default style sheet

The default style sheet for HTML elements used by Firefox 1.5 is contained in its source code, more precisely in the folder /style. The following table summarizes the differences between Firefox 1.5 and CSS 2.1 specs.

Element(s) Firefox 1.5 CSS 2.1
blockquote 'margin: 1em 40px' 'margin: 1.12em 40px'
p, dl 'margin: 1em 0' 'margin: 1.12em 0'
h1...h6 'font-weight: bold' 'font-weight: bolder'
h2 'margin: .83em 0' 'margin: .75em 0'
h3 'margin: 1em 0' 'margin: .83em 0'
h4 'margin: 1.33em 0' 'margin: 1.12em 0'
h5 'margin: 1.67em 0' 'margin: 1.5em 0'
h6 'font-size: 0.67em'
'margin: 2.33em 0'
'font-size: .75em'
'margin: 1.67em 0'
pre 'font-family: -moz-fixed' 'font-family: monospace'
td 'padding: 1px' 'padding: not specified'
tt, code, kbd, samp 'font-family: -moz-fixed' 'font-family: monospace'
big 'font-size: larger' 'font-size: 1.17em'
small, sub, sup 'font-size: smaller' 'font-size: .83em'
sub, sup 'line-height: normal' 'line-height: not specified'
ul, ol 'margin: 1em 0' 'margin: 1.12em 0 1.12em 40px'

For ordered and unordered lists, Firefox uses the following declaration:

ul, ol {-moz-padding-start: 40px}

In Firefox are specified the 'list-style-type' values for 2 and 3 (or more) deep unordered lists, 'circle' and 'square', respectively.

Coming to Internet Explorer, things are much more complicated, since the default style sheet is hardcoded in the program itself.

In IE6, the version we will take as reference, there is a "mysterious" entry in the Windows registry named Styles, located under the key HKEY_LOCAL_MACHINE\Software\Microsoft\Internet Explorer. This key contains a REG_BINARY value, named Count_Style_Sheets, plus a default REG_SZ value, which content is not visible.

Is this key related to the default style sheet of IE? Only MS developers know how things really are. Thus, we should follow the Galilean method, making some attempts to find an hypothetical default style sheet for IE.

We will follow the order showed in the table above, comparing the values found in Firefox 1.5 default style sheet with the hypothetical values used by Internet Explorer (version 6). Specifically, we will focus our attention on block-level elements.

body

This element is not reviewed in the table above, but it is still useful as a starting point. According to its default style sheet, Firefox 1.5 uses the declaration 'margin: 8px' for the BODY element. In this page has been applied 'body {padding: 0}' to test the declaration mentioned above. IE6 uses also the 'margin' property on BODY, but with different results (see the screenshots): the value is greater than 8px, at least for the 'margin-top'/'margin-bottom' properties. It is clear that the value may change when we set a different font on the BODY element. Without any style declaration, results are the same as descripted above.

blockquote

For this element Firefox 1.5 uses the declaration 'margin: 1em 40px'. In this page the BODY element has both margins and padding set to 0. The BLOCKQUOTE element has the (redundant) declaration 'padding: 0', used to test the declaration mentioned above. IE6 uses also the 'margin' property on BLOCKQUOTE, but with different results (see the screenshots): the horizontal space is quite the same, but the vertical space appears collapsed on top. I've noticed that removing the padding declaration on BLOCKQUOTE, the vertical space remains collapsed on top. Result remains the same even if we switch from a Transitional to a Strict DOCTYPE. It is clear that values may change when we set a different font on the BODY element. Without any style declaration, there is no difference between Firefox 1.5 and IE6.

p, dl

For these elements Firefox 1.5 uses the declaration 'margin: 1em 0'. In this page the BODY element has both margins and padding set to 0. The P and DL elements have the (redundant) declaration 'padding: 0', used to test the declaration mentioned above. IE6 uses also the 'margin' property on the two elements, but with different results (see the screenshots): the horizontal space is quite the same, but the vertical space remains collapsed on top. I've noticed that removing the padding declaration on P and DL, the vertical space remains collapsed on top. Result remains the same even if we switch from a Transitional to a Strict DOCTYPE. It is clear that values may change when we set a different font on the BODY element. Without any style declaration, there is no difference between Firefox 1.5 and IE6.

h1, h2, h3, h4, h5, h6

For these elements Firefox 1.5 uses the following declarations:

There is no declaration for the H1 element, so our guesses are much more complicated. In this page the BODY element has both margins and padding set to 0. The H1...H6 elements have the (redundant) declaration 'padding: 0', used to test the declaration mentioned above. IE6 uses also the 'margin' property on the elements, but with different results (see the screenshots): the horizontal space is quite the same, but the vertical space remains collapsed on top. I've noticed that removing the padding declaration on H1...H6 elements, the vertical space remains collapsed on top. Result remains the same even if we switch from a Transitional to a Strict DOCTYPE. It is clear that values may change when we set a different font on the BODY element. Without any style declaration, there is no difference between Firefox 1.5 and IE6.

td

For this element Firefox 1.5 uses the declaration 'padding: 1px'. In this page the BODY element has both margins and padding set to 0. The TABLE and TD elements have the (redundant) declaration 'margin: 0' used to test the declaration mentioned above. Also, we've declared 'border: 1px solid' for the TABLE and TD elements. Results look similar in both browsers (see the screenshots): also IE6 seems to apply padding on the TD element. What's more, IE6 accepts the 'border-collapse' property, which its default value is set on separate for the TABLE element. Since we've not specified a color for the TABLE border, IE6 applies its default value, which is probably related to a sistem color. Without any style declaration, there is still no difference between Firefox 1.5 and IE6.

'list-style-type' for nested lists

In Firefox are specified the 'list-style-type' values for 2 and 3 (or more) deep unordered lists, 'circle' and 'square', respectively. This page shows that also IE6 applies the same declarations (as you can see in the screenshots). The page has no style declaration. For 2 and 3 (or more) deep ordered lists, the values are always set on 'decimal'. Without any style declaration, there is no difference between Firefox 1.5 and IE6.

Posted by Gabriele Romanato