[CSS21] 10.1: Issues with "containing block"

On Fri, Oct 22, 2010 at 06:42:39PM +1100, Alan Gresley wrote:

> >>s/containing block's right edge/containing block's right content edge/
> >
> >No, no.  The containing block doesn't have a "content edge"; it's
> >a rectangular region.
> 
> 
> If you say this, then you still do not understand what a containing
> block is. I'm only talking about the change to rule 3 at this
> moment. The containing block (rectangular region) is formed by the
> content edge. In 10.1 we have.
> 
>   | 2. For other elements, if the element's position is 'relative'
>   | or 'static', the containing block is formed by the content edge
>   | of the nearest block-level, table cell or inline-block ancestor
>   | box.

[Preface warning: it's now way past my bedtime, and I haven't re-read what
 follows; hopefully you can work out what I mean to say if I've mangled
 something.]

I haven't yet noticed a possible interpretation consistent with the above, but
on the other hand the text in the current spec does seem a little contradictory
about what the containing block is.  (I suspect that this is something that has
changed over time, or something where different spec writers have different
mental models of what it is.)

I think that it's a problem if some people think that the containing block has
a distinct content edge, border edge and margin edge: I'm concerned that this
may result in mis-guessing what "the width (or height) of the containing block"
means.

My own understanding is that what we want the containing block to be is
a tuple of:

  - a rectangle (axis-aligned, and whose width may be negative); and

  - a 'direction' value (i.e. either 'ltr' or 'rtl').  
    (In particular, it is just a single value, there is no distinct specified value,
    computed value etc.)

I should also note that my understanding is that the containing block is to be
a property of boxes, not of elements, and that the containing block is defined
in terms of box tree parents rather than element tree parents.  For example, if
an element is display:list-item list-style-position:inside, then by my
understanding, that element generates two boxes with different containing
blocks.  The following also assumes that we want the containing block of the
box of a display:block element whose parent is display:table-row to be based on
the anonymous table-cell box rather than whatever the closest ancestor element
of appropriate 'display' value.  The following also assumes that the box tree
is such that float boxes are "in tree", i.e. that the parent box of a float box
is the principal box of the parent element of the float element.  Also
questionable in the below is the use of the phrase "root box" as shorthand for
"the principal box of the root element", whereas in fact CSS2.1 doesn't fully
define box "family relationships", and leaves open the possibility that boxes
don't form exactly a tree with just a single root box.  More generally, the
fact that "parent box" isn't currently well defined in CSS2.1 is a problem for
expressing these rules in terms of boxes (a concern Bert Bos raised recently).
A number of other things in CSS2.1 are defined in terms of box relationships, 
so either these will all need changing to be in terms of element tree, or we
need to define those box relationships, i.e. define the box tree (if indeed it
is a tree).

The above assumptions still leave open the possibility of describing things in
terms of the element tree, whether normatively (taking care with run-ins and so
on) or informatively.  For simplicity of discussion within www-style, the below
gives only the box-based descriptions.

