What types of CSS selectors are there?
Simple (
*,p,.btn,#main), attribute ([type="email"],[href^="https"]), combinators (nav a,ul > li,h2 + p,h2 ~ p), pseudo-classes for a state (:hover,:nth-child(2n),:has(img)), pseudo-elements for a part (::before,::placeholder), and grouping with commas. See selectors.What is the difference between div p, div > p, div + p and div ~ p?
div pmatches anypinside adivat any depth;div > ponly direct children;div + ponly thepright after adiv;div ~ pevery laterpsibling of adiv.HTML<style> .list li { color: gray; } .list > li { font-weight: bold; } h3 + p { color: crimson; } h3 ~ p { font-style: italic; } </style> <ul class="list"><li>Child of .list: gray and bold</li></ul> <div class="list"><ul><li>Grandchild of .list: gray, not bold</li></ul></div> <h3>Heading</h3> <p>Right after the heading: crimson and italic</p> <p>Later sibling: italic only</p>Sibling combinators only look forward; reaching a previous sibling or a parent needs
:has().How is CSS specificity calculated?
A three-part score (a, b, c): a counts ids, b classes, attributes and pseudo-classes, c type selectors and pseudo-elements. Compared left to right, so one id beats any number of classes.
HTML<style> #intro { color: green; } .lead.big { color: blue; } p.lead { color: red; } p { color: gray; } </style> <p id="intro" class="lead big">Green: the id wins</p> <p class="lead big">Blue: (0, 2, 0) beats (0, 1, 1)</p> <p class="lead">Red: (0, 1, 1) beats (0, 0, 1)</p>*and combinators add nothing;:not(),:is()and:has()take their most specific argument;:where()is always zero.What does !important do, and why is it considered bad practice?
!importantputs a declaration in a higher cascade tier: it beats every normal declaration, inline styles included, whatever the specificity, and loses only to another!importantthat wins the usual comparison, or to a running transition. It is bad practice because each later override needs another one. It is fine for utilities like.hiddenand against a third-party widget's inline styles. More in !important.What is the difference between a pseudo-class and a pseudo-element?
A pseudo-class selects an element in a state or position (
:hover,:checked,:first-child); a pseudo-element styles a part of an element or adds a box that is not in the HTML (::before,::first-letter,::placeholder). Pseudo-classes take one colon, pseudo-elements two (:beforestill works for old CSS2 code).a:hover { text-decoration: underline; } /* a state */ li:nth-child(odd) { background: #f3f4f6; } /* a position */ p::first-line { font-weight: bold; } /* a part */How do ::before and ::after work, and why is my ::before not showing?
They insert a generated first and last child, rendered only when
contentis set (content: ""for a shape).HTML<style> .required::after { content: " *"; color: crimson; } .tag { position: relative; padding-left: 18px; } .tag::before { content: ""; position: absolute; left: 0; top: 50%; width: 10px; height: 10px; border-radius: 50%; background: #16a34a; transform: translateY(-50%); } </style> <label class="required">Email</label> <p class="tag">Online</p>If one does not show:
contentis missing; the element is a replaced element likeimg, whose content comes from outside the document; or it is empty and inline, so it needsdisplay: inline-blockto take a size.What is the difference between :nth-child() and :nth-of-type()?
:nth-child(n)counts all siblings whatever their tag, then checks the rest of the selector;:nth-of-type(n)counts only siblings with the same tag.HTML<style> p:nth-child(2) { background: #fde68a; } p:nth-of-type(2) { color: #2563eb; font-weight: bold; } </style> <div> <h3>Heading (child 1)</h3> <p>Paragraph, child 2: yellow background</p> <p>Paragraph, child 3, second p: blue text</p> </div>So
p:nth-child(1)matches nothing here: the first child is theh3. Both take formulas such as2n+1or-n+3(the first three).How do attribute selectors work?
They match by an attribute's presence or value:
[attr],[attr="x"](exact),^=(starts with),$=(ends with),*=(contains),~=(one word in a list). Addifor a case-insensitive match:[type="EMAIL" i]. Specificity equals a class.HTML<style> input[type="email"] { border: 2px solid #2563eb; } [data-state="error"] { color: crimson; } [class*="badge-"] { padding: 2px 6px; border-radius: 4px; background: #e5e7eb; } </style> <input type="email" placeholder="email: blue border"> <input type="text" placeholder="text: default border"> <p data-state="error">data-state="error" is red</p> <span class="badge-new">badge-new</span> <span class="badge-sale">badge-sale</span>A common use is JavaScript state: set
data-state="open"and style[data-state="open"].What do :is(), :where() and :has() do?
:is()and:where()match any selector in their list.:is()takes its most specific argument's specificity and:where()zero, which suits defaults meant to be overridden.:has()matches an element by what it contains or what follows it, the parent selector CSS lacked, in Chrome, Safari and Firefox (since 121).HTML<style> .task { padding: 6px; border-radius: 6px; } .task:has(input:checked) { text-decoration: line-through; background: #dcfce7; } .btn { background: #7c3aed; } /* wins, even though it comes first */ :where(.btn) { color: white; background: #2563eb; } /* specificity (0, 0, 0) */ </style> <label class="task"><input type="checkbox"> Tick me, the row styles itself</label> <p><button class="btn">.btn overrides :where(.btn)</button></p>body:has(...)on a large page can be slow; anchor it to a small container, as the MDN :has() performance notes advise.What is the difference between :root and html in CSS?
In an HTML page both select the
<html>element, but:rootis a pseudo-class, so its specificity is (0, 1, 0) againsthtml's (0, 0, 1). It also matches the root element of SVG and XML documents. That is why custom properties go on:root: a laterhtmlrule cannot override them by accident.HTML<style> :root { --brand: #2563eb; } html { --brand: crimson; } p { color: var(--brand); } </style> <p>Blue: :root (0, 1, 0) beats html (0, 0, 1), even though the html rule comes later.</p>
CSS Selectors and Specificity Interview Questions
Which selector matches what, and which rule wins when several match.
10 questions