Re: [css3-lists] Proposal: list-style-position inside-hanging

On Jun 6, 2010, at 1:50 AM, Markus Ernst wrote:

> -------- Original-Nachricht --------
>> Datum: Sun, 06 Jun 2010 00:28:47 +0200
>> Von: "Markus Ernst" <derernst@gmx.ch>
> 
>> One of the very common use-cases for list-style-position is the one
>> usually called "hanging indent" in word processors and layout softwares: The
>> position of the marker is supposed to align with the edge of the text column,
>> as with list-style-position:inside, but the contents of the list item should
>> appear as a block as with list-style-position:outside.
>> 
>>    Text bla bla bla bla bla
>>    bla bla bla bla
>> 
>>    * List item one
>>      list item 1
>>    * List item two
>> 
>> Trying to get this aligned cross-browser with setting appropriate margins
>> and/or paddings on the ul/ol and li elements is quite a hassle. Even more,
>> if you have ordered lists and at CSS writing time you don't know the number
>> of list items to expect. 

Using the ::marker pseudo-element, this may be possible, once that CSS3 list stuff[1] is actually implemented (AFAIK, it hasn't, but I might be mistaken). For instance:

UL { padding:3em; }
LI { 
    list-style-position: inside;
}
LI::marker { 
    margin-left: -3em;
}

The inside-positioned marker normally seems to have some margin on the right of about 1em, although I don't think this is mandated in any of the specs. That margin can thus push the left edge of the primary box's first line-box away from it to the right by 1 em. By using negative left margin on the marker, you pull it away from that first line so that the marker's right margin is no longer pushing on the first line of primary text, which can then left-align with the rest of the lines of text in the primary box.

Or, at least, that is how it would work if 'list-style-position: inside' had the marker box outside the principal block box, the way the 'outside' marker box does.  Then the primary difference between the two would be:

• for 'inside', 'margin-left:0; position:static;' means that the left edge of the marker box aligns with the left edge of the principal block box (with any positive 'margin-right' pushing the first line of text in the principal box aside to the right), and

• for 'outside', 'margin-right:0; position:static;' means that the right edge of the marker box aligns with the left edge of the principal block box  (any positive 'margin-right' pushes the marker box further to the left).

However, with the way the working draft is worded now, 'list-style-position: inside' also means that the marker box is _within_ the first line box of the principal  box (it is a child of the principal box). So my rules above would result in the fist line of content being pulled to the left too, following marker box and its negative left margin. This is a problem with the current working draft, at least the way I read it, and I'd like to see it changed.

So we can instead try to do your bullet-left-alignment with 'list-style-position: outside':

UL { padding:3em; }
LI { 
    list-style-position: outside;
}
LI::marker { 
    width: 2em; 
    margin-right: 1em;
}

We can't just use margin by itself, because we don't know the exact width of the bullet glyph, number, or other text being used for the marker (assuming you don't want to rely on just images of known width to get this effect). So to get it to line up with the left edge, you make the glyph box an exact width that fits within the UL padding correctly for whatever right margin you have on the marker box.

The problem now, is that you might get an overflow situation in your marker box, if it includes a very large number or some generated content. And, assuming 'overflow:visible' on the marker, that overflow might overlap some of the text in the primary box (which would be bad). If we had been able to use the inside marker instead, we wouldn't have this problem (with that one, over-long marker content would just push primary box text further to the right). We can still avoid the problem by using 'min-width' instead of 'width', but this means that instead of overflow, we get the left edge of the marker box being pushed further to the left than you wanted. So my preferred solution is to modify the draft so that both 'inside' and 'outside' marker boxes are drawn as independent boxes that can push against the text of the primary box (similar to how floats push against line boxes).

....and another thing.....

I would also, as a shorthand sort of thing for the above, propose to let "list-style-position" accept lengths. So, for instance,  both of the following would produce similar results:

(#1:)
LI { list-style-position: 40px; }

(#2:)
LI { list-style-position: inside; }
LI::marker { 
    margin-left: -40px;
}

Thus, the distance measurement determines how far the left edge of the marker is from the left edge of the first character or node of the list item. If this distance is less than the width of the marker and the marker's margin-right, then the marker pushes in on the first character or node of the list item by the difference, so that the following two line are also equivalent:

LI { list-style-position: inside; }
LI { list-style-position: 0px; }





[1] http://www.w3.org/TR/2002/WD-css3-lists-20021107/#markers

Received on Monday, 7 June 2010 16:37:52 UTC