devnotes.

Types of Selectors

CSS offers many ways to target elements, from broad to extremely specific.

/* Type selector — targets all <p> elements */
p { margin: 0; }

/* Class selector — targets elements with class="card" */
.card { border: 1px solid #ddd; }

/* ID selector — targets the single element with id="header" */
#header { background: #333; }

/* Attribute selector — targets inputs with type="email" */
input[type="email"] { border-color: blue; }

/* Descendant selector — targets <a> anywhere inside .nav */
.nav a { text-decoration: none; }

/* Direct child selector — targets <li> that are direct children of .nav */
.nav > li { display: inline-block; }

/* Pseudo-class — targets <a> only while hovered */
a:hover { color: orange; }

/* Universal selector — targets everything */
* { box-sizing: border-box; }

A practical guideline for choosing selectors:

  • Use classes for anything reusable across multiple elements — this is the most common and flexible choice.
  • Use IDs sparingly, mainly for unique page landmarks or JavaScript hooks, since ID-based rules are hard to override later (high specificity).
  • Use type selectors (p, h1) for broad, page-wide resets or defaults.
  • Combine selectors to be precise: .card h2 targets <h2> only inside elements with class card, without needing a new class name for every heading variant.

Overusing IDs or writing overly long combined selectors (div.container ul.list li.item a.link) makes CSS brittle — prefer flat, class-based rules wherever possible.