W3C home > Mailing lists > Public > www-style@w3.org > December 1999

Line boxes

From: Matthew Brealey <thelawnet@yahoo.com>
Date: Mon, 6 Dec 1999 06:45:25 -0800 (PST)
Message-ID: <19991206144525.27894.qmail@web906.mail.yahoo.com>
To: www-style <www-style@w3.org>
1.

One area of the existing specification that I believe
is poorly described is that of the vertical box model
properties on inline elements.

Although margin-left, margin-right, etc., are obvious,
vertical margins are less so.

For example, the picture 
http://www.w3.org/TR/REC-CSS2/images/inline-layout.gif
doesn't seem to be right, since the text isn't centred
in the line box, the border goes outside of the line
box, margin-left and margin-right only are applied,
even though the property used is margin, which sets
all four margins, and padding-left and padding-right
only are applied, even though the property used is
padding, which sets all four sides.

I would say that to resolve the difficulties (and
believe me, there are difficulties), the direct
consequence of which has been buggy support in
browsers, relating to vertical box model properties,
the 

margin-top simply adjusts the height of the top line
box, and margin-bottom the bottom line-box, and
border-top and border-bottom adjust the height of the
line box in the same way, but only apply the border
around the element.

Conversely, horizontal box model properties (e.g.,
border-left) are placed normally within the box.

E.g.,

<p style="font: 12pt/14pt sans-serif; background:
blue; color: black>
<pseudo title="element signifying that the enclosed
text represents one line">
This is <span style="line-height: 18pt">line 1</span>
</pseudo>
<pseudo title="element signifying that the enclosed
text represents one line">
This is <span style="margin-top: 5pt;">line 2</span>
</pseudo>
<pseudo title="element signifying that the enclosed
text represents one line">
This is <span style="margin-top: 5pt; background:
red">line 3
</pseudo>
<pseudo title="element signifying that the enclosed
text represents one line">
This is</span> line 4
</pseudo>
<pseudo title="element signifying that the enclosed
text represents one line">
This is <span style="border: 5pt solid">line 5
</pseudo>
<pseudo title="element signifying that the enclosed
text represents one line">
This is</span> line 6
</pseudo>
<pseudo title="element signifying that the enclosed
text represents one line">
This is <span style="border: 5pt solid; margin: 2pt;
padding: 10pt; background: red">line 7
</pseudo>
<pseudo title="element signifying that the enclosed
text represents one line">
This is</span> line 8
</pseudo>
</p>

In this example, line box 1 would be 18pt high, line
box 2 would be 14pt high, but would appear to the
naked eye to be 19pt high. In actual fact, it would be
also be 14pt high, but the 5pt would be applied to the
whole line box.
Line boxes 3 and 4 would also be 14pt high, but line
boxes 3 and 4 would both have 5pt margin-tops (this is
because if you just apply the 5pt to the inline
element, either the line box above would be overlapped
or the content would be obscured, or something equal
undesirable). Obviously, the red background would only
be applied to the content.
Line boxes 5 and 6 would have 14pt high, but 5pt of
space would be added above and below them, and the
border would be drawn as normal around the content.
As a result, the distance between the top of the
border and the top of the inline box would be the same
as what the distance would be between the top of text
and the top of the line box if the border wasn't
there.

Line boxes 5 and 6 would not have a height of 14pt and
a border-top 5pt - the border should be placed next to
the top of the text, not next to the top of the line
box.

Line boxes 7 and 8 would be 14pt + 10pt above + 10pt
below = 34pt high (i.e., padding is applied to
increase line-height), and there would be 5pt + 2pt =
7pt above and 7pt below the line box.

As a result, the line box's 'effective height' would
be 48pt.

