Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
115 changes: 114 additions & 1 deletion docs/css/selectors/attribute-selectors.mdx
Original file line number Diff line number Diff line change
@@ -1 +1,114 @@
<ComingSoon />
---
title: Attribute Selectors
description: "Learn how to use Attribute Selectors to target elements based on the presence, exact value, or partial match of their HTML attributes, such as type, href, or target."
keywords: [CSS Attribute Selectors, Attribute presence, Attribute value, Substring matching, CSS Selectors, CodeHarborHub]
sidebar_label: Attribute Selectors
---

So far, we've targeted elements by their tag name, class, ID, or position. **Attribute Selectors** give us a powerful new way to target elements based on the attributes they possess in the HTML (like `type`, `href`, `title`, or `disabled`).

This is incredibly useful for styling elements that share the same tag but have different functions (e.g., different input types).

<AdsComponent />
<br />

## The Basic Syntax

Attribute selectors are always enclosed in **square brackets (`[]`)**.

### 1. Attribute Presence Selector `[attr]`

This is the simplest form. It selects any element that simply **has the specified attribute**, regardless of its value.

| Syntax | Example | Targets |
| :--- | :--- | :--- |
| **`[attr]`** | `[disabled]` | All elements that possess the **`disabled`** attribute, regardless of its value. |
| **`a[title]`** | `a[title]` | All `<a>` tags that have a **`title`** attribute present. |
| **`[attr="value"]`** | `[type="submit"]` | All elements where the `type` attribute value is **exactly `"submit"`**. |
| **`a[target="_blank"]`** | `a[target="_blank"]` | All links that have the `target` attribute set **exactly to `"_blank"`**. |

```css title="Styles any input that is disabled, regardless of its type"
input[disabled] {
opacity: 0.6;
cursor: not-allowed;
}
```

### 2. Exact Attribute Value Selector `[attr="value"]`

This selects any element that has the specified attribute **and** its value exactly matches the one provided.

| Syntax | Example | Targets |
| :--- | :--- | :--- |
| `[attr="value"]` | `[type="submit"]` | All elements whose `type` attribute is **exactly** `"submit"`. |
| `a[target="_blank"]` | `a[target="_blank"]` | All anchor tags (`<a>`) whose `target` attribute is **exactly** `"_blank"` (opens in a new tab). |

```css title="Targets only submit buttons"
input[type="submit"] {
background-color: #28a745; /* Green */
color: white;
}
```

<AdsComponent />
<br />

## Substring Matching (Advanced Selectors)

CSS offers several specialized operators for matching only a *part* of the attribute's value.

| Operator | Syntax | Description | Specificity Score |
| :--- | :--- | :--- | :--- |
| **`~=`** | `[attr~="value"]` | Contains the whole **word** (`value`), separated by spaces. (e.g., `class="nav link"`, targets `link`) | (0, 0, 1, 0) |
| **<code>&#124;=</code>** | <code>[attr&#124;="value"]</code> | Starts with the whole **word** (`value`), followed by a **hyphen** (`-`). (e.g., `lang="en-US"`) | (0, 0, 1, 0) |
| **`^=`** | `[attr^="value"]` | **Starts with** the exact string (`value`). | (0, 0, 1, 0) |
| **`$=`** | `[attr$="value"]` | **Ends with** the exact string (`value`). (e.g., targeting `.pdf` links) | (0, 0, 1, 0) |
| **`*=`** | `[attr*="value"]` | **Contains** the exact string (`value`) **anywhere** in the attribute. | (0, 0, 1, 0) |

### Example: Targeting File Extensions

You can use the `$=` selector to target links that end with a specific file extension, like `.pdf`.

```css title="styles.css"
/* Targets any link whose 'href' ends with '.pdf' */
a[href$=".pdf"] {
padding-right: 20px;
background: url('/icons/pdf.png') no-repeat right center;
}
```

### Example: Targeting Partial Class Names

You can use `*=` to style elements whose class names contain a specific component, which is useful in utility frameworks.

