[css3-regions][css3-content] Explicit/Implicit, Named/Anonymous Regions

I think we must distinguish different concepts and decide which one or ones we want in CSS. Several related modules should follow the same design.

The first approach, “A”, is a combination of sources and targets where the former push their contents away into named flows (possibly each into more than one) and the latter pull in as much content from one or more flows as they can handle. Neither needs to know the name or selector of the other. Both can exist in a random number, i.e. it is an n:m relationship.

The second approach, “B”, is an association of source element with target region, i.e. the former “knows” the latter, but not vice versa, because it is a n:1 model.

Step 1
======

The first thing we need to do in both cases is to find some source elements with existing selectors to fill with their children/content 
[A] (at least) one arbitrarily named flow or 
[B] an implicit named region that is created, if not already existing. 
This is not DOM tree manipulation, although we are copying or moving contents from a node to the flow, which is not anchored yet within the (rendering) tree.

I can think of two reasonable variants for how a source element “foo” pushes its content away into “bar” which is [A] a named flow or [B] a target region. One variant uses the new, proposed ‘flow’ property that takes a string, i.e. an identifier, as its value

  foo {        /* “foo” is a source element */
    flow: bar; /* “bar” is [A] a named flow or [B] a target region */
  }

and the other variant uses the existing ‘content’ property with a new pseudo-function value

  foo {
    content: to(bar);
  }

If you need multiple targets – more on how those would be handled later – you simply add them separated by commas, e.g.

  flow: bar, baz, quuz;
  content: to(bar, baz, quuz);

It would be possible and desirable to distinguish between moving and cloning (e.g. pull quotes) the content. In the ‘content’ variant this would be done either by using two different pseudo functions or by introducing a second (optional) parameter:

  content: to(bar, keep);    or  copy(bar);  or  clone(bar); 
  content: to(bar, remove);  or  cut(bar);   or  move(bar); 

The unified function of course works worse than the alternative if you want to support more than one target:

  content: to(bar, baz, quuz, keep);

With the ‘flow’ variant you could actually employ the content property

  flow: bar; content: contents; /* copy */
  flow: bar; content: none;     /* move */

Step 2
======

In the second step we must either
[A] generate and style explicit regions that pull their content from flows or
[B] style implicit regions whether anonymous or named.

Step 2 for anonymous regions
----------------------------

There are three variants for dealing with anonymous regions.

A first variant uses existing properties ‘display’ (or ‘position’) and, optionally, ‘content’ to transform a DOM node (marked up or using a pseudo-element) that is selected by traditional means into a region and pull contents from a named flow. Normal styling is possible for the node and its anonymous region, but it is impossible to select a paragraph that is (completely) in that region.

  baz /* a normal selector */ {
    display: <region>; /* some ‘display’ values make “baz” an anonymous region */
    content: from(bar); /* anonymous regions must pull their content from named flows */
    width: 50%;
    color: blue;
  }

It would, however, be possible to style all content that belongs to a named flow (as opposed to an anonymous region):

  @flow bar {
    p {
      color: green;
    }
  }

Another variant uses special region selectors, possibly pseudo-elements. Note, though, that pseudo-elements should be used to match stuff that is already in the document, just not marked up explicitly, like a first line, and not for arbitrary regions (or grids or …) which are created by the styling language.

The region selector creates an anonymous region, which at first does not make this variant more attractive than the first, but using a new pseudo-class that works similar to proposed ‘:matches()’ one can select nodes that are flowed into a certain anonymous region, maybe this would even work for individual parts (i.e. lines) of theses nodes.

  <quuz> /* a region selector */ {
    content: from(bar); /* anonymous regions must pull their content from named flows */
    width: 50%;
    color: blue;
  }
  p:in(<quuz>) /* a paragraph that is (completely) in the anonymous region created by “<quuz>” */ {
    color: green;
  }

A final variant makes use of a new at-rule that has more flexible content between its braces than normal rulesets, i.e. we don’t need the pseudo-class from the previous variant.

  @region {
    content: from(bar); /* anonymous regions must pull their content from named flows */
    width: 50%;
    color: blue;
    p /* a paragraph that is (completely) in this anonymous region */ {
      color: green;
    }
  }

The pseudo-function ‘from()’ used in all three variants could support multiple flow sources in specified order

  content: from(bar, baz, quuz);

This conflicts, however, with the desire to control whether it amends or replaces existing content

  content: from(bar, add);
  content: from(bar, replace);

but that could be dealt with by ‘content’ conventions: mutually exclusive alternatives (i.e. fallbacks) are in a comma-separated list, combinations are space separated.

  content: contents from(bar);  /* add */
  content: from(bar), contents; /* replace */

This method could also be used for (and combined with) multiple sources.

  content: from(bar) from(baz) from(quuz);   /* cumulative */
  content: from(bar), from(baz), from(quuz); /* exclusive */

Step 2 for named regions
------------------------

Named regions automatically include the content of the flow of the same name, i.e. there’s no need for the ‘content’ property with a ‘from()’ pseudo-function. Still, we can do this in two variants.

The first variant is actually close to the last variant for anonymous regions, we just include a name with the at-rule. This model would make the concept of flows unnecessary.

  @region bar {/* “bar” is a named region */
    width: 50%;
    color: blue;
    p /* a paragraph that is (completely) in this named region */ {
      color: green;
    }
  }

Alternatively we can keep the distinction between named flow and named region, by using two at-rules where the first styles the region and the second styles content that is moved into the flow, i.e. it works similar to ‘@media’. I think this is a cleaner design.

  @region bar {/* “bar” is a named region */
    width: 50%;
    color: blue;
  }
  @flow bar {/* “bar” is a named flow */
    p {color: green;}
  }

Sub-variants of both main variants for named regions don’t require nested selectors, but make use of the name in pseudo-selectors that are simpler than the ‘:matches()’-like approach above. This actually may work on parts.

  p:in(bar) /* a paragraph that is (completely) in region “bar” */ {
    color: green;
  }
  p::in(bar) /* all parts (i.e. lines) of a paragraph that flow into region “bar” */ {
    color: red;
  }

Since many authors fail to grasp the difference between pseudo-elements and pseudo-classes a different name for one of them would be wise.

  p::lines(bar) {
    color: red;
  }

One could also distinguish regions and flows.

  p:in-flow(bar) /* a paragraph that is (completely) in flow “bar” */ {
    color: orange;
  }
  p:in-region(bar) /* a paragraph that is (completely) in region “bar” */ {
    color: green;
  }

Received on Tuesday, 17 May 2011 07:40:34 UTC