Mastering the DOM: A Comprehensive Guide to CSS Selectors
CSS Selectors are the foundation of styling. They are the "query language" of CSS, allowing you to pinpoint the exact HTML elements you want to style. Mastering them is the first and most critical step to moving beyond basic styles and building complex, maintainable websites.
1. The Basic Selectors
These are the three workhorses you'll use every day.
- Element (or Type) Selector: Targets all elements of a specific tag name. Great for setting global defaults.
p { line-height: 1.6; color: #333; } - Class Selector: Targets all elements with a specific `class` attribute. This is your most-used, most-versatile selector. It's reusable. It starts with a period (`.`).
/* In HTML: <button class="btn-primary">Click</button> */ .btn-primary { background-color: blue; color: white; } - ID Selector: Targets *one unique* element with a specific `id` attribute. IDs *must* be unique on the page. It's used for major page landmarks. It starts with a hash (`#`).
/* In HTML: <footer id="main-footer">...</footer> */ #main-footer { padding: 2rem; background-color: #f4f4f4; }
2. Attribute Selectors
These allow you to select elements based on the presence or value of their HTML attributes. They are enclosed in square brackets `[]`.
[href]: Selects all elements with an `href` attribute.[target="_blank"]: Selects elements with a `target` attribute set to exactly `_blank`.[href^="https"]: Selects `a` tags whose `href` *starts with* "https".[href$=".pdf"]: Selects `a` tags whose `href` *ends with* ".pdf".[href*="example"]: Selects `a` tags whose `href` *contains* the string "example".
3. Pseudo-Classes
Pseudo-classes select elements based on a specific *state* or *position*. They start with a single colon (`:`).
- Dynamic States:
:hover: When the user mouses over the element.:active: When the user clicks on the element.:focus: When the element (like an input field) is focused.
- Positional:
:first-child: The first element among its siblings.:last-child: The last element among its siblings.:nth-child(2n): Selects every even element (2n). `nth-child(odd)` selects odd ones.
- Logical:
:not(.special): Selects all elements *except* those with the class "special".
4. Pseudo-Elements
Pseudo-elements style a *part* of an element. By modern convention, they start with a double colon (`::`).
::before&::after: Creates a "virtual" element before or after the content of the selected element. Requires a `content` property.::first-letter: Styles the first letter of a block of text.::placeholder: Styles the placeholder text in an `input` or `textarea`.
5. Combinators
Combinators define the relationship between multiple selectors.
- Descendant ( ): `article p` - Selects all `p` elements *anywhere inside* an `article`.
- Child (>): `article > p` - Selects only `p` elements that are *direct children* of an `article`.
- Adjacent Sibling (+): `h2 + p` - Selects the `p` element that comes *immediately after* an `h2`.
- General Sibling (~): `h2 ~ p` - Selects *all* `p` elements that come after an `h2` and share the same parent.
6. Specificity: The Deciding Factor
What happens when two rules target the same element? Specificity decides the winner. Think of it as a score:
- IDs: (e.g., `#nav`) - Worth 100 points.
- Classes, Pseudo-classes, Attributes: (e.g., `.btn`, `:hover`, `[type="text"]`) - Worth 10 points each.
- Elements, Pseudo-elements: (e.g., `p`, `::before`) - Worth 1 point each.
The selector with the highest score wins. `!important` overrides all of this, but should be avoided as it's a sign of poor code structure.
✔️ Specificity Example
<p class="highlight">Hello</p>p { color: red; } /* Score: 1 */
.highlight { color: blue; } /* Score: 10 */The text will be **blue** because the class selector (10) is more specific than the element selector (1).
Key Takeaway: Always use the *least specific* selector that gets the job done. Prefer Classes for styling. Use IDs for page structure and JS hooks. Use Element selectors for global defaults. This approach makes your CSS predictable and easy to override.