Re: [CSS21] Distinguishing block boxes, block containers, and block-level elements

fantasai wrote:
> CSS2.1 Issue 120
>   http://wiki.csswg.org/spec/css2.1#issue-120
> 
> The approach taken is to define existing terms more precisely, define a
> couple of new terms, and use all of these terms more accurately throughout
> the specification. Errors that were corrected include use of "block-level"
> when "block box" was meant and vice versa, use of "inline-level" when
> "inline box" was meant and vice versa, lists that mistakenly left out
> table-cells or table-captions, and lists that mistakenly left out inline
> blocks or inline tables.
> 
> These changes also make CSS easier to extend with new layout models,
> as they make the text less dependent on specific 'display' values by
> consistently using terms that capture key distinctions in how boxes
> behave.

I think this is an excellent idea (and I've been looking forward to
seeing it since you announced your intention back in October!)  This
approach has the potential to clear up various editorial problems
including element vs box.  It's also, out of necessity, fairly
wide-ranging, and will need careful review.

In this post I'm going to comment on the heart of the issue - namely
Chapter 9, box generation and block/inline formatting contexts – as well
as a few related issues concerning boxes.  (Note that specific responses
to your proposal start a little way further down this post.)  If
necessary, a future post will comment on the knock-on editorial changes
that you put forward to other areas of the spec.


8 (Box model):[1]

   # The CSS box model describes the rectangular boxes that are generated
   # for elements in the document tree and laid out according to the
   # visual formatting model.

Well, it describes some of them.  Is it talking about the marker box of
a list-item, though?  What about various table boxes?

Note that this chapter is reasonably consistent in its use of the term
"box"; we just need to establish precisely which boxes we're talking
about.  Specifically, I think it's talking about inline-level and
block-level boxes in particular, including anonymous boxes.  (The
sections on anonymous boxes explain that properties of anonymous block
boxes are inherited from the enclosing non-anonymous box and that
properties set on elements that cause anonymous block boxes to be
generated still apply to the boxes and content of that element; whilst
anonymous inline boxes inherit inheritable properties from their block
parent box and non-inherited properties have their initial value.)


9.1 (Introduction to the visual formatting model):[2]

   # In the visual formatting model, each element in the document tree
   # generates zero or more boxes according to the box model.

"According to the box model"? The box model chapter doesn't define which
boxes possess a box model; rather, it implicitly defers to this chapter
and hence creates circularity.  (Note that this is one of several issues
raised by Peter Moulder in [3].)


9.2 (Controlling box generation):[4]

   # The following sections describe the types of boxes that may be
   # generated in CSS 2.1. A box's type affects, in part, its behavior in
   # the visual formatting model.

Well, they don't describe list-item marker boxes or table-* boxes.
Indeed, although it's not really called out anywhere, an element can be
neither block-level nor inline-level; it can be a table-*, for example.
  It would be a useful clarification of this section to call that out.

   # The 'display' property, described below, specifies a box's type.

For every possible box?  I suppose so; although the link is often
indirect, which isn't too clear from that sentence.


9.2.1 (Block-level elements and block boxes):[5]

   # Block-level elements are those elements of the source document that
   # are formatted visually as blocks (e.g., paragraphs). Several values
   # of the 'display' property make an element block-level: 'block',
   # 'list-item', and 'run-in' (part of the time; see run-in boxes), and
   # 'table'.

The first sentence sounds like a definition, when in fact it's merely a
vague description of behaviour.  The definition is actually the second
sentence.

This section introduces the concept of a "block-level element".


Now to your proposal.

> Section 9.2.1 Block-level elements and block boxes
> 
>   Replace
> 
>   # Block-level elements (...) generate a principal block box that
>   # contains either only block boxes or only inline boxes. The
>   # principal block box establishes the containing block for descendant
>   # boxes and generated content and is also the box involved in any
>   # positioning scheme. Principal block boxes participate in a block
>   # formatting context.
> 
>   with
> 
>   | Block-level elements generate a principal block-level box that
>   | contains descendant boxes and generated content and is also
>   | the box involved in any positioning scheme.

