CSS Selectors
🎯 🎯 The Power of Precise Targeting
Imagine you're decorating a house—you wouldn't paint every room the same color, right? CSS selectors are like having specific instructions: 'paint this bedroom blue,' 'make all kitchen walls white,' or 'add gold trim to the living room door.'
Why selectors matter: Professional websites use hundreds of different styles. Selectors let you apply the right style to the right element without affecting anything else.
- How do you think websites apply different styles to different sections?
- What would happen if you could only style ALL paragraphs the same way?
- How might you target just one specific element among many similar ones?
In this tutorial, you'll master CSS selectors—the foundation of precise, efficient styling. This is what separates beginners from professional developers.
Learning Objectives
By the end of this lesson, you'll be able to:
- ✓ Select elements by type, class, and ID with precision
- ✓ Combine selectors to target specific elements
- ✓ Use attribute selectors for dynamic styling
- ✓ Apply Apply pseudo-classes for interactive states
- ✓ Understand Understand selector specificity and the cascade
- ✓ Write efficient, maintainable selector patterns
- ✓ Debug selector issues using browser dev tools
Why This Matters:
Selectors are the most fundamental skill in CSS. Master them and you can style anything on the web with precision and confidence. Poor selector knowledge leads to messy, unmaintainable code—strong selector skills make you a CSS expert.
CSS selectors are patterns used to select and style HTML elements on a webpage. Understanding selectors is key to writing effective CSS.
Basic Selectors
Basic selectors target HTML elements directly by their tag name. They apply styles to all instances of that element on the page.
Understanding CSS Rules
Before diving into selectors, let's understand how CSS rules are written in both internal and external styles:
External CSS
.css file:
h1 {
color: blue;
}Internal CSS
<style>
h1 {
color: blue;
}
</style>Inline CSS
<h1 style="color: blue;">
Heading
</h1>Element Selectors
Element selectors target HTML elements by their tag name. They affect all elements of that type on the page.
Syntax
element-name {
property: value;
}Example
p {
color: navy;
line-height: 1.6;
}
h1 {
font-size: 24px;
margin-bottom: 1em;
}- Targets all elements of specified type
- No special characters needed
- Commonly used for basic styling
- Lower specificity than classes and IDs
Class Selectors
Class selectors target elements with a specific class attribute. Multiple elements can share the same class.
CSS Syntax
.highlight {
background-color: yellow;
}
.btn {
padding: 10px 20px;
border-radius: 4px;
}HTML Usage
<p class="highlight">This text will be highlighted</p>
<button class="btn">Click me</button>
<!-- Multiple classes on one element -->
<div class="highlight btn">
Both classes will apply
</div>- Must start with a period (.)
- Can contain letters, numbers, hyphens, and underscores
- Case-sensitive
- Cannot start with a number
- No spaces allowed in class names
- Use meaningful, descriptive names
- Use hyphens for multi-word classes
- Keep names as short as practical
- Elements can have multiple classes (space-separated)
ID Selectors
ID selectors target a single, unique element on the page. Each ID should only be used once per HTML document.
CSS Syntax
#main-header {
background-image: url('header.jpg');
}
#contact-form {
max-width: 600px;
margin: 0 auto;
}HTML Usage
<header id="main-header">
Site Header
</header>
<form id="contact-form">
Contact form fields
</form>
<!-- INCORRECT: Don't use the same ID multiple times -->
<div id="main-header">
This is not allowed!
</div>- Use the same ID multiple times in a document
- Add multiple IDs to one element
- Combine IDs with spaces like you can with classes
- Must start with a hash (#)
- Must be unique in the document
- Can contain letters, numbers, hyphens, and underscores
- Case-sensitive
- Cannot start with a number
- No spaces allowed in ID names
- Highest specificity of the basic selectors
- Should be used sparingly
- Better to use classes for styling
- IDs are better for JavaScript hooks and anchor links
Universal Selector
The universal selector (*) matches any element on the page. It's a powerful tool that should be used carefully.
CSS Syntax
/* Selects all elements */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
/* With a specific parent */
.container * {
border: 1px solid #ccc;
}
/* With pseudo-classes */
*:hover {
cursor: pointer;
}HTML Context
<div class="container">
<h1>Heading</h1>
<p>Paragraph</p>
<ul>
<li>Item</li>
</ul>
</div>- CSS resets
- Box-sizing adjustments
- Debugging layouts
- Applying base styles
- Can impact page performance if overused
- Affects every element, including new ones added dynamically
- Use sparingly and with specific parent selectors when possible
- Consider using more specific selectors for better performance
- Avoid using for general styling
- Prefer element or class selectors for specific styles
- Use primarily for CSS resets or global box-sizing
- Be cautious with properties that inherit naturally
Combining Selectors
Combinators allow us to select elements based on their relationship with other elements. Let's look at the two most common combinators.
Descendant Combinator (space)
Selects all elements that are descendants of a specified element. The elements don't need to be direct children.
CSS Syntax
/* Selects all p elements inside article */
article p {
color: navy;
}
/* Selects all spans inside div with class 'container' */
.container span {
font-weight: bold;
}HTML Example
<article>
<p>This paragraph is selected</p>
<div>
<p>This nested paragraph is also selected</p>
</div>
</article>- Matches elements at any level of nesting
- Uses a space between selectors
- Very common in CSS styling
- Can impact performance if too broad
Child Combinator (>)
Selects elements that are direct children of a specified element. Only works for immediate children.
CSS Syntax
/* Selects only direct li children of ul */
ul > li {
list-style: square;
}
/* Selects only direct p children of div.container */
.container > p {
margin-bottom: 1em;
}HTML Example
<ul>
<li>Direct child - Selected</li>
<li>Direct child - Selected
<ul>
<li>Nested - Not Selected</li>
</ul>
</li>
</ul>- Only matches direct children
- More specific than descendant selector
- Useful for strict hierarchies
- Better performance than descendant selector
- Use when you need to target only immediate children
- Helps prevent unintended styling of nested elements
- Consider using when building component-based designs
Attribute Selectors
Attribute selectors allow you to select elements based on their attributes or attribute values. These are especially useful when working with forms and custom data attributes.
Basic Attribute Selector [attribute]
Selects elements that have a specific attribute, regardless of its value.
CSS Syntax
/* Selects all elements with a title attribute */
[title] {
cursor: help;
}
/* Selects all inputs with required attribute */
input[required] {
border-color: red;
}HTML Example
<p title="More info">Hover me for a tooltip</p>
<form>
<input type="text" required>
<input type="text"> <!-- Not selected -->
</form>- Styling required form fields
- Adding indicators to elements with tooltips
- Targeting elements with specific ARIA attributes
- Styling elements with custom data attributes
Exact Value Selector [attribute="value"]
Selects elements where the attribute matches an exact value.
CSS Syntax
/* Selects inputs of type "submit" */
input[type="submit"] {
background-color: blue;
color: white;
}
/* Selects elements with specific role */
[role="button"] {
cursor: pointer;
padding: 0.5em 1em;
}HTML Example
<form>
<input type="text"> <!-- Not selected -->
<input type="submit"> <!-- Selected -->
</form>
<div role="button">Click Me</div>- Styling specific types of form inputs
- Targeting elements with specific roles
- Styling links with specific relationships (rel attribute)
- Matching exact data attribute values
- Use for specific, targeted styling
- Consider using data-* attributes for custom styling hooks
- Combine with other selectors when needed
- Keep selectors simple and readable
Practical Example: Styling Form Inputs
/* Style all required inputs */
input[required] {
border: 2px solid #ff9f43;
}
/* Style different input types */
input[type="email"] {
background: url('email-icon.png') no-repeat 10px center;
padding-left: 35px;
}
input[type="tel"] {
background: url('phone-icon.png') no-repeat 10px center;
padding-left: 35px;
}
/* Style external links */
a[target="_blank"] {
padding-right: 20px;
background: url('external-link.png') no-repeat right;
}Pseudo-classes
Pseudo-classes select elements based on their state or position. They allow you to style elements differently based on how users interact with them or where they appear in the document.
State Pseudo-classes
These pseudo-classes respond to user interactions like hovering, clicking, or focusing on elements.
Common State Pseudo-classes
/* Hover state */
button:hover {
background-color: #0056b3;
}
/* Active state (while clicking) */
button:active {
transform: scale(0.98);
}
/* Focus state */
input:focus {
border-color: #007bff;
outline: none;
}
/* Visited links */
a:visited {
color: purple;
}HTML Example
<button class="btn">Hover Me</button>
<input type="text" placeholder="Focus Me">
<a href="#">Click Me</a>- Creating interactive button states
- Showing focus states for accessibility
- Differentiating visited links
- Providing user feedback on interactions
- Always maintain visible focus states for accessibility
- Use :hover for supplementary information only
- Ensure sufficient color contrast in all states
- Test interactions across different devices
Simple Structural Pseudo-classes
These pseudo-classes select elements based on their position in the document structure.
Basic Structural Selectors
/* First child element */
li:first-child {
font-weight: bold;
}
/* Last child element */
li:last-child {
border-bottom: none;
}
/* Only child */
p:only-child {
font-style: italic;
}HTML Example
<ul>
<li>First item (bold)</li>
<li>Middle item</li>
<li>Last item (no border)</li>
</ul>
<div>
<p>Only paragraph (italic)</p>
</div>- Removing borders from last items in lists
- Styling first or last elements differently
- Special styling for single elements
- Basic list styling
Specificity
Specificity determines which CSS rules are applied when multiple rules target the same element. Think of it as a scoring system that decides which styles take precedence.
Specificity Hierarchy
From highest to lowest specificity:
1. Inline Styles
<div style="color: blue;">Highest specificity, but should be avoided for maintainability
2. ID Selectors
#header { color: blue; }Very high specificity, use sparingly
3. Class, Attribute, and Pseudo-class Selectors
.highlight, [type="text"], :hover { color: blue; }Medium specificity, commonly used
4. Element and Pseudo-element Selectors
p, ::before { color: blue; }Lowest specificity, most general
- Count the number of ID selectors (a)
- Count the number of class, attribute, and pseudo-class selectors (b)
- Count the number of element selectors (c)
- Write as: a-b-c
- Keep selectors as simple as possible
- Avoid inline styles
- Use classes instead of IDs for styling
- Don't over-qualify selectors
The !important declaration overrides normal specificity rules and should be avoided. It makes styles harder to maintain and debug.
Specificity Visual Guide
- The wider the bar, the higher the specificity weight
- Each level shows a different type of selector
- Numbers in parentheses show the specificity score (Inline, ID, Class, Element)
- Inline styles always override other selectors unless !important is used
⏸️ Pause & Check: Do You Understand?
Before moving forward, can you answer these?
- What is the difference between a class selector and an ID selector?
- How does the descendant combinator (space) differ from the child combinator (>)?
- What is CSS specificity and why does it matter?
- When would you use a pseudo-class like :hover or :nth-child()?
Check Your Answers
- Class selectors (.) can be used on multiple elements and are reusable, while ID selectors (#) should only be used once per page. Classes are for styling groups of elements; IDs are for unique elements and have higher specificity.
- The descendant combinator (space) selects all matching elements at any depth within an ancestor, while the child combinator (>) only selects direct children. For example, "div p" selects all p elements inside any div, but "div > p" only selects p elements that are immediate children of div.
- Specificity determines which CSS rule applies when multiple rules target the same element. It's calculated based on the types of selectors used: inline styles (1000), IDs (100), classes/attributes/pseudo-classes (10), and elements (1). Understanding specificity helps you control which styles apply without using !important.
- Pseudo-classes select elements based on their state or position. Use :hover for interactive styling when users mouse over elements, :nth-child() to select specific children by position (like every other row in a table), :first-child/:last-child for boundary elements, and :focus for keyboard navigation accessibility.
How confident are you with this concept?
😕 Still confused | 🤔 Getting there | 😊 Got it! | 🎉 Could explain it to a friend!
Practical Exercises
Let's practice organizing selectors for our restaurant websites. We'll focus on structuring our CSS selectors before adding properties in later lessons.
Exercise 1: Black Swan Bistro
Create an external stylesheet (style.css) for common elements and an internal style block for page-specific styles.
Tasks:
- Style the main headings using element selectors
- Create classes for different menu sections
- Style the special announcement with a unique ID
- Use combinators to style nested menu items
The styles below are just one way to achieve the desired result.
External Stylesheet (style.css)
/* Header Styles */
header {}
.main-header {}
#restaurant-name {}
.tagline {}
/* Navigation */
nav {}
.main-nav {}
.nav-list {}
.nav-item {}
.nav-link {}
/* Footer */
footer {}
.footer-content {}
.social-links {}
.contact-info {}
/* Common Elements */
.container {}
.section {}
.button {}Internal Styles (index.html)
<style>
/* Hero Section */
.hero-section {}
.hero-content {}
.hero-image {}
/* Featured Menu */
.featured-menu {}
.menu-item {}
.menu-title {}
.menu-description {}
.menu-price {}
/* Special Events */
.events-section {}
.event-card {}
.event-date {}
.event-details {}
</style>- External stylesheet for site-wide elements
- Class-based selectors for reusable components
- IDs only for unique elements
- Semantic class names that describe purpose
Exercise 2: Personal Profile Page
Apply the selectors from this tutorial to Alex Chen's Personal Profile Page using the following goals:
Styling Goals- Target the profile header with element and class selectors
- Style the skills list items with class selectors
- Use attribute selectors for contact form inputs
- Keep the page readable and easy to expand later
The code below is just one way to achieve the desired result.
External Stylesheet (profile-styles.css)
/* Profile Header */
.profile-header {}
.profile-name {}
.profile-role {}
/* Main Sections */
.about-section {}
.skills-section {}
.interests-section {}
/* Lists and Cards */
.skills-list {}
.skill-item {}
.interest-card {}
/* Contact Form */
.contact-section {}
.contact-form {}
input[type="text"] {}
input[type="email"] {}
textarea {}Internal Styles (profile-page.html)
<style>
/* Hero Area */
.hero {}
.hero-content {}
.profile-photo {}
/* Skills and Interests */
.skills-list li {}
.interests-grid {}
.interest-item {}
/* Contact Details */
.contact-links {}
.contact-form label {}
.contact-form button {}
</style>- Group related selectors together
- Use consistent naming conventions
- Keep specificity low for flexibility
- Plan for component reusability
Practice organizing selectors before adding properties. This helps:
- Plan the structure of your stylesheets
- Create maintainable and scalable CSS
- Understand the relationship between HTML and CSS
- Prepare for adding properties in future lessons
Lesson checkpoint
Test Your Knowledge
Strengthen your understanding of Selectors by answering the quiz below.
Selectors Quiz
Test your understanding of Selectors concepts.
Lesson Complete: What You Learned
Key Takeaways:
- Element selectors target HTML tags, class selectors (.) target multiple elements, and ID selectors (#) target unique elements
- Combinators control relationships: descendant (space), child (>), adjacent sibling (+), and general sibling (~)
- Attribute selectors target elements based on attributes and values using [attribute], [attribute=value], and pattern matching
- Pseudo-classes like :hover, :focus, :nth-child() select elements based on state or position
- Specificity determines which styles apply: inline (1000) > IDs (100) > classes/attributes (10) > elements (1)
- Combining selectors increases specificity and targeting precision
- Writing specific, maintainable selectors is more important than using !important
Learning Objectives Review:
Look back at what you set out to learn. Can you now:
- ✅ Master basic selectors: element, class, ID, and universal (*) Check!
- ✅ Use combinators to target elements based on their relationships Got it!
- ✅ Apply attribute selectors for flexible targeting Can explain it!
- ✅ Understand and use pseudo-classes for state and position-based styling Could teach this!
- ✅ Calculate and manage CSS specificity effectively Check!
- ✅ Write efficient, maintainable selectors following best practices Got it!
If you can confidently answer "yes" to most of these, you're ready to move on!
Think & Reflect:
Precision Targeting
- When should you use a class selector versus an ID selector?
- How can you make selectors more specific without increasing complexity?
Specificity Management
- What problems arise from specificity conflicts?
- How can you avoid needing !important to override styles?
🤔 Real-World Test:
Professional CSS relies heavily on selector strategy. Large codebases from companies like GitHub, Airbnb, and Shopify use methodologies like BEM (Block Element Modifier) to manage selector specificity and prevent conflicts. Understanding selectors deeply allows you to write CSS that scales from small projects to enterprise applications.
Modern CSS frameworks like Tailwind and CSS-in-JS solutions abstract selectors, but when debugging or customizing, you need to understand how selectors work. Mastering selectors makes you a more effective developer regardless of the tools you use.
🎯 Looking Ahead:
With selectors mastered, you're ready to learn the CSS Box Model—one of the most fundamental concepts in CSS layout. The box model explains how elements occupy space, including content, padding, borders, and margins. Understanding the box model is essential for controlling layout and spacing.
Every CSS layout challenge involves the box model. Whether you're centering content, creating grids, or debugging spacing issues, box model knowledge is your foundation. Let's dive in!
Recommended Next Steps
Continue Learning
Ready to move forward? Continue with the next tutorial in this series:
Colors & TypographyRelated Topics
Explore these related tutorials to expand your knowledge:
Practice Projects
Apply what you've learned with these hands-on projects:
Additional Resources
Deepen your understanding with these helpful resources:
- MDN: CSS Selectors - Guide to CSS selectors
Progress tracking is disabled. Enable it in to track your completed tutorials.
Cookie Settings