Estelle Weyl | @estellevw | Github | Press key to advance.

Select This!
CSS Selectors

http://estelle.github.com/selectors/

Me

Estelle Weyl

www.standardista.com

@estellevw

@standardista

HTML5 and CSS3 for the Real WorldCSS: The Definitive GuideMObile HTML5Web Performance Daybook

We're Hiring

Selectors

selectorA {
   property1: value1;
   property2: value2;
}

selectorB {
   property1: value3;
   property2: value4;
}

Selectors

selector:pseudo-class::pseudo-element {
    -vendor-property: value;
}

selector[attribute],
selector ~ relation {
    property: -vendor-value;
    -vendor-property: -vendor-value;
    -vendor-property: weirdsyntax;
}

Basic Selectors

<ul>
<li id="myID" class="myClass">item 1</li>
<li class="myClass">item 2</li>
<li>item 3</li>
</ul> 
#myID
ID
.myClass
class
li
tag name

Play Time

Try it out

Selectors in CSS Level 1

E
E F
.class
#ID
:link
:active

Lots 'o Selectors

  • CSS Level 1 Selectors

  • E
  • .class
  • #id
  • E F
  • :link
  • :active
  • CSS Level 2 Selectors

  • *
  • E > F
  • E + F
  • E[attribute]
  • E[attribute=value]
  • E[attribute~=value]
  • E[attribute|=value]
  • :first-child
  • :lang(en)
  • :focus
  • :hover
  • :visited
  • :before
  • :after
  • :first-letter
  • :first-line

Lots 'o Selectors

  • CSS Selects Level 3

  • ::before
  • ::after
  • ::first-letter
  • ::first-line

  • E[attribute^=value]
  • E[attribute$=value]
  • E[attribute*=value]

  • E ~ F
  • :root
  • E:last-child
  • E:only-child
  • E:nth-child(n)
  • E:nth-last-child(n)
  • E:first-of-type
  • E:last-of-type
  • E:only-of-type
  • E:nth-of-type(n)
  • E:nth-last-of-type(n)

  • E:empty
  • E:not(selector)
  • E:target

Lots 'o Selectors

  • UI / Selectors #4

  • E:enabled
  • E:disabled
  • E:checked
  • E:default
  • E:valid
  • E:invalid
  • E:in-range
  • E:out-of-range
  • E:required
  • E:optional
  • E:read-only
  • E:read-write

CSS Selectors Level 4

  • :blank
  • :indeterminate
  • :placeholder-shown
  • :not(s1, s2)
  • :matches(s1, s2)
  • :has(rs1, rs2)
  • [foo="bar" i]
  • :dir(ltr)
  • :lang(zh, *-hant)
  • :any-link
  • :scope
  • :current
  • :focus-ring
  • :drop
  • :drop(active)
  • :drop(valid)
  • :drop(invalid)
  • :user-invalid
  • E >> F
  • F || E
  • :nth-column(n)
  • :nth-last-column(n)

More...

Maybe

  • ::selection
  • :scope-context()
  • :current(s)
  • :past
  • :future
  • :host
  • :host()
  • :host-context()
  • ::shadow
  • ::content
  • :column(selector)
  • E /foo/ F
  • E! > F
  • :local-link
  • :nth-match()

All the selectors

Open

Specificity (SpeciFISHity)

Download

Specificity: How it works

  • 1-0-0: ID selector
  • 0-1-0: Class selector (Also attribute selector & pseudoclass)
  • 0-0-1: Element Selector
  • The * selector, or global selector, has no value.

    * {} 0-0-0 

    Combinators, like ~, >, and + have no value

    ul li {} 0-0-2
    ul > li {} 0-0-2

Relational selectors & Combinators

  1. item 1
  2. item 2
  3. item 3
    • item a
    • item b
    • item c
  4. hasaclass
  5. item 5
  6. item 6
  7. item 7
ul li,
ol li
descendant selector
matches nested <li>s
ol > li
child selector 
matches <li>s in <ol> but not nested <ul>
li.hasaclass + li
adjacent sibling 
NEW  (IE7+)
li.hasaclass ~ li
general sibling selector
matches later siblings, but not nested.
E >> F
NEW: descendant combinator

Selectors API

var chil = $('#bar .foo');

Natively

var el   = document.querySelector('#bar');

var chil = el.querySelectorAll('.foo');

or

chil = document.querySelectorAll('#bar .foo');

Attribute selectors

element[attribute]
Select elements containing the named attribute
img[alt] {}
     <img src="image.jpg" alt="accessible">
     <img src="image.jpg" title="inaccessible">
form [type] {}
     <input type=date>
     <select>