```css
/* Targets any element whose class contains the word 'btn-' */
[class*="btn-"] {
cursor: pointer;
border-radius: 4px;
}
```

## Specificity Score

Attribute Selectors have the same medium specificity as **Class Selectors**.

| Selector Type | Specificity Score |
| :--- | :--- |
| **Attribute Selector** | **(0, 0, 1, 0)** |

A score of **10** means they easily override Element Selectors but can be overridden by ID Selectors.

<AdsComponent />
<br />

## Interactive Attribute Selector Demo

In this demo, the CSS targets inputs based on their `type` attribute. Notice how different selectors are needed for the text field and the password field.

<CodePenEmbed
title="Interactive Attribute Selector Demo"
penId="OPNbqRE"
/>

**Challenge:** Remove the `required` attribute from the text input in the HTML. The red border will instantly disappear, showing the power of the presence selector `[required]`.
90 changes: 89 additions & 1 deletion docs/css/selectors/combinators/adjacent-sibling.mdx
Original file line number Diff line number Diff line change
@@ -1 +1,89 @@
<ComingSoon />
---
title: The Adjacent Sibling Combinator
description: "Learn how to use the Adjacent Sibling Combinator (+) to select an element that immediately follows another element at the same level in the HTML structure."
keywords: [CSS Adjacent Sibling Combinator, Plus Selector, Immediate Follow, Sequential Styling, CSS Combinators, CodeHarborHub]
sidebar_label: Adjacent Sibling Combinator
---

We've explored selectors based on hierarchy (parent/child). Now we look at selectors based on **sequence**—elements that appear one after the other.

The **Adjacent Sibling Combinator** selects an element that is the **immediate successor** of a preceding element, and both must be at the same level in the HTML structure (siblings).

It is represented by the **plus sign (`+`)**.

<AdsComponent />
<br />

## How to Use the Adjacent Sibling Combinator

The rule is very strict: the second element must directly and immediately follow the first element in the HTML source code.

### The Syntax

```css title="Adjacent Sibling Combinator Syntax"
preceding_selector + target_selector {
/* styles applied ONLY to the target_selector */
}
```

* **`preceding_selector`**: The element that comes first (e.g., `h2`, `.callout`).
* **`target_selector`**: The element that immediately follows the preceding element.

### Example: Spacing After a Heading

A very common use case is applying specific top margin or spacing to a paragraph *only* when it immediately follows a main heading.

<Tabs>
<TabItem value="html" label="HTML Structure">

```html
<div class="content">
<h2>Main Section Title</h2> <p>First paragraph after the title.</p> <div>
<p>Second paragraph (UNSTYLED)</p>
</div>
</div>
```

</TabItem>
<TabItem value="css" label="CSS Rule">

```css
/* Targets ONLY a <p> that IMMEDIATELY follows an <h2> */
h2 + p {
margin-top: 30px; /* Extra space above the first paragraph */
font-weight: bold;
}
```

</TabItem>
</Tabs>

In this example, the **first** paragraph gets the `margin-top: 30px;` because it is the adjacent sibling of `<h2>`. The second paragraph is **ignored** because it is contained within a `<div>`, meaning its immediate preceding sibling is the `<div>`, not the `<h2>`.

<AdsComponent />
<br />

## How it Relates to Flow

The Adjacent Sibling Combinator is a powerful tool for controlling the **vertical flow** of a document without relying on classes.

### Strict Sequential Requirement

Remember this rule: **there can be no other element or even a comment node between the two siblings.**

| HTML Sequence | CSS Rule: `h2 + p` | Result |
| :--- | :--- | :--- |
| `<h2>...</h2> <p>...</p>` | ✅ Match | The paragraph is styled. |
| `<h2>...</h2> <div>...</div> <p>...</p>` | No Match | The `<div>` breaks the adjacency. |
| `<h2>...</h2> <p>...</p>` | No Match | The comment node technically breaks the adjacency. |

## Interactive Adjacent Sibling Demo