Based on all those assumptions, I would suggest the following changes.

  - First sentence: s/certain rectangle/certain rectangle and 'direction' value/.

    Also, to avoid giving the idea that the containing block is a function of
    an element, I would change the start of the sentence not to mention "an
    element" at all, i.e. "The position and size of a box are sometimes...".

  - Second sentence: s/of an element/of a box/ (given the above example where
    an element can have more than one containing block).

  - Rule 1: "containing block in which [an element] lives" is unclear as to whether
    it's the same thing as the containing block of that element, so
    s/in which the root element lives/of the principal box of the root element/.
    s/is a rectangle called/is called/.
    s/'direction' property/'direction' value/, and correspondingly
    s/same as for the root element/same as the root box's value of 'direction'/.

  - Rule 2: The main issue here that can contribute to the interpretation where
    the containing block is a block box and thus has a border edge etc. is that
    rule 2 is currently silent on what the 'direction' for the containing block is,
    giving the impression that the containing block *is* the named ancestor box
    (because that way it isn't necessary to separately specify what the 'direction'
    of the containing block is).  So I suggest inserting "and 'direction' value"
    after "content edge".

    Based on the above-mentioned assumption that containing block is a property of
    boxes rather than elements, I would of course also suggest changing "For other
    elements".  How it should be changed depends on how the next item is resolved:
    it should either be changed so that it more obviously means that rules 2–4
    only apply for non-root boxes, or it should be changed so that it's less likely
    to be taken to mean that rules 2–4 only apply to non-root boxes.  (It makes
    no difference to rule 4, it differs only for rule 3, see below.)

  - In rule 2, concerning the phrase "the element's position": There are
    several places in the spec where "position of an element/box" or
    "element/box's position" refers to the location coordinates of the box, or
    (for elements) the position in the document tree.  Accordingly, I suggest
    changing "the element's position" to "the box's value of 'position'".

  - Rules 1 and 3 conflict with each other in the case that the root element is
    position:fixed.  However, the two rules do give very similar results (the
    same width and height for example), differing only in the position of the
    containing block, and even then only in continuous media.  I believe
    the difference can be tested by using a position:absolute box (where position
    is defined to be relative to the containing block).  If rule 1 wins, then
    the containing block is "anchored at" (which I take to mean that its top-left
    corner coincides with) the canvas origin, so a position:absolute box
    that extends outside of the initial viewport should be reachable by scrolling;
    whereas if rule 3 wins, then the containing block is instead equal to the viewport,
    so scrolling won't make the position:absolute box visible, and so it would
    be reasonable not to display scrollbars.
    
    I see the following behaviour:

      - Gecko and WebKit don't give scrollbars, so presumably apply rule 3
        (containing block equals viewport).

      - An old (~2005) version of Opera does give a scrollbar, which scrolls
 both the position:absolute box and the root's background image, so is
 applying rule 1 (containing block is anchored at canvas origin).
 
 [I say "scrollbar" singular because it changed the x coordinate of the
  position:absolute box such that no horizontal scrolling is needed.
  Presumably this is unrelated.]

      - Konqueror apparently can't make up its mind: it gives scrollbars, and
 scrolls *part* of the background image, while the position:absolute box
 and the other part of the background image do not scroll.

  - The rules (notably including rule 3) don't specify the 'direction' value
    for the containing block of position:fixed boxes.  This would affect
    what happens when the position:fixed box's position & width are
    over-constrained, for example.  Without having tested implementations,
    I would say that the root's value of 'direction' would be the most
    reasonable, but that the box's own value of 'direction' might also
    seem reasonable: both rules could be seen to be analogous to rule 1.

  - As usual, s/element/box/ in rule 3 if the assumptions given at the start
    are correct.
  
  - The construct "element has 'position: fixed'" (in rule 3 and a similar
    phrase in rule 4) suggests that it's talking about what was in the
    stylesheet rather than what the computed value is.  I suggest avoiding
    the misleading colon notation here, changing to, say, "value of 'position'
    is 'fixed'".

  - In rule 3, either the phrase "is established by" must be taken to mean
    "equals", or else rule 3 is underspecified as to what the containing block
    actually is.  Whereas in rule 4, taking the phrase "is established by" to
    mean "equals" would require that the containing block be an ancestor.
    (Thus, this is one of the things that might result in an interpretation
    where a containing block can have a border edge.)
    I suggest that rule 3 be clarified s/containing block is established
    by/containing block's rectangle is/, while in rule 4 changing to, say,
    "is based on" (or "is calculated from").

  - In rule 4, there needs to be some clarification of what the "ancestor" is.
    Evidently it's something that can generate multiple boxes, which suggests
    that it really is talking about an ancestor element rather than box,
    but I don't think it's clear what's expected to happen when a
    position:static run-in element has a position:absolute child and an
    immediately following display:block position:relative sibling: I would
    suspect in this case that the intent would be that the containing block be
    the padding edge of the position:relative sibling of the run-in element,
    even though this isn't an ancestor element of the position:absolute
    element.  I.e. I would suspect that the intent be based on a version of the
    box tree before line-breaking and quite possibly before anonymous block
    processing too, given that the tree for purposes of what position:relative
    affects seems to be unaffected by anonymous block processing (based on
    "When such an inline box is affected by relative positioning, the relative
    positioning also affects the block box.")  So one test case would involve
    a position:absolute element with a display:block parent that in turn has
    a display:inline position:relative parent.
    
    This sounds like a rather hairy area.


There is just one other change that we should at least consider, and that is to
rename the term "containing block" so as not to give the impression that it's a
block, and so as to avoid confusion with "block container", which is similar
enough that the two might be taken to be synonyms.  Of course "containing
block" is a well-established phrase, which does make this a questionable change.
We could somewhat mitigate this by adding that "previous versions of this
specification called this ...".

(By comparison, "block container" still hasn't appeared in a publicly-visible
version of CSS2.1, if we want to rename that, perhaps to something from one of
the "inwardly block" proposals.  Doing so wouldn't affect the "is the
containing block a block" problem, though.)

Other relevant information: Some readers may recall that someone previously
expressed concern about confusion between those two phrases in the thread
where "block container" was introduced.  I've just checked, and both of these
messages in that thread were from Alan Gresley, so don't constitute evidence
of anyone else with the same interpretation or concerns.

If we were to rename "containing block", then a candidate new name would be
"basis rectangle".

pjrm.

Received on Friday, 22 October 2010 20:14:28 UTC