W3C home > Mailing lists > Public > www-style@w3.org > November 2014

Re: [css-gcpm] String-set issues

From: Brad Kemper <brad.kemper@gmail.com>
Date: Tue, 25 Nov 2014 00:43:23 -0800
Message-Id: <2390FDD3-731A-4A55-9BE3-BBA7383DA518@gmail.com>
Cc: www-style list <www-style@w3.org>, Dave Cramer <Dave.Cramer@hbgusa.com>
To: Håkon Wium Lie <howcome@opera.com>

> On Nov 24, 2014, at 10:49 AM, Håkon Wium Lie <howcome@opera.com> wrote:
> 
> Brad Kemper wrote:
> 
>> 1. 'string-set' is a weird and confusing property name. It sounds
>> like it is for a set of something, but I think really 'set' is
>> meant to mean that you are assigning a (string) value to a name.
>> We don't do that in other places where we have named things. For
>> instance, we have '@counter-style', not '@counter-style-set';
>> '--foo', not 'foo-set', the 'font-family' descriptor of
>> @font-face, not 'font-family-set', etc.
> 
> I like 'string-set'. It uses 'set' similar to 'reset' (as in
> 'counter-reset').

Yet it isn't 'string-reset', and we don't have 'counter-set'. Maybe because 'counter-set' sounds like pushing a new kitchen counter into the mortar to set it level or something. 

Seriously, I used to think that 'string-set' might refer to a set of text strings. It turns out to mean something more like the "set" in "set a goal" or "set the timer". It is an ambiguous word. 

> The property is interoperably implemented by
> Prince/AntennaHouse, so it would take some convincing to make the
> change.

It is an experimental feature Sent from my iPad

>> 2. Pseudo-elements are excluded from being able to use
>> 'string-set', so the 'content()' function has its own way of
>> accessing them. That seems unnecessary. Just let pseudo-elements
>> assign their contents to a named string, if you need that. It is
>> simpler to learn, and less complicated, because you just use
>> selectors like you normally do with pseudos. And really, most of
>> the time, you won't even need that, because the actual element has
>> access to the counter too, and that can be assigned to a name
>> there. This would also eliminate the need for parentheses after
>> the keyword 'content'.
> 
> This could work, too. There would be more declarations, which some
> would consider more complex, but the values would -- like you say --
> be simpler. Again, the question will be whether implementors are
> prepared to make changes that doesn't add new functionality.

I think most of the time you don't even to access the pseudo, because whatever you put in its content can be put in the main element's string-set. 

>> 3. 'string-set' only gets the text of the element. I would think
>> there are times when it would be useful to get all the content
>> nodes, including links, bolds, small pictures, spans with class
>> names, etc.
> 
> Yes, this is what running elements are for.

Yeah, but why would you want that as a completely separate thing? String-set is already more powerful than running elements because you can combine them with other content, and pull the info from where you want on the page (first, last, etc.). They just have this one deficiency of being strings only. But it is a deficiency that can be fixed without resorting to a new 'position' value, and a totally separate and different mechanism for rich content vs strings. 

> https://books.spec.whatwg.org/#running-elements
> 
>> 4. When 'string()' is used to access a named string, it ignores
>> what was set on assigned to that name for elements not on the
>> page.
> 
> I'm not following you here. By default, named strings carries the
> values from one page to the next (unless set to some other value).
> 
>> But in CSS3-content [2], the examples include 'META[author]
>> { string-set: author attr(author); }', which selects something
>> completely outside the page and uses it. Is this because the two
>> drafts are out-of0synch, or are all these examples supposed to
>> work somehow?
> 
> The example works as expected -- the META elemet sets the "author"
> string which can be referred to later in the document. This is e.g.
> used when listing the author's name in a running header.

I guess I'm just finding it unintuitive that assigning a value to a name doesn't assign a single value to that name, replacing other values that were set earlier. If you had two author meta tags, the second one would presumably replace the value that the first on set on the name, but there can still be as many values associated with a name as there are elements matching a selector. I'm getting it a little more now, especially if I think of it being more like the way named counters work than the way named flows work. 

