Re: list-style-position

On Thu, 7 Aug 2003, Roger Larsson wrote:
>
> I would appreciate if someone would like to clarify the implications of  the
> "list-style-position" property.

My current thinking on this is as follows. Note that I describe this
in terms of the CSS3 model:

   http://www.w3.org/TR/css3-lists/

...not the CSS2.1 model, because the former is much more clearly
defined. (This is only my thinking. I'm the editor of the above spec,
but I am not speaking for the working group here, and this could all
change before we reach a stable spec. It's reasonably unlikely,
however, since this is basically a description of the CSS2 model, in
more detail.)


Markers are created by setting an element's 'display' property to
list-item. As far as rendering goes, the list-item display type is
otherwise identical to the block display type.

The marker box is only created if the computed value of the 'content'
property for the pseudo-element is not 'inhibit'. For more details on
the current thinking of how 'content' works on ::marker, see the
Generated and Replaced Content draft:

   http://www.w3.org/TR/css3-content/


In the 'inside' positioning model, the ::marker pseudo-element is
placed at the beginning of the first line box of the principal block
box. This will typically cause the first character of the marker to
match the element's ::first-letter pseudo-element.

For the purposes of white space collapsing, the marker is considered
to be on the line. Typically this will make leading white-space in the
block itself significant. This is the same as for ::before and ::after
pseudo-elements.

The 'display' property always computes to inline on an 'inside' marker
pseudo-element. The 'float' and 'position' properties do not apply. A
long marker or one containing newlines preserved by the 'white-space'
properties will wrap onto several lines, just like any long inline
element.


If the elements' 'list-style-position' property has the value outside,
then the value of the element's ::marker pseudo-element's 'content'
property is formatted in an independent marker box, outside the
principal box. Marker boxes are formatted as an inline-block (i.e.,
they fit in one line box), so they are not as flexible as floats or
absolutely positioned boxes.

The 'display' property always computes to inline-block on an 'outside'
marker pseudo-element. The 'float' and 'position' properties do not
apply.

Marker boxes have padding, borders and margins, just like inline-block
elements. The marker box will be vertically aligned with the first
line of content in the principal box, as specified by the
pseudo-element's 'vertical-align' property. (The principal box is the
main one generated for the element with its 'display' property set to
list-item, as opposed to the marker box.) The marker box participates
in the height calculations of the principal box's first line box.
Thus, markers are aligned with the first line of an element's content.
If no first line box exists in a principal box, the marker box
establishes its line box alone, as the first box of the principal
block box. (The first line of a principal box is the one matched by
the box's '::first-line' pseudo-element. It might not be a direct
child of the box, but it must be in flow.)

The end of the marker box is horizontally aligned with where the start
of a line box directly inside the list-item element would be, given
the vertical position of the marker: for example in a left to right
context, the right margin edge of the marker box coincides with the
left edge of the line box. Thus if a float intersects the element,
moving the line box start, the marker box is moved as well. It is the
responsibility of the author to ensure that sufficient margins are
provided on floats to prevent marker boxes overlapping with them. The
CSS3 Box Model will define the properties 'float-displace' and
'indent-edge-reset' to control how far line boxes are moved in the
presence of floats.

Spaces at the front of the text are collapsed away according to the
'white-space' properties, as if the marker was not present.

If the value of the 'width' property is auto, the marker box content
width is that of the content, otherwise it is the value of 'width'.
For values of 'width' less than the content width, the overflow is
visible. The 'overflow' property does not apply. The 'text-align'
property determines the horizontal alignment of the content in the
marker box.

Marker boxes may overlap principal boxes and other marker boxes.
Overlap could happen for several reasons. If several nested elements
without inline content all have marker boxes, for instance, or if a
marker box has negative margins. Marker boxes are rendered at the same
stack level as inline content of the principle box, as if it was the
first box of the first line box.

The CSS2 'marker-offset' property is obsoleted in this model and has
no effect. (It is replaced by the 'margin-right' property in
left-to-right text, and the 'margin-left' property in right-to-left
text.) 9.3. Edge cases of note for 'outside' marker boxes

If the marker box contents consist of just one image (as would
typically be the case if 'list-style-image' is set, for example), then
the marker box becomes a replaced inline-block element. In this state,
the block-progression-direction (vertical in left-to-right text)
margins, borders, and padding of the marker box contribute to the
height of the line box. In the normal case, only the 'line-height'
does.

