Level 4 Extends and Replaces 1, 2.1 (wtf), and 3
(If it worked before and isn’t redefined in level 4, it will still
work.)
:not(s1, s2)<div class="card"> <h3 class="card__title">Banana Stand</h3> <div class="card__content"> <img class="card__image" src="banana.jpg"> <p>You’ll always find money here.</p> <ul> <li>Mr Manager</li> <li>Manager</li> <li>Sandwiches</li> </ul> </div> </div>
:not(s1, s2)<div class="card"> <h3 class="card__title">Banana Stand</h3> <div class="card__content"> <img class="card__image" src="banana.jpg"> <p>You’ll always find money here.</p> <ul> <li>Mr Manager</li> <li>Manager</li> <li>Sandwiches</li> </ul> </div> </div>
// CSS Level 3 *:not([class^="card"]) { border: 1px solid orange; }
:not(s1, s2)<div class="card"> <h3 class="card__title">Banana Stand</h3> <div class="card__content"> <img class="card__image" src="banana.jpg"> <p>You’ll always find money here.</p> <ul> <li>Mr Manager</li> <li>Manager</li> <li>Sandwiches</li> </ul> </div> </div>
// CSS Level 4 *:not([class^=“card”], p) { border: 1px solid orange; }
:not(s1, s2)<div class="card"> <h3 class="card__title">What is the world on?</h3> <div class="card__content"> <ul> <li>Turtles</li> <li>Turtles</li> <li>Turtles</li> <li>Turtles</li> <li>Turtles</li> <li>Turtles
<ul> <li>Recursive Turtles</li>
</ul> </li>
<li></li> <li>Turtles</li> <li>Turtles</li> <li>Turtles</li> <li>Turtles</li> <li>Turtles</li> <li>Turtles</li> <li>Turtles</li> <li>Turtles</li> <li>Turtles</li> <li>Turtles</li> <li>Turtles</li> <li>Turtles</li> <li>Turtles</li> <!-- ... all the way down --> </ul> </div> </div>
:not(s1, s2)<div class="card"> <h3 class="card__title">What is the world on?</h3> <div class="card__content"> <ul> <li>Turtles</li> <li>Turtles</li> <li>Turtles</li> <li>Turtles</li> <li>Turtles</li> <li>Turtles
<ul> <li>Recursive Turtles</li>
</ul> </li>
<li></li> <li>Turtles</li> <li>Turtles</li> <li>Turtles</li> <li>Turtles</li> <li>Turtles</li> <li>Turtles</li> <li>Turtles</li> <li>Turtles</li> <li>Turtles</li> <li>Turtles</li> <li>Turtles</li> <li>Turtles</li> <li>Turtles</li> <!-- ... all the way down --> </ul> </div> </div>
:not(s1, s2)<div class="card"> <h3 class="card__title">What is the world on?</h3> <div class="card__content"> <ul> <li>Turtles</li> <li>Turtles</li> <li>Turtles</li> <li>Turtles</li> <li>Turtles</li> <li>Turtles
<ul> <li>Recursive Turtles</li>
</ul> </li>
<li>Turtles</li> <li>Turtles</li>
li:not(:nth-child(7n), :last-child, :empty, ul ul li){ border: 1px solid orange; }
:not(s1, s2)li:not(:nth-child(7n), :last-child, :empty, ul ul li){ border: 1px solid orange; }
// Select all li’s that are not any of: // - 7n children, // - last children, // - empty (including text nodes), // - or nested inside a secondary <ul>
:focus, :link {}
// is not technically equivalent to
*:focus, *:link {}
Bonus: “*” means more than you might think.
:focus, :link {}
// is not technically equivalent to
*:focus, *:link {}
Bonus: “*” means more than you might think.
* is a universal selector that selects all elements in the default namespace.
:matches(s1, s2).card h1, .card h2, .card h3, .sidebar h1, .sidebar h2, .sidebar h3, .article-header h1, .article-header h2, .article-header h3 { font-weight: 400; color: orange; }
Ever done this?
:matches(s1, s2)
.card-or-article-heading { font-weight: 400; color: orange; }
And then did this and felt gross?
:matches(s1, s2)
.card-or-article-heading { font-weight: 400; color: orange; }
And then did this and felt gross?
:matches(s1, s2)
.card, .sidebar, .article-header { h1,h2,h3 { font-weight: 400; color: orange; } }
(SCSS)
:matches(s1, s2)
:matches(.card, .sidebar) :matches(h1, h2, h3){ font-weight: 400; color: orange; }
The new hotness:
:matches(s1, s2)
:matches(.card, .sidebar) :matches(h1, h2, h3){ font-weight: 400; color: orange; }
The new hotness:
:matches(s1, s2)
:matches(.card, .sidebar) :matches(h1, h2, h3){ font-weight: 400; color: orange; }
.card h1, .card h2, .card h3,
.sidebar h1, .sidebar h2, .sidebar h3,
.article-header h1, .article-header h2, .article-header h3 { font-weight: 400; color: orange; }
:matches(s1, s2):matches(.card, .sidebar) :matches(h1, h2, h3){ font-weight: 400; color: orange; }
.card h1, .card h2, .card h3,
.sidebar h1, .sidebar h2, .sidebar h3,
.article-header h1, .article-header h2, .article-header h3 { font-weight: 400; color: orange; }
:has(s1, s2)
Disclaimer: This won’t ever work in CSS. (But you should know about it, cause it will work in JavaScript, and in other “static” contexts, such
as book rendering frameworks.)
:has(s1, s2)<menu> <a href="http://somewhere.com">External Link</a> <a href="/internal-link">Internal Link</a> <a href="http://mysite.com/internal-link">Internal Link!</a> </menu>
:has(s1, s2)
menu:has(a:not([href^="/"], [href^="http://mysite.com"])){ background-image: url("img/out-arrow.png"); background-position: left center; padding-left: 20px; }
menu:has(a:not([href^="/"], [href^="http://mysite.com"])){ background-image: url("img/out-arrow.png"); background-position: left center; padding-left: 20px; }
Select any menu element with a link that links out to an external site.*
*This does not cover all cases, but we’ll act like it does for the sake of time.
:has(s1, s2)
:has(s1, s2)<menu> <a href="http://somewhere.com">External Link</a> <a href="/internal-link">Internal Link</a> <a href="http://mysite.com/internal-link">Internal Link!</a> </menu>
:has(s1, s2)$("menu").filter(function(item){ var anchors = $(item).find("a").filter(function(anchor){ return ($(anchor).attr("href").indexOf("/") == -1 && $(anchor).attr("href").indexOf("http://mysite.com") == -1); }); return anchors.length; });
E[foo=“bar” i]
<div data-username="JCutrell"></div> <div data-username="jcutrell"></div> <div data-username="Jcutrell"></div> <div data-username="JCUTRELL"></div>
E[foo=“bar” i]
[data-username="JCutrell"] [data-username="jcutrell"] [data-username="Jcutrell"] [data-username="JCUTRELL"]
E[foo=“bar” i]
[data-username="jcutrell" i]
[data-username="JCutrell"] [data-username="jcutrell"] [data-username="Jcutrell"] [data-username="JCUTRELL"]
E:dir(ltr)
Any element that resolves to the direction argument provided.
(The only relevant arguments are currently “ltr” and “rtl”.)
E:lang(zh, “*-hant”)
Matches any element of type E that is designated as written in any dialect of “zh” (Chinese) or otherwise written with Chinese characters (*-hant)
E:scope<div> <style scoped> div:scope { background-color: orange; } </style> Here's some content. </div>
Time-dimensional Pseudo-classes
E:current E:current(s) E:past E:future
(Used for things like spoken transcripts)
Time-dimensional Pseudo-classes
<video controls preload="metadata"> <source ... /> <track label="English" kind="subtitles" srclang="en" src="..." default> </video>
No one supports .vtt yet. But they will.
E:read-write / E:read-only
<!-- Read-write: --> <input> <textarea></textarea> <div contenteditable></div>
<!-- Read-only: --> <div></div> <input disabled>
E:placeholder-shown<!-- Matches until user focuses the input: --> <input placeholder="Your email">
<!-- Doesn't match --> <input> <input value="Some value"> <input value="Some value" placeholder="Your email">
E:default
<select> <option selected>This is the default</option> <option>Not the default at all</option> </select>
select :default {}
E:default
select :default {}
Default buttons, checked-by-default inputs, option elements that have the selected attribute
<select> <option selected>This is the default</option> <option>Not the default at all</option> </select>
E:indeterminate<!-- is it checked or not? --> <input type=“checkbox">
<!-- what is the progress value? --> <progress></progress>
<!-- how would one determine? -->
E:in-range / E:out-of-range
<!-- in range --> <input type="range" min="0" max="42" value=“17">
<!-- out of range --> <input type="range" min="0" max="42" value="56">
E:valid / E:invalid<!-- invalid --> <input type="url" value="not.a.url"> <input type="email" value="Assistant to the regional manager"> <input type="range" min="0" max="10" value="12">
<!-- valid --> <input required value="Anything at all"> <input> <input type="email" value="[email protected]">
<!-- neither valid nor invalid --> <p>Now, this is a story all about how, My life got flipped-turned upside down</p>
E:valid / E:invalid
You are now a Real Programmer™:
<input pattern="[0-9]{3}-[0-9]{3}-[0-9]{4}">
423-867-5309: valid!
E:user-invalid
The same as :invalid, except only after the user has interacted with the input.
Why, you ask?
If the input is required and is blank, it is invalid
on load.
E:valid / E:invalid, E:user-valid / E:user-invalid
Bonus! You can use these psuedo classes on inputs
AND on fieldsets.
E:required / E:optional
<input required><!-- :required --> <input><!-- :optional (default for read/write) —> <div></div><!-- neither -->
E:blank<!-- both :empty and :blank --> <div></div>
<!-- :blank, but not :empty --> <div> </div>
<!-- Neither :blank nor :empty --> <div>Anything with non-whitespace.</div>
E >> F(“Descendant” combinator)
“introduced to give the descendant
combinator a visible, non-whitespace form
and to bridge the gap between the child
combinator (>) and the shadow-piercing
descendant combinator (>>>)”
F || E(Column combinator)
<table> <col> <col span=2> <col class="wham"> <tr> <td>Who?</td> <td><span>Ann</span></td> <td>Egg</td> <td><span>Her?</span></td> </tr> </table>
F || E(Column combinator)
How to select an item based on which
column it belongs to in a table?
(Select the span that is in the column with
the class “wham”.)
F || E(Column combinator)<table> <col> <col span=2> <col class="wham"> <tr> <td>Who?</td> <td><span>Ann</span></td> <td>Egg</td> <td><span>Her?</span></td> </tr> </table>
E:nth-column(n), E:nth-last-column(n)
:nth-column(2n) <table> <col> <col span=2> <col class="wham"> <tr> <td>Who?</td> <td><span>Ann</span></td> <td>Egg</td> <td><span>Her?</span></td> </tr> </table>
E:nth-column(n), E:nth-last-column(n)
:nth-column(2n) <table> <col> <col span=2> <col class="wham"> <tr> <td>Who?</td> <td><span>Ann</span></td> <td>Egg</td> <td><span>Her?</span></td> </tr> </table>
:nth-last-column(2n)