# selectors

[CSS]() ⟩ [CSS Rules](rules) ⟩ selectors

{% hint style="info" %}

{% endhint %}

{% tabs %}
{% tab title="🔴 主題" %}
* [basic](selectors/basic "mention")
* [attribute-selectors](selectors/attribute-selectors "mention")
* [combinators](selectors/combinators "mention")
* [pseudo-class](selectors/pseudo-class "mention")
* [pseudo-element](selectors/pseudo-element "mention")
* [custom-selectors](selectors/custom-selectors "mention")
* [direct-children-by-js](selectors/direct-children-by-js "mention")
{% endtab %}

{% tab title="🛠 工具" %}
* :tools: [CSS Diner](https://flukeout.github.io/)
{% endtab %}

{% tab title="📗 參考" %}
* [ ] :green\_book: [CSS Selectors](https://css-tricks.com/almanac/selectors/) (CSS Tricks)
* [ ] JavaScript: The Definitive Guide (15.3 Scripting Documents)
{% endtab %}

{% tab title="📘 手冊" %}
* [NodeList](https://developer.mozilla.org/en-US/docs/Web/API/NodeList)
* [Document.querySelector()](https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector)
* [Document.querySelectorAll()](https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelectorAll)
* [Element.querySelector()](https://developer.mozilla.org/en-US/docs/Web/API/Element/querySelector)
* [Element.querySelectorAll()](https://developer.mozilla.org/en-US/docs/Web/API/Element/querySelectorAll)
* [DocumentFragment.querySelector()](https://developer.mozilla.org/en-US/docs/Web/API/DocumentFragment/querySelector)
* [`DocumentFragment.querySelectorAll()`](https://developer.mozilla.org/en-US/docs/Web/API/DocumentFragment/querySelectorAll)
{% endtab %}

{% tab title="👥 相關" %}
* DOM ⟩ [querying-elements](../browser/dom/querying-elements "mention")
{% endtab %}

{% tab title="🗣 討論" %}
* [Which characters are valid in CSS class names/selectors?](https://stackoverflow.com/questions/448981/which-characters-are-valid-in-css-class-names-selectors)
{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="💾 語法" %}
{% tabs %}
{% tab title="基本" %}
```css
div          /* tag name selector: <div>            */
#nav         /* id selector      : id="nav"         */
.warning     /* class selector   : class="warning"  */
```
{% endtab %}

{% tab title="屬性" %}
```css
/* attribute selector */
p[lang="fr"]    /* <p lang="fr">             */
*[name="x"]     /* any element with name="x" */
```
{% endtab %}

{% tab title=":prop?" %}
```css
body > h1:first-child  /* first <h1> direct child of <body> */
```
{% endtab %}

{% tab title="DOM" %}
```css
/* ------------ 親子關係 ------------ */

/* 不一定是直接的親子關係 */
ancestor descendant      /* op: space */

/* 直接子元素 */
parent > direct-child 

/* 直接子元素，但不是第一個(以下寫法效果都一樣) */
parent > direct-child + next-siblling    /* immediate sibling */
parent > :not(:first-child)
parent > :nth-child(n+2)    /* n = 0, 1, 2 ... */

/* 沒有子元素的元素(最底層) */
:not(:has(*))               /* :has() 為 CSS4 功能 */

/* ------------ 兄弟關係 ------------ */

/* (緊鄰著的)下一個兄弟(next sibling) */
brother + next-younger-brother

/* 後面的兄弟(following sibling) */
older ~ younger      /* 不必一定要緊接著的 */
```
{% endtab %}

{% tab title="組合" %}
```css
span.fatal.error         /* <span class="fatal error"> */
span[lang="fr"].warning  /* <span lang="fr" class="warning"> */
```
{% endtab %}
{% endtabs %}
{% endtab %}

{% tab title="⭐️ 重點" %}
{% hint style="warning" %}
The <mark style="color:yellow;">**return value**</mark> of [querySelectorAll()](https://developer.mozilla.org/en-US/docs/Web/API/Element/querySelector) is <mark style="color:red;">**not**</mark> an **array** of [Element](https://developer.mozilla.org/en-US/docs/Web/API/Element) objects. Instead, it is an <mark style="color:yellow;">**iterable**</mark> <mark style="color:orange;">**array-like**</mark> object known as a [NodeList](https://developer.mozilla.org/en-US/docs/Web/API/NodeList).&#x20;
{% endhint %}

{% hint style="info" %}
NodeList objects&#x20;

* have a <mark style="color:yellow;">**length**</mark> property, can be <mark style="color:yellow;">**indexed**</mark> like arrays.&#x20;
* can <mark style="color:yellow;">**loop**</mark> with traditional <mark style="color:blue;">**for( ; ; )**</mark> loop, <mark style="color:blue;">**for-of**</mark> loop, <mark style="color:blue;">**forEach()**</mark> method.&#x20;
* can convert into <mark style="color:yellow;">**array**</mark> with <mark style="color:blue;">**Array.from()**</mark>.
{% endhint %}

{% hint style="danger" %}
However, some older browsers have <mark style="color:red;">**not implemented**</mark> <mark style="color:blue;">`NodeList.forEach()`</mark> nor <mark style="color:blue;">`Array.from()`</mark>. This can be circumvented by using [`Array.prototype.forEach()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach) — see this document's [Example](https://developer.mozilla.org/en-US/docs/Web/API/NodeList#example).
{% endhint %}
{% endtab %}
{% endtabs %}
