W3C home > Mailing lists > Public > www-style@w3.org > April 2012

Re: [css3-values] use cases and the design of 'cycle()'

From: Tab Atkins Jr. <jackalmage@gmail.com>
Date: Mon, 9 Apr 2012 13:44:21 -0700
Message-ID: <CAAWBYDASOAi8G1ku21t0BMXTCTw-gqBKtwMacQ1rWAP4E+55RA@mail.gmail.com>
To: "Kang-Hao (Kenny) Lu" <kennyluck@csail.mit.edu>
Cc: WWW Style <www-style@w3.org>
On Mon, Apr 9, 2012 at 1:14 PM, Kang-Hao (Kenny) Lu
<kennyluck@csail.mit.edu> wrote:
>> It also works incorrectly if you have a chain of cycle()s that work
>> together, but in the middle you instead set the value to an explicit
>> option - the following cycle() will just ignore that value and
>> continue to iterate to the entry following whatever the grandparent
>> used.
>
> I think I need an example to fully understand this. Can you give me an
> example use case? Why would you want to have a chain of cycle()s? My
> impression is that I don't think this behavior is actually desirable,
> and this is only correct if you want the "use x if the parent is y..."
> behavior, which as I said, is very different from "use x, and then y,
> and then z..."

Say you have this:

<ul id=one>
  <ul id=two>
    <ul id=three>...</ul>
  </ul>
</ul>
<style>
ul { list-style-type: cycle(disc, square, circle); }
</style>

Now, imagine that for some reason you (or another author on the same
project) adds a rule like "#two { list-style-type: square; }".  This
has no visible effect on #two, since the cycle() rule would have set
it to 'square' anyway.  However, this changes the rendering of #three
- it's now 'square' rather than the intended 'circle'.  That's
surprising and unintuitive.

>>> == Advantages ==
>>>
>>> 1. It is a lot more intuitive and less error-prone by specifying "use x,
>>> and then y, and then z..." than "use x if the parent is y...". For
>>> example, css3-lists has
>>>
>>>  # /* Default list style types for unordered lists up to 3 deep */
>>>  # ul { list-style-type: disc; }
>>>  # ul ul { list-style-type: square; }
>>>  # ul ul ul { list-style-type: circle; }
>>>  # /* Alternately, if Values & Units Level 3 is supported, replace
>>>  #    the above three lines with: */
>>>  # ul { list-style-type: cycle(disc, square, circle); }
>>>
>>> in the "Sample style sheet for HTML", which doesn't work without
>>> Proposal B applied because the inherited value I is 'disc' from the
>>> initial value (and people forget that) and so the 'list-style-type' of
>>> the top level <ul> is 'square'.
>>
>> Ah, yes, that's definitely an error.  This aspect is a bit of a
>> footgun, but it should be quickly obvious in practice.  I'll fix the
>> error.
>
> I am quite interested in your fix. The best I can do is
>
>  ul { list-style-type: disc; }
>  ul ul { list-style-type: cycle(disc, square, circle);}
>
> but it is no longer too useful if I can only reduce three declarations
> to two. (I don't quite care about this use case though)

Yes, that's how to fix it.  This problem only occurs when the initial
value of the property is set to something "useful", but which is
useless for normal elements.

If the property applies to all elements, the initial value will
instead usually be something that doesn't do anything in particular,
so you can just use a single rule to set up the cycle(), starting with
the useful value you want.

> But anyway, I think this is far from obvious, and this is because "use
> x, and then y, and then z...(repeat)" and "use x if the parent is y..."
> require very different thinking. The current definition is mainly
> designed for the latter as far as I can tell.

Yes, this is true.  We'd have liked to make it the more intuitive
"switch based on nesting level", but there doesn't seem to be a good
way of doing so.  :/

The only way I can think of doing what you want is to force cycle() to
take an ident, and have it compute to the ith entry, where i = (number
of ancestors with a cycle using the same ident) mod (number of entries
in this cycle).  This doesn't require any tricky comparison at all
unless we want to add some for aesthetic purposes - cycle()s with the
same ident can have different values in each entry, and even different
numbers of entries.

This is basically your "counter" idea, except not tied to counters
(and thus no weirdness around siblings), and always explicit (which
avoids the problems yours had trying to match similar cycle()s
together).

Hm.  Now that I've typed this out, I like it a bit better than I
thought I would.

~TJ
Received on Monday, 9 April 2012 20:45:11 GMT

This archive was generated by hypermail 2.3.1 : Tuesday, 26 March 2013 17:20:52 GMT