In the absence of a margin on the marker box, and in the absence of
any padding on the list item's principal box, borders around the
principal box would go under the marker box. (That is to say, the
marker bok would overlap the borders of the list item's principal
box.)

Several nested list items with only one line box between them, in the
inner most list item, will result in several marker boxes all taking
part in the same line box model alignment calculations. Authors
wanting to stop this effect, and instead generate empty line boxes for
the outer marker boxes, can do so by generating a ::before
pseudo-element with its 'content' property set to the empty string.

Note that if a float intersects such a scenario, the markers may well
end up overlapping, because it is likely that the fictional line boxes
with which the ends of the markers are horizontally aligned would end
up starting at the same position.

For example, the following stylesheet and document fragment:

 item {
   border: solid orange; padding; 0.5em 0.5em 0.5em 3em;
   display: list-item; counter-increment: counter;
 }
 item::marker {
   content: counter(counter) '.';
   margin-right: 0.5em;
 }
 float {
   float: left;
   margin-right: 2em;
 }

 <item>
  <item>
   <item>
    List item text.
   </item>
  </item>
 </item>

Would render as in the first set of boxes below if there was no float
present, and as in the second set if a float was present and
overlapping the boxes.

A list item containing a series of nested and adjacent blocks with a
line box some way down will cause the marker to take part in that line
box's alignment.

If the DOM of the document or the stylesheet is changed dynamically,
this can cause the list marker to radically change position.


In the following example, the content is centered within a marker box
of a fixed width. This document:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
<HTML>
 <HEAD>
  <TITLE>Content alignment in the marker box</TITLE>
  <STYLE type="text/css">
   LI::marker {
     content: "(" counter(counter) ")";
     width: 6em;
     text-align: center;
   }
   LI {
     display: list-item;
     counter-increment: counter;
   }
  </STYLE>
 </HEAD>
 <BODY>
  <OL>
   <LI> This is the first item. </LI>
   <LI> This is the second item. </LI>
   <LI> This is the third item. </LI>
  </OL>
 </BODY>
</HTML>

should produce something like this:

  (1)    This is the
         first item.
  (2)    This is the
         second item.
  (3)    This is the
         third item.

The next example uses markers to number notes (paragraphs).

The following document:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
<HTML>
 <HEAD>
  <TITLE>Markers to create numbered notes4>/TITLE>
  <STYLE type="text/css">
   P { margin-left: 12 em; }
   P.Note::marker {
      content: url("note.gif") "Note " counter(note-counter) ":";
      text-align: left;
      width: 10em;
   }
   P.Note {
     display: list-item;
     counter-increment: note-counter;
   }
  </STYLE>
 </HEAD>
 <BODY>
  <P>This is the first paragraph in this document.</P>
  <P CLASS="Note">This is a very short document.</P>
  <P>This is the end.</P>
 </BODY>
</HTML>

should produce something like:

            This is the first paragraph
            in this document.

  Note 1:   This is a very short
            document.

            This is the end.

The following example illustrates how markers may be offset from their
element. This HTML application and style sheet:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
 <HEAD>
  <TITLE>Marker example 5</TITLE>
  <STYLE type="text/css">
   P { margin-left: 8em } /* Make space for counters */
   LI::marker { margin: 0 3em 0 0; content: counter(list-item, lower-roman) "."; }
   LI { display: list-item }
  </STYLE>
 </HEAD>
 <BODY>
  <P> This is a long preceding paragraph ...</P>
  <OL>
   <LI> This is the first item.
   <LI> This is the second item.
   <LI> This is the third item.
  </OL>
  <P> This is a long following paragraph ...</P>
 </BODY>
</HTML>

should produce something like this:

        This is a long preceding
        paragraph ...

   i.   This is the first item.
  ii.   This is the second item.
 iii.   This is the third item.

        This is a long following
        paragraph ...

(Note the use of the implicit counter increment.)


HTH. Let me know if you see anything wrong with this model!

Cheers,
-- 
Ian Hickson                                      )\._.,--....,'``.    fL
"meow"                                          /,   _.. \   _\  ;`._ ,.
http://index.hixie.ch/                         `._.-(,_..'--(,_..'`-.;.'

Received on Thursday, 7 August 2003 15:39:17 UTC