Is this the definition of a "principal block-level box"?  In particular,
is this the only way that principal block-level boxes can arise?  (See
also [6] where I query in general whether "element" includes
pseudo-elements and/or generated content in sentences such as these.)


>   and append contents of the next paragraph:
> 
>   # Some block-level elements generate additional boxes outside of the
>   # principal box: 'list-item' elements. These additional boxes are
>   # placed with respect to the principal box.
> 
>   Start a new paragraph.

<excuse my splits in the following proposed paragraph>


>   | Except for 'table' elements, which are described in a later chapter,
>   | and replaced elements, the principal block-level box is also a
>   | <dfn>block container box</dfn>.

Note that under your proposal, a table now generates a principal
block-level box, but this is not a block container box.  In the existing
spec, a table explicitly doesn't generate a principal block-level box,
but I think you've exactly captured the required distinction.


>   | A block container box contains either
>   | only block-level boxes or only inline-level boxes.

Hang on, what's a "block-level box"?  This is an important ambiguity.  I
/think/ you intend it to be precisely a principal block-level box or an
anonymous block-level box as described in 9.2.1.1 (Anonymous block boxes).

Note that you haven't really defined "block container box", although you
have described its behaviour.  (I think perhaps these sorts of
definition-by-behaviour-without-classification instances in the
spec should be rewritten, since its usually unclear whether the /only/
elements/boxes which are X are necessarily those mentioned when
describing X's behaviour.) A block container box isn't necessarily a
principal block-level box - nor block-level at all - for example:

>   | Inline blocks, table cells, and table captions are also block
>   | container boxes, but are not block-level boxes.

(I've repositioned this sentence within your paragraph; I think it's
more logical this way.)


>   | Boxes that are
>   | block-level block containers are called <dfn>block boxes</dfn>.

OK.  The term "block box" is more specialized in your proposal than in
the current spec.


>   | Replaced block-level
>   | boxes are considered block boxes, but are not block container boxes.

This directly contradicts the definition!  Hence the definition needs
rewording:

   | A <dfn>block box</dfn> is a block-level box that is either a block
   | container box or the principal block-level box of a replaced
   | element or inline-block.

(Note the addition of inline-block.)


>   | The three terms 'block-level box', 'block container box', and
>   | 'block box' are sometimes abbreviated as 'block' where unambiguous.

Indeed; although I wonder whether the abbreviation has more to do with
the spec not bothering to nail down what is really meant than with lack
of ambiguity. ;-)


> Section 9.2.1.1 Anonymous block boxes
> 
>   # In other words: if a block box (such as that generated for the DIV
>   # above) has another block box or run-in box inside it (such as the P
>   # above), then we force it to have only block boxes and run-in boxes
>   # inside it.
> 
>   s/another block box or run-in box/a block-level box/
>   s/only block boxes and run-in boxes/only block-level boxes/

Also s/if a block box/if a block container box/, no?  The block
container box for an inline-block is inline-level and yet we still
expect it to have the above behaviour, by definition.


>   # When an inline box contains a block box, the inline box (and its
>   # inline ancestors within the same line box) are broken around the
>   # block. The line boxes before the break and after the break are
>   # enclosed in anonymous boxes, and the block box becomes a sibling
>   # of those anonymous boxes. When such an inline box is affected by
>   # relative positioning, the relative positioning also affects the
>   # block box.
> 
>   s/block/block-level/g

Also:

s/around the block/around the block-level box/

(Brevity here just creates confusion.)

And:

s/enclosed in anonymous boxes/enclosed in anonymous block boxes/

("block boxes" is correct here because these anonymous boxes are both
block-level and block container boxes, the former by assumption above
and the latter by my assumption in [7].)


> Section 9.2.2 Inline-level elements and inline boxes
> 
>   # Several values of the 'display' property make an element inline:
> 
>   s/inline/inline-level/
> 
>   # 'inline', 'inline-table', 'inline-block' and 'run-in' (part of
>   # the time; see run-in boxes). Inline-level elements generate
>   # inline boxes.
> 
>   Replace "inline boxes" with "inline-level boxes, which participate
>   in an inline formatting context".

