css level 4 selectors - environments for...

77
CSS Level 4 Selectors: The good, the weird, and the awesome @jcutrell

Upload: others

Post on 29-May-2020

26 views

Category:

Documents


0 download

TRANSCRIPT

CSS Level 4 Selectors: The good, the weird,

and the awesome

@jcutrell

CSS DEV CONF 2015!!!

Hi! I’m Jonathan.

@JCutrell @DeveloperTea @whiteboardis

@JCutrell @DeveloperTea @whiteboardis

Enjoy your tea.

@JCutrell @DeveloperTea @whiteboardis

@JCutrell @DeveloperTea @whiteboardis

Vote if you’d like!

bit.ly/votecss4

@JCutrell @DeveloperTea @whiteboardis

Where I learn.

@JCutrell @DeveloperTea @whiteboardis

CSS Level 4!

Today’s talk:

EVERY new selector!

Read the specs some time. (not today.)

Level 4 Extends and Replaces 1, 2.1 (wtf), and 3

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)Element does not match compound selector

s1 OR compound selector s2.

: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>

Bonus: “*” means more than you might think.

: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)

: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)

The “coffee cup cabinet”: Selection based on

contents.

Select a menu that has a link that is outbound.

: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: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:any-link

<a href=""></a> <area href=""></area> <link href=""></link>

E:any-link

Equivalent to:

:matches(:visited, :link) {}

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

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.

Drag and Drop

E:drop E:drop(active) E:drop(valid) E:drop(invalid)

Drag and Drop

<div draggable>Drag Me!</div> <div dropzone="copy">Drop here!</div>

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.

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

div p a {} // equivalent to: div>>p>>a {}

(“Descendant” combinator)

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 (>>>)”

Table selectors

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>

F || E

(Column combinator)

.wham || span {}

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)

The End! We covered it all!

@JCutrell @DeveloperTea @whiteboardis

Thank you!

@JCutrell @DeveloperTea @whiteboardis

@JCutrell @DeveloperTea @whiteboardis

Vote if you’d like!

bit.ly/votecss4