: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
: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- pseudo-classes:nth-child(3n) :nth-last-child(odd) :nth-of-type(5) :nth-last-of-type(3n+1)
starting from the top or bottom
:nth- pseudo-classesTarget element or elements based on argument passed to the selector
:nth-of-type(even) :nth-of-type(odd) :nth-of-type(An+B) :nth-last-child(An+B [of S])
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%;}
:nth-child(An+B [of S]) :nth-last-child(An+B [of S])
li:nth-child(2n of .foo) li:nth-child(3n+1 of .bar)
Specificity is 0-1-0 for :nth-child(An+B), plus specificity of the most specific
complex selector in S
select the 3rd li with the class of foo
:nth-child(3 of li.foo) /* matches #8 */
Select the 3rd li if it has the class foo
li.foo:nth-child(3) /* no match */
Match every even row of the visible rows
tr:nth-child(even of :not([hidden]))
:root
Selects the document root, which is <html>
:not -
Negation pseudo-classE:not(s1)
div:not(.excludeMe)
Specificity: weight of (s1), not the :not.
*:not(h1) /* 0 - 0 - 1 */ *:not(.class) /* 0 - 1 - 0 */ *:not(#myId) /* 1 - 0 - 0 */
Supported everywhere since IE9
E:not(s1, s2)
div:not(.excludeMe, .excuseYou)
Reminder: if a browser doesn't recognize a pseudo-class, the entire selector block fails
"RESOLVED: Drop individual invalid selectors from selector lists in *all* selector functions that take such lists, *except* for :not()."
Most specific of (s1, .s2, #s3), in this case 1-0-0.
:is(s1, s2) :matches(s1, s2)
RESOLVED: Rename :matches() to :is() and deprecate :matches()
E:is(s1, s2)
li:is([title], [role]) a {}
li[title] a,
li[role] a {}
:is() doesn't get invalidated if a parameter is invalid.
:matches(s1, s2):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, :-moz-any & :-webkit-any for FF & Chrome
:-webkit-any(article, aside) :-webkit-any(article, aside) h1 {}
:-moz-any(article, aside) :-moz-any(article, aside) h1 {}
:matches(article, aside) :matches(article, aside) h1 {}
:is(article, aside) :is(article, aside) h1 {}
article article h1,
article aside h1,
aside article h1,
aside aside h1 { }
article, aside {
article, aside {
h1 {
/* sass nesting*/
}
}
}
a:-webkit-any(.foo, .bar, .bam) span {}
a:-moz-any(.foo, .bar, .bam) span {}
a:matches(.foo, .bar, .bam) span {}
a:is(.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(:is(.foo, .bar, .bam)),
nav a:not(.foo, .bar, .bam),
nav a:not(.foo):not(.bar).not(.bam) {
}
:-webkit-any(header, aside, footer) [contenteditable]:hover {
color: blue;
cursor: pointer;
}
:-moz-any(header, aside, footer) [contenteditable]:hover {
color: blue;
cursor: pointer;
}
:matches(header, aside, footer) [contenteditable]:hover {
color: blue;
cursor: pointer;
}
:is(header, aside, footer) [contenteditable]:hover {
color: blue;
cursor: pointer;
}
:is(header, aside, footer) [contenteditable]:hover { /* CSS Selectors level 4 */
color: blue;
cursor: pointer;
}
header, aside, footer { /* sass */
[contenteditable]:hover {
color: blue;
cursor: pointer;
}
}
header [contenteditable]:hover { /* CSS Selectors level 2 */
color: blue;
cursor: pointer;
}
aside [contenteditable]:hover {
color: blue;
cursor: pointer;
}
footer [contenteditable]:hover {
color: blue;
cursor: pointer;
}
The specificity is the specificity of its most specific argument:
:is(ul, ol, .list) > [hidden] { ... /* 0-2-0 */
ul > [hidden],
ol > [hidden], /* 0-1-1 */
.list > [hidden] { /* 0-2-0 */
<ol> <li hidden>This matches</li> <li>This doesn't</li> </ol>
:where()
Same as :is(s1, s2), but with no specificity
Specificity sometimes makes life hard:
a:not(:hover) {
text-decoration: none;
}
nav a { /* has lower specificity */
text-decoration: underline;
}
:where() adds no specificity weight
a:where(:not(:hover)) {
text-decoration: none;
}
nav a { /* has greater specificity */
text-decoration: underline;
}
:has(s1, s2)
Parent Selector
Parent selector
document.querySelectorAll(':has(s1, s2)');
Contains a header
document.querySelectorAll('header:has(h1, h2, h3, h4, h5, h6)');
Contains no headers
document.querySelectorAll('header:not(:has(h1, h2, h3, h4, h5, h6))');
Contains something that is not a header
document.querySelectorAll('header:has(:not(h1, h2, h3, h4, h5, h6))');
CanIUse.com
Matches if the element has the lang attribute
html[lang|="en"]
Matches if the element is in the language, as determined by document language, headers, and lang attribute on ancestors.
p:lang(en)
:lang(l1, l2)
- Matches and language common to the country. Accepts comma separated values.
:lang(\*-ch, \*-be)
:dir() -
Matches content that is left to right (ltr) or right to left (rtl) based on
language, dir attribute, or surrounding text.
:dir(rtl)
Any element with an href attribute
a:link /* unvisited links */ a:visited /* visited links */
CSS Selectors Level 4
a:any-link /* a:link, a:visited */
:local-link /* target absolute URL == document URL */
/* :not(:local-link) == external link */
:any-link
Any element with an href attribute:
<a> <area> <link>
:any-link is the same as :is(:link, :visited)
:local-link
:local-link {
text-decoration: none;
color: inherit;
}
a:local-link {
/* match links on this page or section of page (#fragment) */
}
a:not(:local-link) {
/* on a different document or site */
}
:hover :active :focus
Note: always style :focus when you style :hover
:focus-visible :focus-within
:-moz-focusring
You can toggle :hover, :active, :focus, and
:focus-within in DevTools
:hover :active :focus
a:visited:hover button:active:focus
Never, ever, ever do....
*:focus { outline: none; }
Improving accessibility:
:focus-visible matches active elements:focus-visible when focused, even if
interaction doesn’t affect :focus.:focus-visible spot, the newly focused element should match
:focus-visible.
:focus-visible spot, the newly focused element should NOT
match :focus-visible either.:focus-visible is applied to :focus as well. :focus-visible:target
:target
myPage.html#anchor
<div id="anchor">ipsum lorem....
div:target::first-line {
font-weight: bold;
}
:target presentation:target-within
:target :target-within
The :target-within pseudo-class applies to elements for which the :target pseudo
class applies as well as to an element whose descendant in the flat tree (including non-element nodes, such
as text nodes) matches the conditions for matching :target-within.
: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()
E || F
col.selected || td {
/* matches all cells within the column's scope*/
}
:nth-col(An+B) :nth-last-col(An+B)
:current :current(s) :future :past
:playing :paused
There are lots of Developer Tool featues related to selectors, including pseudo classes.
:hover, :active, :visited,
:focus, and :focus-within.
Add this HTML to the page you created in the intro
<figure>
<div data-type="H">
<div></div>
<div data-value="A">♥</div>
</div>
<div data-type="C">
<div></div>
<div data-value="A">♣</div>
</div>
<div data-type="D">
<div></div>
<div data-value="A">♦</div>
</div>
</figure>
There are three playing cards, each with a face side and a back, all inside a <figure>
container. For right now every card is an ace.
Create the following selector blocks in your css file:
The figure
figure {}
all the cards
[data-type] {}
backs of the cards
[data-type] > :first-child
card faces
[data-value]
first, second, and last card
[data-type]:first-of-type {}
[data-type]:nth-of-type(2) {}
[data-type]:last-of-type {}
faces of first, second and last cards
[data-type]:first-of-type [data-value]{}
[data-type]:nth-of-type(2) [data-value] {}
[data-type]:last-of-type [data-value] {}
red cards
[data-type="H" i],
[data-type="D" i] {}
black cards
[data-type="C" i],
[data-type="S" i] {}
hovered card
[data-type]:hover {}
Now that we know how to target cards without classes, let's add some classes to make our code easier to
discuss. You can now add the card, back, and face classes to your HTML.
<figure>
<div class="card" data-type="H">
<div class="back"></div>
<div class="face" data-value="A">♥</div>
</div>
<div class="card" data-type="C">
<div class="back"></div>
<div class="face" data-value="A">♣</div>
</div>
<div class="card" data-type="D">
<div class="back"></div>
<div class="face" data-value="A">♦</div>
</div>
</figure>
Your original selectors still all work.