CSS 2 attribute selectors

E[attr]
Element E that has the attribute attr with any value.
E[attr="val"]
Element E that has the attribute attr with the exact, case-sensitive if attribute is case sensitive, value val.
E[attr|=val]
Element E whose attribute attr has a value val or begins with val- ("val" plus "-").
p[lang|="en"]{/* <p lang="en-us">  <p lang="en-uk"> */ }
E[attr~=val]
Element E whose attribute attr has within its value the space-separated full word val.
a[title~=more] {/* <a title="want more info about this?">}

Attribute Selectors in CSS Selectors Level 3

E[attr^=val]
Element E whose attribute attr starts with the value val.
a[href^=mailto] {background-image: url(emailicon.gif);}
a[href^=http]:after {content: " (" attr(href) ")";}
E[attr$=val]
Element E whose attribute attr ends in val . 
a[href$=pdf] {background-image: url(pdficon.gif);}
a[href$=pdf]:after {content: " (PDF)";}
E[attr*=val]
Element E whose attribute attr matches val anywhere within the attribute. Similar to E[attr~=val] above, except the val can be part of a word.

Note: Multiple attributes work! a[title][href]

Attribute Selectors 4: Case Insensitivity

E[foo="bar" i]
input[type=checkbox i]

Only relevant if attribute value is case senstive
(as it is for all attributes in XHTML)

CodePen test page

Attribute Selectors Recap

input[placeholder] {/* matches any input with a placeholder */}
input[type=email] {/* exact match */}
abbr[title~=unicorn] {/* matches unicorn but not unicorns */}
abbr[title|=en] {/* matches en-us and en-uk */}
a[href^=mailto] {/* starts with */}
a[href$=pdf]{/* ends in */}
abbr[title*=unicorn] {/* matches unicorn and unicorns */}
abbr[title*=UNICORN i] {/* matches unicorn and UnIcOrNs */}
E:[att] /* have the attribute at all */
E:[att=val] /* exact */
E:[att~=val] /* val is a space separated word */
E:[att|=val] /* with a dash */
E:[att^=val] /* begins with val */
E:[att$=val]  /* ends with val */
E:[att*=val]  /* val is anywhere as a substring */
E:[att*=VAL i]  /* anywhere as a case insenstive substring */
@media print{
  abbr[title]:after {
    content: "(" attr(title) ")";
  }
  a[href^=http]:after {
    content: "(" attr(href) ")";
  }
}

Using attribute selectors

Attribute Selectors

Note: The top line of the example is editable. The CSS will impact the contents on the rest of the page.

UI pseudo-classes

Based on current state of UI

  :enabled

  :disabled

  :checked

  :indeterminate (Level 4)
input[type=checkbox]:checked + label {
  color: red;
}

Basic User Interface Module Level 3 (CSS3 UI)

Form related UI pseudo-classes

:default
:valid
:invalid

:required
:optional

:in-range
:out-of-range

:read-only
:read-write

:placeholder-shown

:user-invalid

Form related UI pseudo-classes

input:valid { border: 1px solid green;}
input:invalid { border: 1px solid red;}
input:required,
input[aria-required="true"] {border-width: 5px;}
input:optional {border-width: 10px;}
input:out-of-range { background-color: pink;}
input:in-range { background-color:lightgreen;}

<input type="number" min="5" max="7"
  required aria-required="true"/>

<input type="number" min="0" step="0.1" max="10"/>

UI selectors

UI Selectors

Test them out for yourselves

Open in new page

UI selectors

UI Selectors

Test them out for yourselves

Open in new page

Structural selectors

:root

:empty 

:blank 

:nth-child()

:nth-last-child()

:first-child (2)

:last-child

:only-child

:nth-of-type()

:nth-last-of-type()

:first-of-type

:last-of-type

:only-of-type
  • Target elements on the page based on their relationships to other elements in the DOM.
  • Updates dynamically if page updates.
  • Reduced need for extra markup, classes and IDs

First, last, & only

:first-child

:last-child

:first-of-type

:last-of-type

:only-child

:only-of-type

Easier to explain by example

First, last, & only

First, last and only

nth pseudo-classes

:nth-child(3n)

:nth-last-child(odd)

:nth-of-type(5)

:nth-last-of-type(3n+1) 

Target element or elements based on argument passed to the selector

  • :nth-of-type(even)
  • :nth-of-type(odd)
  • :nth-of-type(an+b)

Structural Selectors

