selectorA { property1: value1; property2: value2; } selectorB { property1: value3; property2: value4; }
Estelle Weyl | @estellevw | Github | Press → key to advance.
selectorA { property1: value1; property2: value2; } selectorB { property1: value3; property2: value4; }
selector:pseudo-class::pseudo-element { -vendor-property: value; } selector[attribute], selector ~ relation { property: -vendor-value; -vendor-property: -vendor-value; -vendor-property: weirdsyntax; }
<ul> <li id="myID" class="myClass">item 1</li> <li class="myClass">item 2</li> <li>item 3</li> </ul>
E E F .class #ID :link :active
1-0-0
: ID selector0-1-0
: Class selector (Also attribute selector & pseudoclass)0-0-1
: Element SelectorThe * 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
var chil = $('#bar .foo');
Natively
var el = document.querySelector('#bar'); var chil = el.querySelectorAll('.foo');
or
chil = document.querySelectorAll('#bar .foo');
function hasaclass(slctr){ var i = j = 0, elements = document.querySelectorAll('.cur .ex li'), cur = document.querySelectorAll('.cur .ex ' + slctr); for (; i < elements.length; i++){ elements[i].classList.remove('active'); } for (; j < cur.length; j++){ cur[j].classList.add('active'); } }
img[alt] {} <img src="image.jpg" alt="accessible"> <img src="image.jpg" title="inaccessible"> form [type] {} <input type=date> <select>
p[lang|="en"]{/* <p lang="en-us"> <p lang="en-uk"> */ }
a[title~=more] {/* <a title="want more info about this?">}
a[href^=mailto] {background-image: url(emailicon.gif);} a[href^=http]:after {content: " (" attr(href) ")";}
a[href$=pdf] {background-image: url(pdficon.gif);} a[href$=pdf]:after {content: " (PDF)";}
Note: Multiple attributes work! a[title][href]
E[foo="bar" i]
input[type=checkbox i]
Only relevant if attribute value is case senstive
(as it is for all attributes in XHTML)
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) ")"; } }
Note: The top line of the example is editable. The CSS will impact the contents on the rest of the page.
Based on current state of UI
:enabled :disabled :checked :indeterminate (Level 4)
input[type=checkbox]:checked + label { color: red; }
:default :valid :invalid :required :optional :in-range :out-of-range :read-only :read-write :placeholder-shown :user-error or :user-invalid
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"/>
:root :empty :blank :nth-child() :nth-last-child() :first-child* :last-child :only-child :nth-of-type() :nth-last-of-type() :first-of-type :last-of-type :only-of-type
:first-child :last-child :first-of-type :last-of-type :only-child :only-of-type
Easier to explain by example
: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
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; }
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%;}
:root
Selects the document root, which is <html>
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
E:not(s1)
div:not(.excludeMe)
Supported everywhere since IE9
E:not(s1, s2)
div:not(.excludeMe, .excuseYou)
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 {}
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){ }
Reference combinator
E /attr/ F
label /for/ input
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
CSS 2.1
html[lang|="en"]
p:lang(en)
CSS Selectors Level 4
:lang(*-ch)
:dir(ltr|rtl):dir => FF only, :lang(*-ch) => none
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)
:hover :active :focus
Note: always style :focus when you style :hover
:focus-ring :focus-within
:drop :drop()
:hover :active :focus
a:visited:hover button:active:focus
Never, ever, ever do....
*:focus { outline: none; }
:drop
dropzone
attribute is not yet supported:drop(active)
:drop(valid
:drop(invalid)
:drop(valid active)
:target
myPage.html#anchor <div id="anchor">ipsum lorem.... div:target::first-line { font-weight: bold; }
: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()
Column combinator
E || F
col.selected || td { /* matches all cells within the column's scope*/ }
:nth-column(An+B) :nth-last-column(An+B)
:current :future :past
:playing :paused
0-0-0
: Global selector1-0-0
: ID selector0-1-0
: Class selector (Also attribute selector & pseudoclass)0-0-1
: Element SelectorThe * 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
.disabled {cursor: default !important;} p.btn {cursor: pointer;}
v.
.disabled.disabled.disabled {cursor: default;} p.btn {cursor: pointer;}
#TheirWidget {background-color: blue !important;} #3rdPartyWidget {background-color: white;}v.
#TheirWidget#TheirWidget {background-color: blue ;} #3rdPartyWidget {background-color: white;}
a:not(#idDoesNotExist#idDoesNotExist#idDoesNotExist)
::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.
.thisSlide *::selection { background-color: #990000; color: #ffffff; }
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
Highlight Pseudo-elements:
::selection ::inactive-selection ::spelling-error ::grammar-error
Other Pseudo-elements:
::marker ::placeholder ::content
.thisSlide *::selection { background-color: #F63; }
For mobile but impacts desktop too:
.thisSlide { -webkit-tap-highlight-color: #bada55; -webkit-user-select: none; -webkit-touch-callout: none; }
::-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
Many, many more pseudo-elements with prefixes currently treated as a shadow DOM