Advanced CSS Selectors

CSS provides powerful selectors to target elements based on their relationships, attributes, and states. Mastering selectors enables precise styling without adding extra classes.

Descendant and Child Selectors

The descendant selector (space) selects all elements that are descendants of a specified element, at any level.

The child selector (>) selects only direct children of an element, not deeper descendants.

Descendant selectors are useful for styling content within specific containers.

Child selectors provide more precise control when you only want immediate children.

/* Descendant selector (all paragraphs inside article) */
article p {
  line-height: 1.6;
  color: #333;
}

/* Child selector (only direct children) */
ul > li {
  list-style-type: square;
}

/* Difference between descendant and child */
div p {
  color: blue;  /* All p elements inside div, at any level */
}

div > p {
  color: red;   /* Only p elements that are direct children of div */
}

/* Practical example */
nav ul li a {
  text-decoration: none;
  color: white;
}

.menu > li {
  display: inline-block;
  margin-right: 20px;
}

Adjacent and General Sibling Selectors

The adjacent sibling selector (+) selects an element that comes immediately after another specific element.

The general sibling selector (~) selects all elements that are siblings of a specified element.

Both selectors require elements to share the same parent and be at the same level.

These are useful for styling elements based on their context relative to other elements.

/* Adjacent sibling (paragraph immediately after h2) */
h2 + p {
  font-weight: bold;
  font-size: 1.1em;
}

/* General sibling (all paragraphs after h2) */
h2 ~ p {
  color: #666;
}

/* Practical examples */
label + input {
  margin-left: 10px;
}

.checkbox:checked + label {
  color: green;
  font-weight: bold;
}

/* Space between list items except first */
li + li {
  margin-top: 10px;
}

/* Style all images after first paragraph */
p:first-of-type ~ img {
  float: right;
  margin-left: 20px;
}

Attribute Selectors

Attribute selectors target elements based on their attributes and attribute values.

[attr] selects elements with the specified attribute.

[attr=value] selects elements where the attribute exactly equals the value.

[attr~=value] selects elements where the attribute contains the value as a whole word.

[attr|=value] selects elements where the attribute starts with the value followed by a hyphen.

[attr^=value] selects elements where the attribute starts with the value.

[attr$=value] selects elements where the attribute ends with the value.

[attr*=value] selects elements where the attribute contains the value anywhere.

/* Has attribute */
a[target] {
  background-color: yellow;
}

/* Exact match */
a[href="https://example.com"] {
  color: red;
}

/* Contains word */
[class~="btn"] {
  padding: 10px;
}

/* Starts with (for language codes) */
[lang|="en"] {
  color: blue;
}

/* Starts with */
a[href^="https"] {
  padding-left: 20px;
}

/* Ends with */
a[href$=".pdf"] {
  background: url(pdf-icon.png) no-repeat left;
}

/* Contains */
a[href*="google"] {
  color: blue;
}

/* Case-insensitive match */
input[type="text" i] {
  border: 1px solid gray;
}

Pseudo-class Selectors

Pseudo-classes select elements based on their state or position, not their attributes or content.

:hover, :active, :focus select elements based on user interaction.

:first-child, :last-child, :nth-child() select elements based on their position among siblings.

:not() excludes elements matching a selector.

:checked, :disabled, :enabled select form elements based on their state.

/* Interactive states */
a:hover {
  color: red;
  text-decoration: underline;
}

input:focus {
  border-color: blue;
  outline: 2px solid lightblue;
}

button:active {
  transform: scale(0.98);
}

/* Position-based */
li:first-child {
  font-weight: bold;
}

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

/* Nth-child patterns */
tr:nth-child(odd) {
  background-color: #f2f2f2;
}

tr:nth-child(even) {
  background-color: white;
}

li:nth-child(3) {
  color: red;
}

/* Negation */
p:not(.intro) {
  color: gray;
}

/* Form states */
input:checked + label {
  font-weight: bold;
}

input:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

Pseudo-element Selectors

Pseudo-elements style specific parts of an element or insert content.

::before and ::after insert content before or after an element's content.

::first-line and ::first-letter style the first line or first letter of text.

::selection styles the portion of text selected by the user.

Use double colons (::) for pseudo-elements to distinguish them from pseudo-classes.

/* Insert content */
.required::after {
  content: ' *';
  color: red;
}

blockquote::before {
  content: '\"';
  font-size: 2em;
  color: gray;
}

/* Decorative elements */
.btn::before {
  content: '';
  display: inline-block;
  width: 10px;
  height: 10px;
  background: url(icon.png);
  margin-right: 5px;
}

/* First line/letter */
p::first-line {
  font-weight: bold;
  font-size: 1.2em;
}

p::first-letter {
  font-size: 3em;
  float: left;
  line-height: 1;
  margin-right: 5px;
}

/* Selection */
::selection {
  background-color: yellow;
  color: black;
}