The border would be applied above the content, in the
5pt of space above the top and below the bottom of the
line box (height 34pt). All 48pt of effective height
on both lines would be blue, with the exception of the
34pt around the SPAN box, which would be red, and the
border, which would be black (since border-color's
initial value is color's value = black).

This would make Opera's approach, whereby large
borders increase the line box height, but the borders
run into each other, wrong.

<q cite="http://www.w3.org/TR/REC-CSS2/visuren.html">
Line boxes are stacked with no vertical separation and
they never overlap.
</q>

I would say not, e.g., because of margins

2. HEADING: Positioning of text within line boxes
[apologies if this overlaps with the previous thread,
but it was getting a bit unwieldy]

To consider it logically:

line-height: whatever is the one thing that we have a
fixed definition for.

Therefore, all we need to do is draw the line box, and
once we have done that place the text within it.

I believe that we should be taking a line-box-oriented
approach, since given font-size: 18px, line-height: 1,
the line box is 18px high, which is easily done.

Now that we have a line box, whose height is fixed, we
can use this as a foundation to place the text within
it.

To do this, we work out where the baseline should be
relative to the bottom of the line box, and place the
text on this.

Although some fonts will have glyphs that are larger
than their font-size, it is not our role to consider
this - this is for the font vendors to consider.

However, there are some things that it is within our
grasp to decide. The main criteria are:

1. that the text appears centred within the line box
2. that the chance of overlapping at 'set solid' text
(i.e., font-size: 1/1em/100%) is minimised
3. that the baseline HAS to be a constant distance
above the bottom of the line box for a given
vertical-align, regardless of font-size 

Therefore:
Proposal A: should the baseline be line-height/2 above
the bottom of the line box?

I would say not, since the text should appear to be
centred in the box, but with this proposal, it is not
done so (since the baseline is centred, whereas we
actually want the middle of the text to be centred).

Conclusion: REJECT

Proposal B: 
Possibly the baseline could be aligned with
line-height/2 - x-height, since would have the
advantage of favouring a position nearer the bottom of
the line box (look at 'x' and then look at 'l'), which
seems to be better than one too far up.

However, this will result in glyphs that are larger
than x-height overflowing [2] the line box.

Conclusion: REJECT

Proposal C:
Apply (line-box-height - font-size)/2 as the distance
between the bottom of the line box and the baseline.

This is the option that Opera adopts (try 
<p style="line-height: 1; background: red /* must be
different from rest of document */>
Something quirky.
</p>

Since the baseline is at the bottom of the line box
(since l = 1*f, and (f -f) /2 = 0, the descenders are
not covered by the background (well some of them are
due to internal leading [3]).

This is clearly unsatisfactory - there is too much
space on top of the font, and not enough underneath
it, so:

Conclusion: REJECT


Proposal D:

An equation that seems initially attractive is:

bottom of line box to baseline = (linebox-height -
max-x-height-in-that-line-box)/2 +
(max-descent-in-that-line-box), where x-height and
descent represent the actual values for the font's
calculated value for font-size, rather than those
native to the font.

This equation satisifes the biggest concern, namely
that the bottom of the text does not go outside the
bottom of the line box.

For example, given a line box whose max-x-height was
7pt, whose max-descent was 3pt, and whose
linebox-height was 15pt, the baseline would be placed
(15pt - 7pt)/2 + 3pt = 7pt from the bottom of the line
box.

However, if ascent > 8pt, as it is likely to be, the
font will overflow the line box, so:

Conclusion: REJECT

Proposal E:

Given instead:
bottom of line box to baseline = (linebox-height -
max-font-size-in-that-line-box)/2 +
(max-descent-in-that-line-box)

For example, given a line box whose font-size was
15pt, whose max-descent was 3pt, and whose
linebox-height was 15pt, the baseline would be placed
(15pt - 15pt)/2 + 3pt = 3pt from the bottom of the
line box.

Refined somewhat, this seems the best equation:

bottom of line box to baseline =
(max-line-height-in-line-box (NB, not line-box-height,
since this might be increased by inline replaced
elements) - max-font-size-in-that-line-box)/2 +
(max-descent-in-that-line-box), since this can never
result in normal glyphs overflowing their line box. 

e.g., given P {line-height: 1; font-size: 12pt}
SPAN.inlinetoP {font-size: 24pt}, h = 24pt, f = 24pt,
_if_ (i.e., this is only true if the font is one that
doesn't create glyphs that are larger than the
requested font-size)
f >= a + d, glyphs can only overflow their line box if
bottom of line box to baseline + a > f ( i.e., a + d),
so (h - f)/2 + a + d > a + d, i.e., since h = f at
line-height: 1em (i.e., at the minimum size you'd
expect not to overlap), so  (f - f)/2 + a + d > a + d,
i.e., 0 > 0, which is never true, so this equation
never results in overlaps for unaccented glyphs, and
never for accented glyphs either if you re-define
ascent as maximum accented height.

This caters perfectly for vertical-align: sub, super
and percentages as well

[Incidentally, the spec needs to state (to avoid the
absurdity of browsers (Opera, at least) increasing
line-height to cater for vertical-align):
<blockquote>
UAs should apply vertical-align: sub as
vertical-align: -nn%, where nn% is a UA-determined
percentage.
UAs should apply vertical-align: super as
vertical-align: nn%, where nn% is a UA-determined
percentage that should be the same as that used for
sub.

When a percentage specified is greater than that which
can be fitted in the line box, the UA
should clip it to a value that can.

For example, given line-box-height: 1.2em;
vertical-align: 15%, the vertical-align should be
clipped to 10%, since there is only 10% of space that
the text can be moved within the line box.

Equally for sub and super - if a UA normally applies
10%, but there is only room for 5%, 5% is what it
should apply.
</blockquote>

Thus also needed is :
if calculated value for vertical-align > 0 {
if ( ( (max-line-height-in-line-box -
current-font-size)/2 + (calculated value for
vertical-align) ) > (font-size - curent-descent) [=
ascent] ) {
calculated value for vertical-align =
(max-line-height-in-line-box - current-font-size)/2
}
}
and:
if calculated value for vertical-align < 0 {
if ( ( (max-line-height-in-line-box -
current-font-size)/2 +
calculated-value-for-vertical-align  [i.e., +
-whatever = -whatever] + current-descent <
current-descent ) ) {
calculated value for vertical-align =
-((max-line-height-in-line-box - current-font-size)/2)
}
}
i.e.,
if calculated value for vertical-align < 0 {
if ( ( (max-line-height-in-line-box -
current-font-size)/2 +
calculated-value-for-vertical-align  < 0 ) ) {
calculated value for vertical-align =
-((max-line-height-in-line-box - current-font-size)/2)
}
}
]
,
since given, e.g., line-height: 20px, font-size: 14px,
and descent = d, then 
bottom of line box to baseline = (20px - 14px)/2 +
(max-descent-in-that-line-box) + .1*20 (assuming 10%
as the value for %), = 3.5px + d + 2 = 5.5pt, which
will fit in the line box perfectly.

Here's the equation with vertical-align included:
bottom of line box to baseline =
(max-line-height-in-line-box -
max-font-size-in-that-line-box)/2 +
(max-descent-in-that-line-box) +
calculated-value-for-vertical-align

By adopting this baseline approach, all the problems
are solved, since all we need to do is draw a box,
calculate the distance to the baseline, and place the
glyphs on the baseline - we don't need to bother with
any of the font's characteristics except for descent,
and the quoted value for font-size - if a glyph is
placed on the baseline and it overlaps because it has
many accents, so be it.

In addition, vertical-align is easier to implement
following this approach.

Footnotes:
1. This approach would not be appropriate for all
alphabets.
2. Overflow  - not overlap.
3. Not relevant, all we need to do is calculate the
size of the line box, and place the text of the
requested size on the baseline - internal leading is
not our concern.

=====
----------------------------------------------------------
From Matthew Brealey (http://members.tripod.co.uk/lawnet (for law)or http://members.tripod.co.uk/lawnet/WEBFRAME.HTM (for CSS))
__________________________________________________
Do You Yahoo!?
Thousands of Stores.  Millions of Products.  All in one place.
Yahoo! Shopping: http://shopping.yahoo.com
Received on Monday, 6 December 1999 09:45:27 GMT

This archive was generated by hypermail 2.2.0+W3C-0.50 : Monday, 27 April 2009 13:54:01 GMT