The Evolution of Selectors

51
THE EVOLUTION OF SELECTORS - CSS Brigade - May 29, 2014 Dave Arthur

Transcript of The Evolution of Selectors

Page 1: The Evolution of Selectors

THE EVOLUTION OF SELECTORS - CSS Brigade - May 29, 2014Dave Arthur

Page 2: The Evolution of Selectors

OVERVIEW OF TALK1. Brief intro to how CSS evolves

2. Highlight some level 2/3 selectors

3. Look at some level 3/4 selectors

4. Talk about selector performance and maintenance

Page 3: The Evolution of Selectors

CSS IS CONSTANTLY EVOLVINGSelectors are now at Level 4. What does that mean?

Page 4: The Evolution of Selectors

Since CSS3, the spec is broken up into “modules”, each defining aspecific part of CSS. [Click image below to see live W3C page]

Page 5: The Evolution of Selectors

SELECTOR LEVELS

Page 6: The Evolution of Selectors

LEVEL 1ID, class, type/tag, descendantcombinator, :link, :visited,:active, :first-letter,:first-line

LEVEL 2Level 1 + universal(*), attribute,more combinators, :hover,:focus, :before, :after,:first-child

LEVEL 3Level 1 + 2 + structural pseudo-classes incl. :last-child and:nth-child(), UI pseudo-classes,negation (:not()) and :targetpseudo-classes

LEVEL 4Level 1 + 2 + 3 + more UI pseudo-classes, :matches(), :has(), timedimensional pseudo-classes (e.g.text to speech), link pseudo-classes,drag-and-drop-related pseudo-classes, grid-related pseudo-classes

Page 7: The Evolution of Selectors

LEVEL 2 SELECTOR HIGHLIGHTS

Page 8: The Evolution of Selectors

CHILD SELECTOR (COMBINATOR)X > Y

Instead of targeting all descendants of a particular container, itwill only target the direct children.

Page 9: The Evolution of Selectors

E.g.: Styling a nested news list

Transport Minister Lisa Raitt said electronicdevices can be used during takeoff, ascent,descent, landing.

Charlie Angus, Francoise Boivin warngovernment to tread carefully on internetprivacy.

Ottawa to allow air passengers to useelectronic devices on takeoff, landing

Flight attendants resist Transport Canada’s move to cut their numbers

Airline travel: 5 things you need to know about your flight rights

NDP wants privacy, security experts to probewarrantless data gathering

Declaration on mass surveillance calls for new privacy measures

Cyberbullying bill surveillance powers alarm Ontario privacy watchdog

Page 10: The Evolution of Selectors

<section class="news"> <ul class="news-list"> <li> <article class="article"> <h4 class="article-title"><a href="#"></a></h4> <figure class="article-thumb"><a href="#"><img></a></figure> <p class="article-desc"></p> <ul> <li><a href="#"></a></li> <li><a href="#"></a></li> </ul> </article> </li> <li> <article class="article"> <h4 class="article-title"><a href="#"></a></h4> <figure class="article-thumb"><a href="#"><img></a></figure> <p class="article-desc"></p> <ul> <li><a href="#"></a></li> <li><a href="#"></a></li> </ul> </article> </li> </ul></section>

Check out the for full HTMLCodePen

Page 11: The Evolution of Selectors

Using a descendant selector - over-rides needed:

.news-list li { /* Descendant */ list-style: none; padding: 0.5em; margin-bottom: 0.5em; border-bottom: 1px solid #d5d5d5;}

.article li { list-style: square; font-size: 0.9em; padding: 0; /* over-ride */ border-bottom: none; /* over-ride */}

Page 12: The Evolution of Selectors

Using a child selector - cleaner:

.news-list > li { /* Child selector - only selects top-level lis */ list-style: none; padding: 0.5em; border-bottom: 1px solid #d5d5d5;}

.news-list li { /* Descendant - common property in all lis (DRY) */ margin-bottom: 0.5em;}

.article li { list-style: square; font-size: 0.9em; /* no over-ride of bottom border or padding needed */}

Check out the for full CSSCodePen

Page 13: The Evolution of Selectors

ADJACENT SIBLING SELECTOR (COMBINATOR)

X + Y

Targets elements (Y) which have a particular element (X) direclypreceeding it.

Page 14: The Evolution of Selectors

E.g.: Simple inline menu with visual separators

• • •Home About Work Contact

Page 15: The Evolution of Selectors

<nav class="menu" role="navigation"> <ul class="menu-list"> <li><a href="#">Home</a></li> <li><a href="#">About</a></li> <li><a href="#">Work</a></li> <li><a href="#">Contact</a></li> </ul></nav>

.menu-list > li:before { content: '\2022'; padding-right: 0.5em; margin-left: 0.5em; }.menu-list > li:first-child:before { content: none;}

Page 16: The Evolution of Selectors

Cleaner way using “+” combinator

<nav class="menu" role="navigation"> <ul class="menu-list"> <li><a href="#">Home</a></li> <li><a href="#">About</a></li> <li><a href="#">Work</a></li> <li><a href="#">Contact</a></li> </ul></nav>

.menu-list > li + li:before { content: '\2022'; padding-right: 0.5em; margin-left: 0.5em; }

Check out the for exampleCodePen

Page 17: The Evolution of Selectors

ATTRIBUTE SELECTORS (LEVEL 2 & 3)elem[attr="value"] 2elem[attr̂="str"] 3elem[attr$="str"] 3elem[attr*="str"] 3

Full list of attribute selectors:http://dev.w3.org/csswg/selectors4/#attribute-selectors

Page 18: The Evolution of Selectors

elem[attr="value"]Since there are many different input element types (especiallywith HTML5) this selector is great for targeting specific types.

input[type="text"], input[type="email"] { border: 1px solid #999; padding: 5px 10px; }

input[type="submit"] { background-color: #0065BD; color: #fff; border-radius: 10px; padding: 10px; }

Page 19: The Evolution of Selectors

elem[attr̂="str"]Selects elements which have an attribute value beginning with a

particular substring.

E.g. Styling links with different URLs:

Contact us by: Secure Form Email

Page 20: The Evolution of Selectors

<section class="contact"> <h4>Contact us by:</h4> <a href="https://secure.domain.com/contact">Secure Form</a> <a href="mailto:[email protected]">Email</a></section>

.contact > a:before { font-family: 'icomoon'; /* other font declarations */ margin-right: 0.25em;}

.contact > a[href̂="https://secure.domain.com"]:before { content: "\e602";}

.contact > a[href̂="mailto"]:before { content: "\e601";}

Page 21: The Evolution of Selectors

elem[attr$="str"]Selects elements which have an attribute value ending with a

particular substring.

E.g. Styling links to different file types:

Download file: PDF Word

Page 22: The Evolution of Selectors

<section class="file-download"> <h4>Download file:</h4> <a href="http://domain.com/downloads/file.pdf">PDF</a> <a href="http://domain.com/downloads/file.doc">Word</a></section>

.file-download > a:before { font-family: 'icomoon'; /* other font declarations */ margin-right: 0.25em;}

.file-download > a[href$=".pdf"]:before { content: "\e603";}

.file-download > a[href$=".doc"]:before { content: "\e604";}

Page 23: The Evolution of Selectors

elem[attr*="str"]Selects elements which the substring somewhere in the attribute

value.

Great for modular code. E.g. Styling icon links with different typesof icons:

Follow us: Twitter YouTube

Page 24: The Evolution of Selectors

<section class="social"> <h4>Follow us:</h4> <a class="social-link" href="#"><i class="icon-font-twitter"></i>Twitter</a> <a class="social-link" href="#"><i class="icon-sprite-youtube"></i>YouTube</a></section>

i[class*="icon-"] { display: inline-block;}i[class*="icon-font-"]:before { font-family: 'icomoon'; /* other font declarations */}.icon-font-twitter:before { content: "\e606";}i[class*="icon-sprite-"] { background: url(lib/images/icon-sprite.png) no-repeat; /* other sprite declarations */}.icon-sprite-youtube { width: 24px; height: 28px; background-position: 0 0;}.social-link:hover > .icon-sprite-youtube { background-position: 0 -28px;}

Page 25: The Evolution of Selectors

LEVEL 3 & 4 SELECTOR HIGHLIGHTSStructural nth-child() / nth-of-type() 3

Logical :not(), :matches() 3/4

Relational :has() 4

Page 26: The Evolution of Selectors

:nth-child()Now in Level 3 we can choose any child of a containing element.

Heard ’round Springfield

Full demo and code

Page 27: The Evolution of Selectors

HTML:

<section class="character-list"> <article class="char simpsons"> <a href="#"> <img src="homer-simpson.jpg"><q>...</q> </a> </article> <article class="char flandereses"> <a href="#"> <img src="maude-flanders.jpg"><q>...</q> </a> </article> <article class="char bouviers"> <a href="#"> <img src="selma-bouvier.jpg"><q>...</q> </a> </article> ...</section>

Page 28: The Evolution of Selectors

Default positioning of quote bubble:

.char { position: relative;}.char q { position: absolute; top: -70%; left: -50%; /* other styles */}.char q:before, .char q:after { position: absolute; /* other styles */}.char q:before { right: 50%; bottom: -30px; /* other styles */}.char q:after { right: 52%; bottom: -50px; /* other styles */}

Page 29: The Evolution of Selectors

nth-child() positioning of quote bubble:

/* Left-most column */.char:nth-child(6n+1) q { left: -100%;}.char:nth-child(6n+1) q:after { right: 45%;}/* 2nd column in from left */.char:nth-child(6n+2) q { left: -85%;}.char:nth-child(6n+2) q:after { right: 40%;}/* Right-most column */.char:nth-child(6n+6) q { left: 20%;}.char:nth-child(6n+6) q:before { right: 50%;}.char:nth-child(6n+6) q:after { right: 60%;}

Page 30: The Evolution of Selectors

:nth-child()We get problems if we mix element types.

SIMPSONS

FLANDERESES

Page 31: The Evolution of Selectors

HTML:

<section class="character-list"> <h4 class="section-title">Simpsons</h4> <article class="char simpsons"> <a href="#"> <img src="homer-simpson.jpg"><q>...</q> </a> </article> ... <h4 class="section-title">Flandereses</h4> <article class="char flandereses"> <a href="#"> <img src="ned-flanders.jpg"><q>...</q> </a> </article> ...</section>

Page 32: The Evolution of Selectors

Fixed with :nth-of-type()SIMPSONS

FLANDERESES

Full demo and code

Page 33: The Evolution of Selectors

nth-of-type() positioning of quote bubble:

/* Left-most column */.char:nth-of-type(6n+1) q { left: -100%;}.char:nth-of-type(6n+1) q:after { right: 45%;}/* 2nd column in from left */.char:nth-of-type(6n+2) q { left: -85%;}.char:nth-of-type(6n+2) q:after { right: 40%;}/* Right-most column */.char:nth-of-type(6n+6) q { left: 20%;}.char:nth-of-type(6n+6) q:before { right: 50%;}.char:nth-of-type(6n+6) q:after { right: 60%;}

Page 34: The Evolution of Selectors

:not(s) & :not(s1[, s2]*)As of Level 3 we can exclude an element(s) from selections. When Level 4 is supported :not() will take a selector list.

Page 35: The Evolution of Selectors

<section class="character-list"> <article class="char simpsons"> <a href="#"> <img src="homer-simpson.jpg"><q>...</q> </a> </article> <article class="char flandereses"> <a href="#"> <img src="maude-flanders.jpg"><q>...</q> </a> </article> <article class="char bouviers"> <a href="#"> <img src="selma-bouvier.jpg"><q>...</q> </a> </article></section>

.char:not(.simpsons) img { opacity: 0.3;}.char:not(.simpsons) q { display: none;}

Page 36: The Evolution of Selectors

:matches(s1[, s2]*)When supported :matches() will allow us to include a selectoror group of selectors in the selection.

Page 37: The Evolution of Selectors

Previous slide uses the vendor prefixed selector to simulate what:matches() will do. :matches() is currently not supported in browsers I’vetested. Note: I would not recommend using the :any() selector as it’s on its wayout.

:any()

/* Using :matches() - STANDARD but no support yet */.char:matches(.simpsons, .flandereses) img { border-color: #0065BD;}

/* Using vendor prefixed :any() - NON-STANDARD */.char:-moz-any(.simpsons, .flandereses) img { border-color: #0065BD;}.char:-webkit-any(.simpsons, .flandereses) img { border-color: #0065BD;}

/* Using classes */.simpsons img, .flanders img { border-color: #0065BD;}

Page 38: The Evolution of Selectors

One useful application of :matches() would be for styling HTML5 headings.Since the document outline has been revised you can have multiple h1s on a page.Example CSS from MDN doing it the looong way:

/* Level 0 */h1 { font-size: 30px;}/* Level 1 */section h1, article h1, aside h1, nav h1 { font-size: 25px;}/* Level 2 */section section h1, section article h1, section aside h1, section nav h1,article section h1, article article h1, article aside h1, article nav h1,aside section h1, aside article h1, aside aside h1, aside nav h1,nav section h1, nav article h1, nav aside h1, nav nav h1, { font-size: 20px;}/* Level 3 *//* ... don't even think about it*/

Page 39: The Evolution of Selectors

When :matches() is supported:

/* Level 0 */h1 { font-size: 30px;}/* Level 1 */:matches(section, article, aside, nav) h1 { font-size: 25px;}/* Level 2 */:matches(section, article, aside, nav):matches(section, article, aside, nav) h1 { font-size: 20px;}/* Level 3 */:matches(section, article, aside, nav):matches(section, article, aside, nav):matches(section, article, aside, nav) h1 { font-size: 15px;}

Page 40: The Evolution of Selectors

:has(rs1[, rs2]*)Apparently new this year. When supported the :has() relational pseudo willallow us to select for elements which have a particular relationship to theelement(s) passed as parameters.

Examples from W3C spec:

Matches only a elements that contain an img child:

a:has(> img)

Matches a dt element immediately followed by another dt element:

dt:has(+ dt)

Matches section elements that don’t contain any heading elements:

section:not(:has(h1, h2, h3, h4, h5, h6))

Page 41: The Evolution of Selectors

NEED TO SUPPORT OLDER IE VERSIONS? is JS polyfill for Level 3 selectors.Selectivzr

Page 42: The Evolution of Selectors

SELECTOR PERFORMANCE

Page 43: The Evolution of Selectors

SOME CONSIDERATIONSBrowsers read selectors from right to left

Ideally want right-most “key” selector to be specific

IDs and classes are most efficient

Combinators (descendant, child, etc), attributes, pseudo-classes are not as efficient

I know what you are thinking...

Page 44: The Evolution of Selectors

OTHER CONSIDERATIONS. will be dead soon. Browsers are much

better than they used to be!

You should probably focus on other web performance bestpractices first (e.g. minimizing, using fonts/SVG or sprites,optimizing image file sizes, CDNs, caching, etc.)

There isn’t one solution–different websites require differentstrategies

Focus on maintainability...

IE6 is dead IE7 and 8

Page 45: The Evolution of Selectors

MAKING YOUR CSS MORE MAINTAINABLEDon’t tag qualify id or class selectors

Don’t “over-qualify” selectors

Minimize selector depth

Minimize general descendant/child selectors

Modularize code

Choose a naming/coding convention (SMACSS, BEM, etc.)

Decide what level of CSS efficiency is right for your site.

Page 46: The Evolution of Selectors

DON’T TAG QUALIFY ID OR CLASS SELECTORS/* Qualified */div#main-content {}ul.menu-list {}

/* Unqualified */#main-content {}.menu-list {}

ISSUESSelectors tied to particular mark up pattern

Increasing selector specificity

Page 47: The Evolution of Selectors

DON’T “OVER-QUALIFY” SELECTORS/* Over-qualified */.nav ul li a {}

/* Better */.nav a {}

ISSUESBrowsers will need to look up document tree anyways. Addingul and li not necessary

Increasing selector specificity

Page 48: The Evolution of Selectors

MINIMIZE SELECTOR DEPTH/* Not great */.content section ul li a {}

/* Better choices - Add class "list" to ul */.list > li > a {} .list a {}

The key is we reduced the number of levels the browser has towalk up.

Alternatives? Put class on li or individual a elements. Betterefficiency but at cost of maintenance?

Page 49: The Evolution of Selectors

MINIMIZE GENERAL DESCENDANT/CHILDSELECTORS

Especially involving universal selector. E.g.:

#main-content section {}ul li {}.nav > * {}

Alternatives? Can you use classes? Better mark up?

Page 50: The Evolution of Selectors

MODULARIZE CODEKeeps selector depth low

Great for portability with minimal CSS revisions

CSS preprocessors make modularizing easy. Create differentpartial file for each module.

<article class="news-item"> <h2 class="news-item-title">Title of Article</h2> <a href="#"><img class="news-item-thumb" src="" alt=""></a> <p class="news-item-excerpt">Excerpt</p></article>

.news-item {} /* module base class */

.news-item-title {}

.news-item-thumb {}

.news-item-excerpt {}

Page 51: The Evolution of Selectors

THANK YOU FOR LISTENING! QUESTIONS?Additional Resources