Thinking about mixins as a new type of selector

Back in February, I had a discussion with Yehuda Katz [1] and Nicole
Sullivan [2].  I'd meant to write something about it earlier, but it
took a while, so my memory is a little fuzzy.

However, if my memory is correct, the discussion started with the
idea of classes in CSS "inheriting" from another class.  In other
words, authors frequently have a group of styles (say, styles to
give something a border and box shadow that fit in the page's
design) that apply to a bunch of different classes (say, article,
sidebar, footer-item), but it's a lot of maintenance work to do
either of:
 (1) changing the class attribute of each instance of, say,
     class="article" to say class="article frame shadowed-frame"
 (2) changing every selector matching .frame to instead match
     .frame, .article, .sidebar, .footer-item

I don't feel like the concept of "inheriting" really fits in CSS,
though.  It fits somewhat in CSS preprocessors, since underneath I
believe they end up doing something like (2) above.  But CSS
selectors are really based on a model of matching; class selectors
match class attributes in the content.  I think the concepts of
inheritance that I've seen described muddle that mental model and
cause authors to view selectors as "assigning" rather than
"matching".  (I think this is bad because I think that if authors
approach learning something with the wrong underlying model, they
may have success early on, but then find that things are confusing
once they get to the point where the model doesn't work anymore.)

So then I was asked how I thought this problem ought to be
addressed.

I basically came up with two alternatives (of which I think I prefer
the second):

 (a) Change class selectors so that instead of being purely
     equivalent to attribute selectors on the class attribute, they
     *default* to being equivalent to those attribute selectors but
     can be extended by authors (e.g., via an at-rule).

 (b) Add a new sort of selector (like a class selector, but
     different) that doesn't match anything by default, but that
     authors can associate with other selectors.  This is, I think,
     quite similar to the idea of mixins present in Tab's proposal
     [3], which is in turn similar to part of fantasai's constants
     proposal [4], though Tab and fantasai may not have thought of
     it as a selector.

In both of these options, combinators could probably be used on both
halves of the association, which means that the matching power is
equivalent to :matches() with combinators allowed in the argument.
It would, however, be possible to restrict the use of combinators at
the association or (potentially, if the syntax used is something
that doesn't use style rules, such as (B) or (C) in [5] below) at
the use of the new selector.  I tend to think it may be better not
to restrict the use of combinators, though.  In other words (using
the syntax from [5] again), one could write:

  /* box gets different styles inside the sidebar because of the
     sidebar's background colors */
  #sidebar $box { border: thin solid blue }
  /* figures inside articles are all boxes */
  .article .figure { matches: $box }

This ability to use selectors on both sides of the mixin could be
useful.

I don't currently have strong opinions about this syntax versus the
syntax in [3], but I thought it was worth posting the idea.

-David

[1] http://yehudakatz.com/
[2] http://www.stubbornella.org/
[3] http://lists.w3.org/Archives/Public/www-style/2011Mar/0478.html
[4] http://fantasai.inkedblade.net/style/specs/constants/
[5] The syntax sketches that I jotted down in February, but that I
    don't necessarily like all that much, were:

    (A)
      /* I didn't write this part down, but I think it was implied */
      $box { border: medium solid; }

      .news .tab {
        matches: $box;
      }

      .tab {
        matches: $box;
      }

    (B)
      /* I didn't write this part down, but I think it was implied */
      $box { border: medium solid; }

      @matches $box .tab;

    (C)
      $message-box {
        border: medium solid;
      }

      @matches .info-box $mesage-box;
      @matches .warning-box $message-box;

-- 
𝄞   L. David Baron                         http://dbaron.org/   𝄂
𝄢   Mozilla                           http://www.mozilla.org/   𝄂

Received on Sunday, 12 August 2012 20:17:11 UTC