When you get right down to it, CSS rules select matching sets of elements. Sets and logic gates are two of the most fundamental and powerful concepts in computer science – at some level it is upon their backs that just about everything else builds. Despite this, until pretty recently CSS has never had features that hinted at the concept of a set and that seems a shame because integrating the language of logic/sets could be a powerful combination.
What’s changing?
After many years during “the great stagnation” HTML and CSS are moving along quickly again. HTML has increased our ability to express semantics and CSS is adding new selector powers. Selectors Level 3 is a done deal, work is well underway on Selectors Level 4 and we’ve already got a wiki of features for Selectors Level 5. Likewise, we are adding long-needed features like Regions, scoped stylesheets, Shadow DOM and Generated Content. All of these things combine to create a really positive future where CSS can really begin to live up to its potential and the visuals pertaining to good structures can managed via CSS without requiring changes to markup.
Two pseudo-classes in particular – in a group called Logical Combinators – currently :matches (some implemenations call it :any) and :not begin to bring with them some interesting possibilities. Currently they are very limited and can only accept simple (or compound – depending on the level) selectors, but eventually they could accept complex selectors. When that day comes we could begin talking about things in terms of sets.
A Proposal
4 Logical Combinators which can take complex selectors:
- :anyof (:matches?) Filters elements based on whether they match ANY of the provided selector(s) (that is, selectors are OR’ed together) which may express different paths in the same tree.
- :allof
Filters elements based on whether they match ALL of the provided selector(s) (that is, selectors are AND’ed together) which may express different paths in the same tree. - :noneof (:not ?) Filter elements based on whether they match NONE of the provided selector(s) (that is, selectors are NOR’ed together) which may express different paths in the same tree.
- :oneof
Filters elements based on whether they match EXACTLY ONE of the provided selector(s) (that is, selectors are XOR’ed together) which may express different paths in the same tree.
An Example:
Given some rich markup that describes a structure in some local semantic terms (semantics important to my domain)…
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<div class="cars"> | |
<div class="domestic"> | |
<div class="new" id="a"> | |
<div class="cheap small efficient"><p class="car">2012 Ford Fiesta</p></div> | |
<div class="quality efficient"><p class="car">2012 Chrysler 300</p></div> | |
<div class="quality fast performance"><p class="car">2012 Dodge Charger</p></div> | |
</div> | |
<div class="used" id="b"> | |
<div class="cheap small efficient"><p class="car">2009 Ford Fiesta</p></div> | |
<div class="cheap"><p class="car">2004 Chevy Malibu</p></div> | |
<div class="quality fast"><p class="car">2010 Dodge Charger</p></div> | |
</div> | |
</div> | |
<div class="foreign"> | |
<div class="new" id="c"> | |
<div class="cheap"><p class="car">2012 Kia Forte</p></div> | |
<div class="quality"><p class="car">2012 BMW 525i</p></div> | |
</div> | |
<div class="used" id="d"> | |
<div class="cheap"><p class="car">2009 Kia Forte</p></div> | |
<div class="cheap efficient"><p class="car">2005 Toyota Camry</p></div> | |
<div class="quality"><p class="car">2009 Audi R5</p></div> | |
</div> | |
</div> | |
</div> |
I can use logical sets to add styles…
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* Style the cars that are new and have quality as well as domestic and peformance */ | |
.cars div:allof(.new .quality, .domestic .performance) p { | |
color: red; | |
} | |
/* Style the cars that are foreign and used or domestic, new and effiecient. */ | |
.cars div:anyof(.foreign .used, .domestic .new .efficient) p { | |
color: blue; | |
} | |
/* Style the efficient cars that are neither domestic and used nor foreign and new. */ | |
.efficient:noneof(.domestic .used, .foreign .new) p { | |
color: green; | |
} | |
/* Style the cars that are only one of quality or fast (but not both). */ | |
.cars div:oneof(.quality, .fast) p { | |
font-weight: bold; | |
} |
Prollyfilling…
All of the above are prollyfilled currently and come “out of the box” with hitchjs (works in IE9 and all evergreen browsers) – they are all prefixed with -hitch-*. If you’d like to play around with it, simply add the following script include:
<
script
type
=
"text/javascript"
src
=
"http://www.hitchjs.com/dist/hitch-0.6.1.min.js"
></
script
>
and add a data attribute to any <style> or <link> tag which contains hitch prollyfilled rules, for example:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<style type="text/css" data-hitch-interpret> | |
/* Style the cars that are foreign and used or domestic, new and effiecient. */ | |
.cars div:-hitch-anyof(.foreign .used, .domestic .new .efficient) p { | |
color: blue; | |
} | |
</style> |
Truly no matter if someone doesn’t understand afterward its up to other people that they will help, so here it occurs.