Skip to main content

CSS Selectors

CSS selectors are the building blocks of CSS. They define the elements to which a set of CSS rules apply. Understanding selectors is crucial for effective CSS coding. Below are the detailed list of selectors.

Type Selector

Or also called as Tag Selector, targets HTML elements based on their tag name.

p {
color: red;
}

This will apply the style to all <p> elements.

Class Selector

Targets elements based on their class attribute.

.highlight {
font-weight: bold;
}

HTML: <p class="highlight">This is bold.</p>

ID Selector

Targets a specific element based on its id attribute.

#header {
font-size: 24px;
}

HTML: <div id="header">This is the header.</div>

Attribute Selector

Targets elements based on an attribute and its value.

[href="https://google.com"] {
text-decoration: none;
}

Pseudo-class Selector

Pseudo-class selectors in CSS are used to target elements based on their state, position, or other characteristics that can't be targeted using simple selectors. Pseudo-classes are preceded by a single colon (:).

:hover

Targets an element when the mouse is placed over it.

a:hover {
color: blue;
}

:active

Targets an element during the activation state, like when a link or button is being clicked.

button:active {
background-color: green;
}

:focus

Targets an element when it gains focus, such as an input field when clicked on.

input:focus {
border-color: red;
}

:nth-child()

Targets elements based on their position within a parent element.

li:nth-child(odd) {
background-color: grey;
}

:not()

Targets elements that do not match the given selector.

p:not(.special) {
color: red;
}

:first-child and :last-child

Targets the first or last child of a parent element.

li:first-child {
font-weight: bold;
}

:disabled and :enabled

Targets form elements that are disabled or enabled.

input:disabled {
background-color: lightgrey;
}

Targets link elements that have been visited or not.

a:visited {
color: purple;
}

MDN document on Pseudo class selectors

Pseudo-Element Selectors

::first-letter

Targets the first letter of a block-level element.

p::first-letter {
font-size: 2em;
font-weight: bold;
}

::first-line

Targets the first line of a block-level element.

p::first-line {
text-transform: uppercase;
}

::before

Inserts content before an element's actual content.

p::before {
content: "Note: ";
font-weight: bold;
}

::after

Inserts content after an element's actual content.

p::after {
content: " (end)";
font-style: italic;
}

::placeholder

Targets the placeholder text in form fields like input and textarea.

input::placeholder {
color: gray;
}

::selection

Targets the portion of an element that is selected by the user.

p::selection {
background-color: yellow;
}

MDN document on psuedo element selectors

Combinators

In CSS, combinators are used to define relationships between different elements based on their position in the HTML document. They allow you to create more specific and complex selectors. Here are the primary types of combinators:

Descendant Combinator (Space)

This is the most straightforward combinator. It selects all elements that are descendants of a specified element.

Example 1: Style all <p> inside <div>

div p {
color: red;
}

HTML:

<div>
<p>This is red.</p>
<section>
<p>This is also red.</p>
</section>
</div>

Example 2: Style all <a> inside .nav

.nav a {
text-decoration: none;
}

HTML:

<nav class="nav">
<ul>
<li><a href="#">Home</a></li>
<li><a href="#">About</a></li>
</ul>
</nav>

Child Combinator (>)

This selects all elements that are direct children of a specified element.

Example 1: Style Direct <p> Children Inside <div>

In this example, only the <p> elements that are direct children of the <div> will be styled.

div > p {
color: blue;
}

HTML:

<div>
<p>This is blue.</p> <!-- Styled -->
<section>
<p>This is not blue.</p> <!-- Not Styled -->
</section>
<p>This is also blue.</p> <!-- Styled -->
</div>

Example 2: Style Direct <li> Children Inside .menu

Here, only the <li> elements that are direct children of an element with the class .menu will be styled.

.menu > li {
font-weight: bold;
}

HTML:

<ul class="menu">
<li>Item 1</li> <!-- Styled -->
<li>Item 2</li> <!-- Styled -->
<ul>
<li>Sub-item 1</li> <!-- Not Styled -->
</ul>
<li>Item 3</li> <!-- Styled -->
</ul>

Example 3: Style First Direct <div> Child Inside .container

In this example, only the first <div> that is a direct child of .container will be styled.

.container > div:first-child {
background-color: yellow;
}

HTML:

<div class="container">
<div>This is yellow.</div> <!-- Styled -->
<div>This is not yellow.</div> <!-- Not Styled -->
</div>

Example 4: Style Direct <a> Children Inside .nav

Here, only the <a> elements that are direct children of .nav will be styled.

.nav > a {
text-decoration: none;
}

HTML:

<div class="nav">
<a href="#">Link 1</a> <!-- Styled -->
<span>
<a href="#">Link 2</a> <!-- Not Styled -->
</span>
<a href="#">Link 3</a> <!-- Styled -->
</div>

Adjacent Sibling Combinator (+)

This selects the immediate next sibling of an element.

Example 1: Style <p> immediately following <h2>

h2 + p {
font-weight: bold;
}

HTML:

<h2>Title</h2>
<p>This is bold.</p> <!-- This will be bold -->
<p>This is not.</p>

Example 2: Style <li> immediately following .active

li.active + li {
color: grey;
}

HTML:

<ul>
<li class="active">Active</li>
<li>Grey</li> <!-- This will be grey -->
<li>Normal</li>
</ul>

General Sibling Combinator (~)

This selects all elements that share the same parent and are siblings of a specified element.

Example 1: Style all <p> following <h2>

h2 ~ p {
margin-left: 20px;
}

HTML:

<h2>Title</h2>
<p>Indented</p> <!-- This will be indented -->
<p>Also indented</p> <!-- This will also be indented -->

Example 2: Style all <li> following .active

li.active ~ li {
font-size: smaller;
}

HTML:

<ul>
<li class="active">Active</li>
<li>Smaller</li> <!-- This will be smaller -->
<li>Also smaller</li> <!-- This will also be smaller -->
</ul>

When to use them

Below is short explaination about which selector comes handy on which situation.

  1. State-based Styling: Pseudo-classes like :hover, :active, and :focus allow you to apply styles based on user interaction, without using JavaScript.

  2. Structural Styling: Pseudo-classes like :nth-child(), :first-child, and :last-child let you style elements based on their structural position within the document.

  3. Negation: The :not() pseudo-class allows you to exclude specific elements from being selected, offering more control over your styles.

  4. Specificity: Pseudo-classes have the same specificity as class selectors. They can be overridden by more specific selectors or inline styles.

  5. Combining with Other Selectors: You can combine pseudo-classes with other types of selectors for more targeted styling.

Limitations and Considerations

  • Pseudo-elements are not part of the DOM, so they cannot be manipulated using JavaScript.
  • Not all pseudo-elements are supported by all browsers, so it's good to check compatibility.
  • The ::before and ::after pseudo-elements require the content property, even if it's empty, to render.

How They Work

  1. Cascading: If multiple selectors target the same element, the one with the highest specificity wins. Specificity is calculated based on the types of selectors used.

  2. Inheritance: Some properties like color and font-family are inherited from parent elements if not specified.

  3. Rule Application: The browser reads the CSS from top to bottom. If two rules have the same specificity, the latter will override the former.

  4. Importance: The !important flag can override specificity, but it's generally best to avoid using it unless absolutely necessary.

Specificity Hierarchy

  • Inline styles have the highest specificity.
  • ID selectors have higher specificity than class selectors.
  • Class selectors have higher specificity than type selectors.

Example

/* Type selector */
p {
color: red;
}

/* Class selector */
.highlight {
color: green;
}

/* ID selector */
#unique {
color: blue;
}

HTML:

<p>This is red.</p>
<p class="highlight">This is green.</p>
<p id="unique">This is blue.</p>

!important specificity

The !important rule in CSS is used to give a particular style declaration higher importance or specificity than it would naturally have in the cascade. This can be useful for overriding styles that are otherwise difficult to change, but it should be used sparingly.

  1. Overriding Specificity: When !important is added to a CSS rule, it overrides any other declarations for that property on the targeted element, regardless of specificity or source.

  2. Syntax: It is placed at the end of the declaration, before the semicolon.

    p {
    color: blue !important;
    }
  3. Cascade Order: Even among !important rules, the cascade still applies. If there are conflicting !important rules, the one that comes last in the stylesheet will be applied.

  4. Inline Styles: !important in an external or internal stylesheet will override inline styles on an element, which are usually the most specific.

  5. User vs. Author Styles: User stylesheets with !important will override author stylesheets with !important.

Example-I: Basic Usage

/* This will make all paragraphs red, regardless of other styles */
p {
color: red !important;
}

Example-II: Overriding Inline Styles

HTML:

<p style="color: blue;">This is a paragraph.</p>

CSS:

p {
color: red !important;
}

The paragraph will be red, not blue, because of the !important rule.

Best Practices

  1. Use Sparingly: Overusing !important can make your CSS difficult to manage and debug.

  2. Specificity First: Try to use proper specificity to override styles before resorting to !important.

  3. Documentation: If you must use !important, document why it's necessary, so future developers (or future you) understand the reasoning.

  4. User Experience: Be cautious when using !important in a way that could disrupt user styles or accessibility features.

  5. Last Resort: Consider !important as a last resort, especially if you're working on large or collaborative projects where it could cause confusion or conflicts.