HuntExams Academy logo
HTML/CSSBeginner#css#selectors

What is the difference between pseudo-classes and pseudo-elements?

Answer

Pseudo-classes (single colon, like :hover, :nth-child, :focus) select elements based on state or position. Pseudo-elements (double colon, like ::before, ::after, ::first-line) create or target a sub-part of an element that doesn't exist as a separate DOM node.

Example

a:hover { color: red; }
li:nth-child(odd) { background: #f5f5f5; }
.quote::before { content: '\201C'; }

Detailed explanation

Pseudo-classes and pseudo-elements extend CSS selectors, but they answer different questions. A pseudo-class asks, “Which element matches this condition?” A pseudo-element asks, “Which part of this element should be styled?” Pseudo-classes normally use a single colon, such as :hover, :focus, and :nth-child(). Pseudo-elements use double colons, such as ::before, ::after, and ::first-line. This distinction matters because it lets you style interactions, document structure, and selected portions of content without adding unnecessary HTML elements.

A pseudo-class selects an existing element according to a condition, such as its interaction state or position among siblings. For example, a:hover { color: red; } makes a link red while a pointing device hovers over it. The rule li:nth-child(odd) { background: #f5f5f5; } matches list items whose positions among all element siblings are odd, counting from one. The browser evaluates these conditions and updates matching styles when relevant state or structure changes. No extra DOM node is created, and a pseudo-class does not have to represent a temporary state.

A pseudo-element targets a portion of an element’s rendered content or introduces generated content. For example, .quote::before { content: '\201C'; } inserts an opening curly quotation mark before the element’s content. For ::before and ::after, a content value other than none or normal is generally needed to generate the pseudo-element; an empty string can create a decorative box. Meanwhile, ::first-line styles the first formatted line of text, which can change when the container width changes. These are not separate HTML nodes that you can retrieve with ordinary DOM queries.

Interviewers usually expect the conceptual difference, correct examples, and awareness of practical details. In specificity calculations, pseudo-classes generally count like classes, whereas pseudo-elements count like type selectors; exceptions include :where(), which adds no specificity. Browsers accept legacy single-colon forms such as :before for compatibility, but modern code should use ::before. Keep essential information in HTML rather than relying on generated content, and provide keyboard-visible focus styling instead of relying only on hover.

Key points to remember

  • Pseudo-classes select existing elements based on conditions such as state or sibling position.
  • Pseudo-elements target rendered portions of elements or introduce generated content.
  • Use single colons for pseudo-classes and double colons for modern pseudo-element syntax.
  • ::before and ::after usually need a content declaration; ::first-line does not.
  • Pseudo-classes generally contribute class-level specificity; pseudo-elements contribute type-level specificity.

Common mistakes candidates make

  • Saying every pseudo-class describes an interaction state, overlooking structural selectors such as :nth-child().
  • Claiming pseudo-elements create ordinary DOM nodes that JavaScript can select directly.
  • Assuming :nth-child(odd) counts only siblings with the same tag name rather than all element siblings.

Likely follow-up questions

Can a pseudo-class and pseudo-element be combined?

Yes: .button:hover::before targets the button’s ::before pseudo-element while the button is hovered. If ::before supplies generated content, it still needs an appropriate content value.

What is the difference between :nth-child() and :nth-of-type()?

li:nth-child(2) matches an li only if it is the second element child of its parent. li:nth-of-type(2) matches the second li among its siblings, ignoring siblings with different tag names when counting.

Why does :before work if pseudo-elements use double colons?

CSS originally used single-colon syntax for pseudo-elements, so browsers retain support for :before, :after, :first-line, and :first-letter. Prefer double colons in new code to distinguish pseudo-elements clearly; newer pseudo-elements generally require them.

Interview tip: Start with “condition versus part,” explain one example of each, and then mention the colon syntax and generated-content behaviour.

Related Interview Questions

1
HTML/CSSIntermediate#css#selectors

Explain the :nth-child() selector with examples.

Open
2
HTML/CSSIntermediate#css#selectors

What CSS attribute selectors are available?

Open
3
HTML/CSSIntermediate#css#selectors

What is the difference between adjacent sibling (+) and general sibling (~) combinators?

Open