In this demo, the CSS rule targets a list item (`<li>`) that immediately follows an element with the class `.header-item`.

<CodePenEmbed
title="Interactive Adjacent Sibling Demo"
penId="azNBPYK"
/>

**Challenge:** Try adding a new empty `<li></li>` between "Item A" and "Item B" in the HTML panel. What happens to the styling of "Item B"?
109 changes: 108 additions & 1 deletion docs/css/selectors/combinators/child.mdx
Original file line number Diff line number Diff line change
@@ -1 +1,108 @@
<ComingSoon />
---
title: The Child Combinator
description: "Learn how to use the Child Combinator (>) to target elements that are only one level deep inside a parent, ensuring highly precise and immediate contextual styling."
keywords: [CSS Child Combinator, Greater Than Selector, Direct Child, Immediate Nesting, CSS Combinators, CodeHarborHub]
sidebar_label: Child Combinator
---

The **Child Combinator** allows for very precise contextual styling. While the **Descendant Combinator** (space) targets an element nested *anywhere* inside a parent, the Child Combinator (`>`) targets elements that are **direct children**—meaning they are only nested one level deep.

This selector is ideal when you need to style only the immediate children of a component and leave deeper nesting untouched.

<AdsComponent />
<br />

## How to Use the Child Combinator

The Child Combinator is represented by the **greater-than sign (`>`)** placed between two selectors.

### The Syntax

```css
/* Child Combinator Syntax */
parent_selector > child_selector {
/* styles applied ONLY to the immediate child_selector */
}
```

* **`parent_selector`**: The direct parent element (e.g., `.card`, `ul`).
* **`child_selector`**: The element that must be the immediate child of the parent.

### Example

Imagine a list structure where you want to style only the top-level list items, but not any nested sub-lists.

<Tabs>
<TabItem value="html" label="HTML Structure">

```html
<ul class="main-menu">
<li>Item 1</li>
<li>
Item 2
<ul>
<li>Sub-Item 2.1</li>
</ul>
</li>
<li>Item 3</li>
</ul>
```

</TabItem>
<TabItem value="css" label="CSS Rule">

```css
/* Targets ONLY <li> elements that are IMMEDIATE children of .main-menu */
.main-menu > li {
font-weight: bold;
color: #c2185b; /* Deep Pink */
border-bottom: 1px solid #f8bbd0;
}
```

</TabItem>
</Tabs>

In the example above, the styles are applied to "Item 1," "Item 2," and "Item 3," but **not** to "Sub-Item 2.1," because that sub-item's direct parent is the inner `<ul>`, not `.main-menu`.

<AdsComponent />
<br />

## Child vs. Descendant (The Critical Difference)

Understanding the distinction between the two most common combinators is vital for writing robust CSS.

| Combinator | Syntax | Rule | Scope |
| :--- | :--- | :--- | :--- |
| **Descendant** | `A B` (Space) | Selects `B` nested **anywhere** inside `A`. | Broad and less strict. |
| **Child** | `A > B` (Greater-than) | Selects `B` only if it is the **immediate child** of `A`. | Strict and specific (one level deep). |

### Visualizing the Difference

Consider the same HTML:

```html title="index.html"
<div class="header">
<p>Paragraph 1</p>
<section>
<p>Paragraph 2</p>
</section>
</div>
```

| Selector | Targets | Why? |
| :--- | :--- | :--- |
| `.header p` | Paragraph 1 and 2 | The space targets **all** descendants. |
| `.header > p` | Paragraph 1 **only** | The `>` targets only the immediate children. |


## Interactive Child Combinator Demo

In this demo, try changing the CSS rule from the Child Combinator (`>`) to the Descendant Combinator (space) to see how the scope of the rule changes instantly.

<CodePenEmbed
title="Interactive Child Combinator Demo"
penId="pvyNpoy"
/>

**Challenge:** Change `.widget-footer > a` to `.widget-footer a` and observe how the "Legal Text Link" suddenly receives the style, proving it is a descendant, but not a direct child.
Loading