VS Vikesh Singh

Courses CSS Lesson 2

CSS · LESSON 2 OF 18

Selectors: Targeting the Right Element Every Time

· 5 min read

In the last lesson, you learned that CSS rules target HTML elements and apply styles to them.

In the last lesson, you learned that CSS rules target HTML elements and apply styles to them. But how exactly does a rule "find" the right element on a page that might have hundreds of elements? The answer is selectors. A selector is the part of a CSS rule that comes before the curly braces, and its only job is to point at the element or elements you want to style. Getting comfortable with selectors is one of the most important skills in CSS, because almost every bug a beginner has comes down to the selector matching the wrong thing, or not matching anything at all.

Classes And IDs Explained

The simplest selector is the element selector, which you already saw with h1. It matches every element of that tag name on the page. But most real pages need more precision than that, because you rarely want every single paragraph or every single div to look the same. This is where classes and IDs come in.

A class is a label you can put on any HTML element, and you can reuse the same class on as many elements as you like. In CSS, you select a class using a dot.

<p class="warning">Be careful with this setting.</p>
<p class="warning">This also needs attention.</p>
.warning {
  color: darkred;
  font-weight: bold;
}

Both paragraphs get the same styling because they share the class name. This is the backbone of real-world CSS: define a reusable class once, apply it anywhere.

An ID is similar but meant to be unique, used only once per page, typically for something like a specific section or a single important element. You select an ID with a hash symbol.

<div id="profile-card">...</div>
#profile-card {
  border: 1px solid #ccc;
  padding: 16px;
}

A very common beginner mistake is overusing IDs for styling. IDs come with a strength problem we will cover properly in the specificity lesson, but for now, just know the general rule used by most professional developers: prefer classes for styling, and save IDs mostly for JavaScript hooks or page anchors, not for day-to-day CSS.

Combining Selectors For Precision

Selectors can also be combined to get more specific. A few you will use constantly:

<div class="card">
  <h2>Tony Stark</h2>
  <p>Engineer, inventor, Iron Man.</p>
</div>
.card h2 {
  margin-top: 0;
}

.card p {
  color: #555;
}

Here, .card h2 is a descendant selector. It means "find any h2 that is anywhere inside an element with class card," not every h2 on the page. This is extremely useful because it lets you scope styles to a specific section instead of accidentally affecting the whole page.

There is also the child selector, written with a greater-than sign, which is stricter than the descendant selector: it only matches a direct child, not a grandchild buried deeper.

.card > p {
  font-style: italic;
}

If the paragraph were nested inside another div inside .card, this rule would not match it, but the plain descendant selector .card p would. This distinction trips up a lot of beginners who expect both to behave the same way.

You can also select multiple different things in one rule using a comma, which avoids repeating the same style block over and over.

h1, h2, h3 {
  font-family: Arial, sans-serif;
}

And you can select an element based on an attribute, which is especially handy for form inputs.

input[type="email"] {
  border-color: blue;
}

Common Selector Mistakes

A common mistake beginners make is writing a selector that is technically correct but doesn't match because of a typo, like .Card instead of .card (CSS class names are case-sensitive in practice for matching), or forgetting the dot before a class name and accidentally writing an element selector instead. If a style "isn't working," the very first thing to check is always: did my selector actually match the element I think it matched? Developer tools answer this instantly, because unmatched rules will simply not appear on the element you inspect.

Pseudo Classes For States

One more selector worth knowing early is the pseudo-class, written with a single colon, which targets an element based on a state or position rather than its tag, class, or ID. You already saw a cousin of this idea (hover, in a later lesson), but structural pseudo-classes like :first-child and :last-child are useful right now for things like removing a border from the final item in a list, without needing to add an extra class by hand.

<ul class="menu">
  <li>Home</li>
  <li>About</li>
  <li>Contact</li>
</ul>
.menu li {
  border-bottom: 1px solid #ddd;
  padding: 8px 0;
}

.menu li:last-child {
  border-bottom: none;
}

Here, every list item gets a bottom border except the very last one, which is a common, clean pattern for separated lists without a trailing line at the end. Notice this required zero changes to the HTML itself; the selector alone identified which element was the last one, which is exactly the kind of work selectors are meant to do: letting your CSS adapt automatically to the structure that's already there, instead of you manually tagging every special case.

Naming And Practice Tips

Practical tip: name your classes based on what the thing IS, not how it currently looks. A class called .card or .profile-card is useful forever. A class called .red-box becomes confusing the day you decide to make it blue. This naming habit will save you real time as your projects grow.

A quick exercise: build a small HTML page with two or three "cards," each containing a name and a short description, similar to the Tony Stark example above. Give them a shared class for the overall box style, then use descendant selectors to style the heading and paragraph differently inside each card. Practice distinguishing when you'd want .card p versus .card > p.