What about styling anonymous container boxes?

Imagine you have a box - say, an H1 - and you want it to have two
borders, one dark blue and one light blue.

If you have access to the document source, then you can do this quite
easily:

   <DIV><H1>Foo</H1></DIV>

...with the CSS:

   DIV { border: solid navy; }
   H1 { border: solid blue; }

This solution is sub-optimal at best, since it (a) pollutes the
content's document tree with stylistic issues, (b) requires access to
the document in the first place, and (c) requires a document type that
has quite generic containers (an issue with XML).

I suggest the introduction of a pseudo-element that inserts an
anonymous box around the principal box of element in question. This
would then allow for the type of styling described above.

If we call this pesudeo-element ":foobar" (I cannot think of a good
name right now), then the above example could be marked up like this:

   <H1>Foo</H1>

...with the CSS:

   H1 { border: solid blue; }
   H1:foobar { border: solid navy; }

...which is much kinder on the document.


TECHNICAL ISSUES
================

* What value of "display" does the anonymous box initially 'inherit'?

I suggest using the following table to map the main element's
'display' property to the 'inherited' value of the anonymous block's
display property:

		   'display' value of
		  the main  |  the anon-
		   element  |  ymous box
		------------+-------------
		     inline | inline
		      block | block
		  list-item | block
		     run-in | [1]
		    compact | [1]
		     marker | [2]
		      table | block
	       inline-table | inline
	    table-row-group | table-row-group [3]
	 table-header-group | table-header-group [3]
	 table-footer-group | table-footer-group [3]
		  table-row | table-row [3]
	 table-column-group | table-column-group [4]
	       table-column | table-column [4]
		 table-cell | table-cell [3]
	      table-caption | table-caption [5]
		       none | none
	     [inline-block] | inline [6]

Notes:

[1] - The 'computed' value of the display property would be inherited.
For example, if "run-in" results in an inline box, then the anonymous
box created would be inline.

[2] - This cannot ever be the case if we follow the CSS2 rules for
pseudo-elements (namely, that there can only be one at the end of each
selector). However, if, as I have suggested in the past, multiple
pseudo-elements are allowed within each selector in CSS3, then I
suggest that ":foobar" on a display:marker box cause the marker box to
be changed to an inline box, and the anonymous box to be turned into a
marker box.

[3] - This will result in the creation of a set of anonymous table
elements between the anonymous box created by ":foobar" and the
original element's content. 

For example, given:

   <TABLE>
     <TR>
       <TD></TD>
     </TR>
   </TABLE>

...with the CSS

   TABLE { display: table; }
   TR { display: table-row; }
   TD { display: table-cell; }

...if we then add

   TR:foobar { }

...then, for the purposes of the layout engine, the document tree
would end up containing:

   <TABLE>
     <TR:foobar>
       <TD:implied>
	 <TABLE:implied>
	   <TR:implied> 
	     <TD></TD>
	   </TR:implied>
	 </TABLE:implied> 
       </TD:implied>
     </TR:foobar>
   </TABLE>

This is nothing new, CSS2 already covers the relevant rules.

[4] - CSS2 is silent on whether these can be nested or not, and
whether any element implication occurs, as with the row-based table
elements. In terms of implementation, nesting columns should not be
difficult, as in any case these elements do not render per se (they
merely affect the cells they contain).

[5] - Again, CSS2 is silent on whether captions can be nested or not,
and whether any element implication occurs, as with the row-based
table elements. However, I would suggest a scheme similar to marker
boxes, where the principal box of the main element (the real caption)
is turned into a block box, and the anonymous ':foobar' box is made
into a caption.

[6] - 'inline-block' is a proposed addition to CSS3 that was mentioned
a while back. I guess it takes part in the inline formatting model,
and thus an anonymous container box should be inline.


* Which values of 'display' is an anonymous box is allowed to take?

I suggest "all of them" except 'marker', which is reserved for :before
and :after. A quick glance at the spec does not reveal any situations
that this would allow that cannot already be achieved by styling
generic DIVs inserted into the document tree.


* In which direction are properties inherited?

The obvious answer is to use the same behaviour as used with the
:before and :after pseudo-elements, with the only exception being the
display property being set as described above.

Thus in the following snippet:

   *         { border: blue solid; }
   BODY, H2  { font-weight: normal; border: none; }
   H1:foobar { font-weight: bold; }
   H2:foobar { font-weight: bold; }

...H1s and H2s are *not* bold (and since the ":foobar" pseudo-element
is not affected by the 'content' property, nothing related to them can
ever be affected by those font-weight rules). 

Also, since the universal selector only applies to "real" nodes in the
document tree, any H2s will not have a blue border. (H1s will, but this is
independant of the ":foobar" pseudo-element.)

-- 
Ian Hickson

Received on Tuesday, 9 February 1999 18:28:07 UTC