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

Re: [css-selectors] Proposal: Logical Combinators / Sets

From: Brian Kardell <bkardell@gmail.com>
Date: Fri, 5 Apr 2013 19:05:53 -0400
Message-ID: <CADC=+jcwN73BoaSKy_pbMAfON2-ak449nBhZAjYLj8JsmqU3_w@mail.gmail.com>
To: Simon Sapin <simon.sapin@exyr.org>
Cc: "www-style@w3.org" <www-style@w3.org>
[snip]
> :allof() is AND, which is just juxtaposition. In case more than one of
> :allof()’s arguments contain a combinator, :matches() comes to the rescue:
>
>     :allof(.foo, .bar) → .foo.bar
>     :allof(.foo, ol li) → ol li.foo
>     :allof(.foo .bar, ol li) → .foo .bar:matches(ol li)
>
> Finally, :oneof() is XOR, which can be expressed as a combination of AND,
> OR, and NOT.
>
>     :oneof(.foo, .bar) → .foo:not(.bar), .bar:not(.foo)
>
> It gets messy with more XOR arguments, but it’s still doable.
>
>
> So, only :oneof() is arguably useful, but is there really an use case for
> XOR in selectors to begin with?
>
> --
> Simon Sapin


Let me make a couple of points (some of them restated from post and article):
  -  These are only significant (useful/necessary) if all of them can
take complex selectors
  -  Lots of things are currently solved today by modifying the markup
or DOM via for presentation purposes and that is less than ideal, it's
not the vision.  To reach that vision, we need nice semantic markup
(global and local semantics) and rich selector capabilities.
   - :matches and :not are already in there and they probably map to
two of these, but neither takes complex selectors yet.
   - I think pseudos that use well-established mathematical or CS
terms is intuitive.

As a rule, the examples I've seen are too simplistic to add much
benefit anyway..  Here is the example for where the current
implementation of :matches (simple selectors) benefits used in David
Barron's original blog post[1]:


    /* 3 deep (or more) unordered lists use a square */
    ol ol ul,     ol ul ul,     ol menu ul,     ol dir ul,
    ol ol menu,   ol ul menu,   ol menu menu,   ol dir menu,
    ol ol dir,    ol ul dir,    ol menu dir,    ol dir dir,
    ul ol ul,     ul ul ul,     ul menu ul,     ul dir ul,
    ul ol menu,   ul ul menu,   ul menu menu,   ul dir menu,
    ul ol dir,    ul ul dir,    ul menu dir,    ul dir dir,
    menu ol ul,   menu ul ul,   menu menu ul,   menu dir ul,
    menu ol menu, menu ul menu, menu menu menu, menu dir menu,
    menu ol dir,  menu ul dir,  menu menu dir,  menu dir dir,
    dir ol ul,    dir ul ul,    dir menu ul,    dir dir ul,
    dir ol menu,  dir ul menu,  dir menu menu,  dir dir menu,
    dir ol dir,   dir ul dir,   dir menu dir,   dir dir dir {
        list-style-type: square;
    }

The current :matches is just sugar, but that's not a bad thing - it
makes rules considerably more readable and therefore maintainable...
It is much easier to reason about something like:

    :-moz-any(ol, ul, menu, dir) :-moz-any(ol, ul, menu, dir)
:-moz-any(ul, menu, dir) {
        list-style-type: square;
    }

Than it is the expanded form  (above).  So let's not immediately think
"sugar is unnecessary" or bad - in fact, there is a benefit to the
above in that in theory all you need to do is write the
unwinding/expansion and then the underlying support is already in the
browser, and there is a benefit that it is easier to write software to
reason about that as well - you could potentially speed things up by
knowing where the logical forks are.

Given support for complex selectors, however, things change even in
the overly simplistic examples.  You gave:

    .foo .bar:matches(ol li)

We can currently say li.bar, but we cannot actually express the above
today: The relationship of .foo and ol is unknown.  Is ol a descendent
of .foo or vice versa?   This allows you to express wholly new things.
 What is currently called matches would be _extremely_ powerful.

So powerful, that with just complex :matches and :not you might be
right that (most) everything we need would be there.  As I mentioned
above, we need something reasonably rich to show the value, so let's
use my examples...  I called it "anyof", but it could be:

    /* Style the cars that are foreign and used or domestic, new and
effiecient. */
    .cars div:matches(.foreign .used, .domestic .new .efficient) p {
        color: blue;
     }

When I read this, I am personally unsure whether the things inside are
AND'ed or OR'ed since the break is inside parens.  Ok, that is
probably teachable...  Flip to my :allof - you could desugar that to:

     cars div:matches(.new .quality):matches(domestic .performance) p {
        color: red;
     }


And my noneof example:

     /* Style the efficient cars that are neither domestic and used
nor foreign and new. */
    .efficient:not(.domestic .used):not(foreign .new) p {
        color: green;
     }


What would (or would we always disallow) this do?  Would it be true if
one was not, or would they all have to be not?  The later seems in
keeping with what :matches is proposed to do so I'd suggest that:

     /* Style the efficient cars that are neither domestic and used
nor foreign and new. */
    .efficient:not(.domestic .used, foreign .new) p {
        color: green;
     }


As far as I can tell, there is currently no way to write my "oneof"
example -  I have  wanted it in the past myself.

Maybe that is enough and maybe it is intuitive enough - I find it
easier to reason about using set or predicate sorts of language which
don't leave the "what does that mean" sorts of questions I mentioned
above, but maybe that isn't a good enough case.

All of this is a bit of a chicken and egg problem we have here (I'm
glad someone in Lea's border-corners thread mentioned this):  People
work around these limitations today - but they do so by modifying the
DOM itself by either changing markup or through JavaScript - or they
just use an image or something and lose the data - because they have
no other choice - and given new powers, smart people will do new
things.



[1] - http://dbaron.org/log/20100424-any

--
Brian Kardell :: @briankardell :: hitchjs.com
Received on Friday, 5 April 2013 23:06:25 UTC

This archive was generated by hypermail 2.3.1 : Friday, 5 April 2013 23:06:25 UTC