Does this mean that /all/ boxes generated by an inline element are
"inline-level"?  As above for "block-level box", "inline-level box" does
not seem well defined, or rather it's defined (below) but the
classification is vague.  /How/ does an inline-level element generate
inline boxes?  How many of them are there?  (Presumably, the minimum
number possible whilst obeying the requirements for box generation in
the spec, bearing in mind things like breaking across different line
boxes and around block-level boxes.)

This section introduces the concept of a "inline-level element".


>   Append a new paragraph:
> 
>   | An <dfn>inline box</dfn> is one that is both inline-level and whose
>   | children (if any) would participate in its containing inline formatting
>   | context. For non-replaced elements, a 'display' value of 'inline' and
>   | sometimes 'run-in' (when it is not creating a block box) generates an
>   | inline box. Inline-level boxes that are not inline boxes (such as
>   | replaced inline elements, inline-block elements, and inline-table
>   | elements) are called <dfn>atomic inline boxes</dfn> because they
>   | participate in their inline formatting context as a single opaque box.

I don't understand the first sentence, largely because of the "would".
You're trying to exclude things like inline-blocks from generating an
inline box, so it goes hand-in-hand with the following sentences, right?
Does this also exclude replaced inline-level elements, or are they
covered by the "no children" part?  (The case for replaced block-level
elements was more explicit in your changes further up.)


I'm pretty sure by this point that your use of "inline-level box" and
"block-level box" refers to the "outward-facing behaviour" of the boxes,
whereas "inline box" and "block box" refers to the "inward-facing
behaviour".  For example, inline-blocks behave like inlines on the
outside but like blocks on the inside.  I like your attempt to capture
this notion, and it seems to echo various discussions on this list
(often related to higher-level discussion about layout managers and the
like).  I think it'll turn out to be fundamentally useful for future CSS
development to lay the groundwork here.


> Section 9.4 Normal flow
> 
>   # Block boxes participate in a block formatting context. Inline boxes
>   # participate in an inline formatting context.
> 
>   s/Block boxes/Block-level boxes/
>   s/Inline boxes/Inline-level boxes/
> 
> Section 9.4.1 Block formatting contexts
> 
>   Replace
> 
>   # Floats, absolutely positioned elements, inline-blocks, table-cells,
>   # table-captions, and elements with 'overflow' other than 'visible'
> 
>   with
> 
>   | Floats, absolutely positioned elements, block containers (such as
>   | inline-blocks, table-cells, and table-captions) that are not block
>   | boxes, and block boxes with 'overflow' other than 'visible'

Fine.  Note that the next paragraph immediately uses the terms "block
box" and "box" interchangeably, which is valid since 9.4 states that
block boxes participate in a block formatting context, whilst inline
boxes participate in an inline formatting context.  However, I think
it's clearer to be more careful there.  Similarly for 9.4.2.


> Section 9.4.2 Inline formatting context

<snip>

>   # When an inline box exceeds
> 
>   s/an inline/a non-replaced inline/

See my comment above; is the generated inline-level box of a replaced
inline-level element also an inline box?


> Section 10.1 Definition of "containing block'

<snip>
list item 4.1 says:

>   # In the case that the ancestor is inline-level
> 
>   s/inline-level/an inline box/

Yes, I think this is correct.  In the case that the ancestor is an
inline-block or inline-table, for example, we intend 10.1.4.2 to apply.


[1] http://www.w3.org/TR/CSS2/box.html
[2] http://www.w3.org/TR/CSS2/visuren.html#visual-model-intro
[3] http://lists.w3.org/Archives/Public/www-style/2010Jul/0113.html
[4] http://www.w3.org/TR/CSS2/visuren.html#box-gen
[5] http://www.w3.org/TR/CSS2/visuren.html#block-boxes
[6] http://lists.w3.org/Archives/Public/www-style/2010Jul/0438.html
[7] http://lists.w3.org/Archives/Public/www-style/2010Jul/0439.html

Cheers,
Anton Prowse
http://dev.moonhenge.net

Received on Sunday, 25 July 2010 12:47:42 UTC