li:first-child,
li:last-child {
  font-weight: bold;
}
li:first-of-type,
li:last-of-type{
  text-decoration:line-through;
}
li:nth-child(even) {
  background-color: #CCC;
}
li:nth-child(3) {
  color: #CCC;
}
li:nth-of-type(odd) {
  background-color: #FFF;
}
li:nth-of-type(4n) {
  color: hsl(205, 87%, 50%);
}
li:nth-of-type(3n-1) {
  text-align: right;
}

  • item 1
  • item 2
  • item 3
  • item 4
  • item 5
  • item 6
  • item 7
  • item 8
  • item 9
  • item 10

Before Flexbox

  • 1
  • 1
  • 2
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3
  • 4
 li:only-of-type{width: 100%;}

 li:nth-of-type(1):nth-last-of-type(2),
 li:nth-of-type(2):nth-last-of-type(1){width: 50%;}

 li:nth-of-type(1):nth-last-of-type(3),
 li:nth-of-type(3):nth-last-of-type(1),
 li:nth-of-type(2):nth-last-of-type(2){width: 33.33%;}

 li:nth-of-type(1):nth-last-of-type(4),
 li:nth-of-type(2):nth-last-of-type(3),
 li:nth-of-type(3):nth-last-of-type(2),
 li:nth-of-type(4):nth-last-of-type(1){width: 25%;}

Structural Selectors

Structural Selectors

Flag with Structural Selectors

USA Flag

Simpler Flag with Structural Selectors

USA Flag

:root

:root

Selects the document root, which is <html>

  • Declare font-size on :root if using rem units
  • Style :root only if showing <head> (as in our exercise files)
  • In CSS4, define Defining Variables on root. (see Variables module)

example

:empty & :blank pseudo-classes

E:empty
<E/>
<E></E>
<E><!-- this is a comment --></E>
<E title="this is an empty element"/>

No browser support...

E:blank
<E>   <!-- has white space -->   </E>
:-moz-whitespace-only

:not - Negation pseudo-class

E:not(s1)
div:not(.excludeMe)

Supported everywhere since IE9

:not(s1, s2)

E:not(s1, s2)
div:not(.excludeMe, .excuseYou)

Safari Only

:not - Negation pseudo-class

Negation Selectors

:matches(s1, s2)

E:matches(s1, s2)

li:matches([title], [role]) a {}
li[title] a, 
li[role] a {}