>> 5. Normally when we assign a value to some sort of name in CSS, it
>> is one value that is globally available. But with named stings in
>> this draft, every name has multiple values (one for each
>> selector-matched element within each page, multiplied by the
>> number of pages, since the name only has page-wide scope in all
>> the examples of this draft), so that the string() function can
>> access right element, based on its position on the page. For
>> instance, with 'string(theName, first)', the "value of the first
>> assignment on the page is used". Meaning, I think, that if the
>> element is the first occurrence of those on the page that match
>> the selector, then it uses that element for the value assigned to
>> that name. I think it would be better to just use selectors and
>> pseudo-classes to select the right element, rather than to have
>> that take place within the function inside the property value.
> 
> How would you use selectors to express these use cases:

I actually described a syntax in the second half of my email, below the part you quoted...

> In this example, the first term on the page will be shown in the
> top left corner and the last term on the page will be shown in the
> top right corner. In top center of the page, the first letter of
> first term will be shown.
> 
>   @page { @top-left { content: string(term, first) }}
>   @page { @top-right { content: string(term, last) }}
>   @page { @top-center { content: string(index, first) }}
>   dt { string-set: index content(first-letter), term content(text) }

  @page { @top-left { content: firstTerm }}
  @page { @top-right { content: lastTerm }}
  @page { @top-center { content: index }}

  dt:first-of-page::first-letter { copy-into: index }
  dt:first-of-page { copy-into: firstTerm text }
  dt:last-of-page { copy-into: lastTerm text }

It's a couple more lines in this particular case, but I find it much easier to read and understand. Three selectors for the three things selected, and no function syntax needed.

'copy-into' could be 'flow-copy-into' if we wanted to stress the relationship to 'flow-into' of the Regions spec, for further ease of understanding. I'm not opposed. 

> https://books.spec.whatwg.org/#using-named-strings
> 
>> 6. In the 'string()' function, the 'start' keyword is not well
>> defined. It says "If the element is the first element on the
>> page". Is that by document order? What if it has a parent?
>> Technically, doesn't the parent come first? Also, I didn't really
>> get what 'first-except' was for.
> 
> The description is slightly revised here:
> 
>   ''start'': the value of the first assignment on the page is used
>   if the element begins the page or the named string has not been
>   assigned a value. Otherwise, the named string's entry value is
>   used.

That's not much better. It still is imprecise by not defining 'begins the page'. Is it the element that is closest to the top left corner after floating and positioning and re-ordering? The first item in document order (no parents starting before it)? Is something that started on a previous page qualify as the first assignment beginning the page?

Also, how can there be a first ASSIGNMENT if the named string has not been ASSIGNED a value? Isn't that a contradiction?

> https://books.spec.whatwg.org/#using-named-strings
> 
>> 7. In the 'string-set', <content-list> can be used to construct a
>> string from the text contents of the element (using 'content()'),
>> as well as from literal text, counters, and attributes, and assign
>> it to a name. But then, when you want to use a string like that,
>> there is the 'string()' function. With that, you get that named
>> string and construct a string from it and from literal text,
>> counters, and attributes, and assign it to the 'content'
>> attribute. This seems unnecessarily redundant, which can make it
>> confusing. Since 'content' can already string together text from
>> multiple sources, we don't really need to do it before assigning
>> it to a name too, do we? If we need multiple things from the
>> original element (its text and one of its attributes and its
>> counter, for instance), they can just be each assigned to
>> individual names, which can then be pulled into 'content' to be
>> strung together. I think it is more author-friendly to just give
>> us one place to concatenate strings together for the content, and
>> let other properties and functions do their own things. Separation
>> of concerns.
> 
> You're right that the thing can be expressed in two slightly different
> ways. Somewhat like shorthand and longhand syntax.

Not really like that...
> I don't see it as a
> problem; it has been interoperably implemented, and it allows authors
> to express the stringing together where they think is best.

I'm a big believer in simplification, and duplication of nearly identical utilities seems un-simple for learning, but I'm kind of changing my mind about this point. When you have to pass each value through a separate unique name, that can get unwieldy for a lot of separate values, and stringing them together early can help avoid that.
Received on Tuesday, 25 November 2014 08:43:55 UTC

This archive was generated by hypermail 2.3.1 : Monday, 2 May 2016 14:39:26 UTC