:matches(#home, #contact) aside :matches(a:active, a:focus){}
#home aside a:active, 
#contact aside a:active,
#home aside a:focus, 
#contact aside a:focus {}

Safari only

Experimental :any

E:matches(s1, s2)
:-webkit-any(article, aside) :-webkit-any(article, aside) h1,
:-moz-any(article, aside) :-moz-any(article, aside) h1 {
}
a:matches(.foo, .bar, .bam) span,
a:-webkit-any(.foo, .bar, .bam) span,
a:-moz-any(.foo, .bar, .bam) span {
}
nav a:not(:matches(.foo, .bar, .bam)),
nav a:not(:-webkit-any(.foo, .bar, .bam)),
nav a:not(:-moz-any(.foo, .bar, .bam)),
nav a:not(.foo, .bar, .bam) {
}
nav a:not(.foo):not(.bar).not(.bam){
}

Removed from the specification

Reference combinator

E /attr/ F
label /for/ input

Parent Selector

Parent selector

E! > F
:has

Contains a header

header:has(h1, h2, h3, h4, h5, h6)

Contains no headers

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

Contains something that is not a header

header:has(:not(h1, h2, h3, h4, h5, h6))
CanIUse.com

Language Pseudo Classes

CSS 2.1

html[lang|="en"]
p:lang(en)

CSS Selectors Level 4

:lang(*-ch)
:dir(ltr|rtl)
:dir => FF only, :lang(*-ch) => none

Link Pseudo Classes

a with an href attribute

:link
:visited
CSS Selectors Level 4

:any-link
:local-link
:local-link(n)
:any-link is the same as :matches(:link, :visited)

User Action Pseudo Classes

:hover
:active
:focus

Note: always style :focus when you style :hover

:focus-ring
:focus-within
:drop
:drop()

:hover, :active, :focus

:hover
:active
:focus
a:visited:hover
button:active:focus

Never, ever, ever do....

*:focus { outline: none; }

elements that can be active

Drag and Drop Pseudo Classes

  • :drop
    drop targets while the user is “dragging”.
    Unfortunately, dropzone attribute is not yet supported
  • :drop(active)
    current drop target for the drag operation.
  • :drop(valid
    drop target is valid for the object currently being dragged, like correct filetype.
  • :drop(invalid)
    drop target is invalid for the object currently being dragged, i.e. doesn't except the filetype of object being dragged.
  • :drop(valid active)
    matches active drop target if it’s valid

:target

:target
myPage.html#anchor

<div id="anchor">ipsum lorem....

div:target::first-line {
  font-weight: bold;
}

:target pseudo-class

:target example

:scope

:scope

Matches elements that are a reference point for selectors to match against.

/* Selects a scoped element */
:scope {
  background-color: blue;
}

In CSS, :scope is the :root, since we don't have scoped CSS yet.

In JS, :scope matches the element returned by querySelector(), querySelectorAll(), matches(), or el.closest()

Grid-structural selectors

Column combinator

E || F
col.selected || td {
  /* matches all cells within the column's scope*/
}
:nth-column(An+B)
:nth-last-column(An+B)

Time dimensional

:current
:future
:past

Video & Audio

:playing
:paused

Specificity (SpeciFISHity)

Download

Specificity (SpeciFISHity)

Download

Specificity: How it works

  • 0-0-0: Global selector
  • 1-0-0: ID selector
  • 0-1-0: Class selector (Also attribute selector & pseudoclass)
  • 0-0-1: Element Selector

Specificity: The less than obvious

The * selector, or global selector, has a specifity of 0.

Combinators, like ~, >, >>, space, and + have no value

ul li {} 0-0-2
ul > li {} 0-0-2

:not has no value, but parameter selector does

.myClass:not(p) {} 0-1-1

Specificity is not inheritance

Avoid !important

Hacking specificity

.disabled {cursor: default !important;}
p.btn {cursor: pointer;}

v.

.disabled.disabled.disabled {cursor: default;}
p.btn {cursor: pointer;}

Hacking specificity with IDs

#TheirWidget {background-color: blue !important;}
#3rdPartyWidget {background-color: white;}
v.
#TheirWidget#TheirWidget {background-color: blue ;}
#3rdPartyWidget {background-color: white;}

Hack in case of emergency

a:not(#idDoesNotExist#idDoesNotExist#idDoesNotExist) 

!Even More Important

Pseudo elements

::first-line
::first-letter
::selection (not in specification)
::before
::after
    

Pseudo-classes select elements that already exist.
Pseudo-elements create "faux" elements you can style.

::first-letter

You can even pretty drop-caps with :first-letter, but make sure to apply it to p:first-of-type so your site not too ugly. Code for drop cap.

p:first-of-type::first-letter {
  position: relative;
  top: 8px;
  float: left;
  font-size: 3em;
  line-height: 1;
  color: hsl(205, 87%, 50%);
  padding: 0 4px 2px 0;
  font-weight: bold;
}
 
Drop Cap

::selection

.thisSlide *::selection {
   background-color: #990000;
   color: #ffffff;
}
    

::before and ::after

p:before {
  content: "before content - ";
  font-weight: bold;
}
p:after{
  content: " - after content";
  font-weight: bold;
}
<p>the content</p>

the content

<p>
    <before>before content - </before>
        the content
    <after> - after content</after>
</p>
Try it out

Generated Content

Generated Content

Test them out for yourselves

Generated Content: UI selectors

UI Selectors

Test them out for yourselves

Open in new page

Additional Pseudo-elements

Highlight Pseudo-elements:

::selection
::inactive-selection
::spelling-error
::grammar-error

Other Pseudo-elements:

::marker
::placeholder
::content

::selection

.thisSlide *::selection {
   background-color: #F63;
}

Disabling ::selection

For mobile but impacts desktop too:

.thisSlide {
  -webkit-tap-highlight-color: #bada55;
  -webkit-user-select: none;
  -webkit-touch-callout: none;
}

IE10 Specific

::-ms-browse
::-ms-value
::-ms-check
::-ms-clear
::-ms-expand
::-ms-fill
::-ms-fill-lower
::-ms-fill-upper
::-ms-reveal
::-ms-thumb
::-ms-ticks-after
::-ms-ticks-before
::-ms-tooltip
::-ms-track

Shadow DOM

Many, many more pseudo-elements with prefixes currently treated as a shadow DOM

  • ::-webkit-progress-bar
  • ::-webkit-progress-value
  • ::-webkit-meter-even-less-good-value
  • ::-webkit-inner-spin-button /outer-spin-button
  • ::-webkit-validation-bubble / arrow-clipper /arrow /message
  • ::-webkit-scrollbar
  • ::-webkit-scrollbar-button / thumb / track
  • Mozilla Pseudo-elements and pseudo-classes

Pseudo Elements

Me

Estelle Weyl

www.standardista.com

@estellevw

@standardista

HTML5 and CSS3 for the Real WorldCSS: The Definitive GuideMObile HTML5Web Performance Daybook
#PerfMattersConf.com

We're Hiring