# CSS 선택자

## CSS 선택자

이 문서에서는 `CSS 선택자(selector)`에 대해서 다룬다.

### 선택자란

`선택자(Selector)`란 문서 내의 요소(Element)를 선택할 수 있도록 작성하는 글자이다.\
선택자는 기호에 따라 여러 가지 의미를 가지며, 종류는 크게 다음과 같이 구분해볼 수 있다.

* 전체 선택자
* 태그 선택자
* 속성 선택자
* 아이디 선택자
* 클래스 선택자
* 상태 선택자
* 연계 선택자
* 가상 선택자

### 전체 선택자

전체 선택자는 이름 그대로 모든 요소에 적용시키기 위한 선택자를 말한다.\
전체 선택자는 다음과 같이 작성한다.

```css
* {
    /* 적용할 디자인 항목과 속성을 작성 */
}
```

위와 같이 설정할 경우 문서 내의 모든 요소에 적용되므로 사용할 때 반드시 공통적인 부분들만 설정해야 한다.\
주로 사용하는 속성으로는 `font`, `box-sizing` 등이 있다.

### 태그 선택자

특정 태그만 선택하고 싶은 경우에는 태그 선택자를 사용할 수 있다.\
태그 선택자의 경우 이름을 통해 선택을 하며, 코드의 형태는 다음과 같다.

```css
태그명 {
    /* 적용할 디자인 항목과 속성을 작성 */
}
```

전체 선택자와 마찬가지로 많은 수의 태그들을 한 번에 불러와서 처리하기 때문에 특정 태그에 대한 공통 처리들 위주로 작성해야 한다.

만약 모든 h1 태그의 글자색을 빨강으로 설정하고 싶다면 다음과 같이 구문을 작성할 수 있다.

```css
h1 {
    color:red;
}
```

### 속성 선택자

속성 선택자는 태그에 부여된 속성을 이용하여 선택하는 선택자를 말한다.\
속성이 부여되어있는 태그의 예시는 다음과 같다.

```html
<input type="text" name="id">
<input type="checkbox" name="agree">
```

위의 경우 둘 다 input 태그로 동일하기 때문에 태그 선택자로는 선택이 어려우며, 태그의 속성인 type이나 name을 이용하여 구분할 수 있다.\
따라서 다음과 같이 선택 구문을 만들 수 있다.

```css
/* <input type="text" name="id"> 를 type으로 선택 */
input[type=text] {
    /* 적용할 디자인 항목과 속성을 작성 */
}
/* <input type="text" name="id"> 를 name으로 선택 */
input[name=id] {
    /* 적용할 디자인 항목과 속성을 작성 */
}

/* <input type="checkbox" name="agree"> type으로 선택 */
input[type=checkbox] {
    /* 적용할 디자인 항목과 속성을 작성 */
}
/* <input type="checkbox" name="agree"> name으로 선택 */
input[name=agree] {
    /* 적용할 디자인 항목과 속성을 작성 */
}
```

### 아이디 선택자

HTML 태그에는 다음과 같이 `id` 속성을 부여할 수 있다.\
`id` 속성의 특징은 다음과 같다.

* `id` 속성은 페이지 내에서 대상을 유일하게 식별할 수 있어야 한다.
* `id` 속성은 하나의 태그에 하나만 부여할 수 있다.
* `id` 속성은 띄어쓰기가 불가하며, 대시(-)나 언더스코어(\_)를 사용할 수 있다.

`id`가 부여된 태그의 형태는 다음과 같다.

```html
<h1 id="header">...</h1>
```

이 경우 태그 이름으로 선택도 가능하며, `id`를 이용하여 선택할 수도 있다.\
아이디를 이용하여 선택하는 경우 다음과 같이 코드를 작성할 수 있다.

```css
h1[id=header] {
    /* 적용할 디자인 항목과 속성을 작성 */
}
```

`id` 역시 속성이므로 속성 선택자를 이용하여 선택할 수 있지만 `id`만을 위한 전용 기호인 `#`을 사용할 수 있다.

```css
h1#header{
    /* 적용할 디자인 항목과 속성을 작성 */
}
```

`id`는 유일한 식별자이므로 태그의 이름을 적지 않아도 무관하며, 태그 이름을 작성하지 않는 경우 다음과 같이 작성한다.

```css
#header{
    /* 적용할 디자인 항목과 속성을 작성 */
}
```

### 클래스 선택자

`class`란 선택 또는 그룹화를 위해 부여가 가능한 값을 말한다.\
`class`의 특징은 다음과 같다.

* `class`는 태그 하나에 여러 개 부여가 가능하다.
* `class`는 띄어 쓰기를 사용하면 다른 값으로 인식한다.
* 하나의 `class`를 여러 개의 태그에 부여할 수 있다.
* `class`를 이용하여 HTML 요소의 그룹화를 수행할 수 있다.

`class`가 부여된 태그의 예시는 다음과 같다.

```html
<h1 class="headline">테스트 헤더1</h1>
<h1 class="headline headline-bold">테스트 헤더2</h1>
```

첫 번째 h1 태그는 클래스가 1개 부여되어 있으며, 두 번째 h1 태그는 클래스가 2개 부여되어 있다.\
위와 같은 형태의 태그를 선택하기 위해서는 `속성 선택자`나 `클래스 선택자`를 사용할 수 있다.

```css
/* 속성 선택자를 사용하여 테스트 헤더1 선택 */
h1[class=headline] { /*...*/ }

/* 속성 선택자를 사용하여 테스트 헤더2 선택 */
h1[class=headline-bold] { /*...*/ }

h1[class=headline][class=headline-bold] { /*...*/ }

/* 클래스 선택자를 사용하여 테스트 헤더1 선택 */
h1.headline { /*...*/ }

.headline{ /*...*/ }

/* 클래스 선택자를 사용하여 테스트 헤더2 선택 */
h1.headline.headline-bold { /*... */ }

.headline.headline-bold { /*...*/ }
```

`class`로 대상을 선택할 때도 태그명을 생략할 수 있으며, 같이 적으면 범위가 좀 더 제한된다.\
주의사항으로는 `.headline.headline-bold` 처럼 여러개의 클래스가 적용된 태그를 선택하고 싶을 경우 선택자 사이에 띄어쓰기를 하면 안된다는 것이다.

### 연계 선택자

`연계 선택자`는 특정 태그를 기준으로 하여 태그를 선택하기 위한 선택자이다.\
CSS 선택자에서는 다음 네 가지의 연계 선택을 지원한다.

* `+` : 기준 태그의 바로 뒤에 있는 한 개의 태그를 선택한다.
* `~` : 기준 태그의 뒤에 있는 모든 태그를 선택한다.
* `>` : 기준 태그의 바로 밑에 있는 태그를 선택한다.
* : 기준 태그의 밑에 있는 모든 태그를 선택한다(띄어쓰기)

주의사항은 상위태그, 전방태그는 선택이 불가능하다는 것이다.

#### + 선택자

`+` 선택자는 바로 뒤에 있는 태그를 선택한다.

{% embed url="<https://codepen.io/hiphop5782/pen/oNeoZwQ>" %}

파랑으로 선택된 부분이 기준 태그이며, 빨강으로 선택된 부분이 `+` 선택자로 선택된 태그이다. 실제로 이 부분에 대해서 이해하기 위해 위의 코드를 구조화 시키면 다음과 같이 작성될 수 있다.

```
html
  +-- head
  |   +-- style
  +-- body
      +-- h3.tmp(기준태그)
      +-- h3(선택대상)
      +-- h3
      +-- h3
      +-- h3
```

html 요소들은 tree 형태로 배치되며, 작성 순서대로 위치하기 때문에 같은 깊이(depth)에서 `+` 선택자를 이용하여 바로 뒤(아래) 있는 태그를 선택할 수 있다.

#### \~ 선택자

`+` 선택자에서 작성한 코드를 `~` 선택자를 이용하는 것으로 수정하면 다음과 같이 결과가 달라지게 된다.

{% embed url="<https://codepen.io/hiphop5782/pen/KKvympZ>" %}

`~` 선택자는 뒤에 있는 모든 태그를 선택하기 때문에 같은 깊이(depth)에 존재하는 태그를 모두 선택하게 된다. tree 구조로 살펴보면 선택되는 원리를 확인할 수 있다.

```
html
  +-- head
  |   +-- style
  +-- body
      +-- h3.tmp(기준태그)
      +-- h3(선택대상)
      +-- h3(선택대상)
      +-- h3(선택대상)
      +-- h3(선택대상)
```

#### > 선택자

`>` 선택자는 **바로 아래 계층에 존재하는 태그를 선택**할 수 있다. 이를 위해서는 조금 더 계층화된 코드가 필요하며, 이를 위해 list 태그를 사용해본다.

list의 경우 중첩하여 계층 구조를 표현하기에 적합하다.

{% embed url="<https://codepen.io/hiphop5782/pen/mdMqmQm>" %}

`1-1`부터 `1-5`까지만 빨강으로 설정되는 것을 확인할 수 있으며, 그보다 하위에 있는 글자들은 색상이 변하지 않는다는 것을 확인할 수 있다. 이를 tree 계층으로 변환하여 살펴보면 더 쉽게 이해할 수 있다.

```
html
  +-- head
  |   +-- style
  +-- body
      +-- ul.tmp(기준태그)
          +-- li(하위요소)
          |   +-- a(선택대상)
          +-- li(하위요소)
          |   +-- a(선택대상)
          |   +-- ul
          |   |   +-- li
          |   |   |   +-- a
          |   |   +-- li
          |   |   |   +-- a
          |   |   +-- li
          |   |   |   +-- a
          +-- li(하위요소)
          |   +-- a(선택대상)
          |   +-- ul
          |   |   +-- li
          |   |   |   +-- a
          |   |   +-- li
          |   |   |   +-- a
          |   |   +-- li
          |   |   |   +-- a
          +-- li(하위요소)
          |   +-- a(선택대상)
          +-- li(하위요소)
              +-- a(선택대상)
```

위의 구조를 보면 `>` 선택자를 통하여 바로 아래 계층만 선택하는 것을 확인할 수 있다.

#### 하위 선택자(띄어쓰기)

특정 태그의 하위(내부)에 존재한 모든 대상에게 효과를 주고 싶은 경우에는 띄어쓰기를 사용한다.\
`>` 선택자에서 살펴본 코드를 조금 수정하면 특징을 확인할 수 있다.

{% embed url="<https://codepen.io/hiphop5782/pen/dyzZWYb>" %}

실행 결과를 확인해보면 모든 a태그의 글자가 빨강으로 나오는 것을 확인할 수 있다. tree 구조를 통해 살펴보면 기준이 되는 태그에 속해 있는 모든 하위 요소가 다 선택되는 것을 확인할 수 있다.

```
html
  +-- head
  |   +-- style
  +-- body
      +-- ul.tmp(기준태그)
          +-- li
          |   +-- a(선택대상)
          +-- li
          |   +-- a(선택대상)
          |   +-- ul
          |   |   +-- li
          |   |   |   +-- a(선택대상)
          |   |   +-- li
          |   |   |   +-- a(선택대상)
          |   |   +-- li
          |   |   |   +-- a(선택대상)
          +-- li
          |   +-- a(선택대상)
          |   +-- ul
          |   |   +-- li
          |   |   |   +-- a(선택대상)
          |   |   +-- li
          |   |   |   +-- a(선택대상)
          |   |   +-- li
          |   |   |   +-- a(선택대상)
          +-- li
          |   +-- a(선택대상)
          +-- li
              +-- a(선택대상)
```

### 상태 선택자

`상태 선택자`는 **특정 상태인 경우**를 선택하기 위한 선택자이다.\
이를 이용하여 다양한 상태에 특화된 디자인을 처리할 수 있다.

#### :first-child

`first-child` 상태는 **그룹의 첫 번째 요소**를 선택하기 위한 선택자이다.

예시 코드와 실행 결과는 다음과 같다.

{% embed url="<https://codepen.io/hiphop5782/pen/yLoPbdw>" %}

`1-1`과 `2-1`이 빨강으로 변하는 것을 보아 선택되었다는 것을 확인할 수 있다. tree 구조로 확인하면 더 쉽게 이해할 수 있다.

```
div
  +-- h5(first-child)
  +-- h5
  +-- h5
div
  +-- h5(first-child)
  +-- h5
  +-- h5
```

`h5` 태그는 총 6개이지만 `div`를 기준으로 분할되어있기 때문에 그룹이 2개로 나누어져있다고 볼 수 있다. 따라서 그룹마다 첫 번째 태그가 `first-child`가 되어 선택되는 것을 알 수 있다.

{% hint style="info" %}
:first-child 로 선택되려면 반드시 해당 영역의 첫 번째에 위치해야 한다. h5 중에서 처음인 경우가 아니라 영역 내 태그 중 처음이어야 한다.
{% endhint %}

#### :last-child

`last-child` 상태는 **그룹의 마지막 요소**를 선택하기 위한 선택자이다. `first-child`의 예제를 변경하여 살펴보도록 한다.

{% embed url="<https://codepen.io/hiphop5782/pen/PoKOjYQ>" %}

tree 구조로 살펴보면 각각 `div` 그룹의 마지막 `h5` 요소가 `last-child`로 선택된다는 것을 확인할 수 있다.

```
div
  +-- h5
  +-- h5
  +-- h5(last-child)
div
  +-- h5
  +-- h5
  +-- h5(last-child)
```

{% hint style="info" %}
:last-child 로 선택되려면 반드시 해당 영역의 마지막에 위치해야 한다. h5 중에서 마지막인 경우가 아니라 영역 내 태그 중 마지막이어야 한다.
{% endhint %}

#### :nth-child()

`nth-child` 상태는 **그룹의 원하는 순서의 요소**를 선택하기 위한 선택자이다. 패턴을 통해 반복적으로 선택도 가능하다.

{% embed url="<https://codepen.io/hiphop5782/pen/GRvOERO>" %}

tree 구조로 살펴보면 각각의 그룹에서 `nth-child(2)`에 해당하는 2번째 요소들이 선택되는 것을 확인할 수 있다.

```
div
  +-- h5 : nth-child(1)
  +-- h5 : nth-child(2) - 2번째 요소
  +-- h5 : nth-child(3)
div
  +-- h5 : nth-child(1)
  +-- h5 : nth-child(2) - 2번째 요소
  +-- h5 : nth-child(3)
```

패턴을 부여하여 홀수 또는 짝수 번째의 태그 선택도 가능하다.

{% embed url="<https://codepen.io/hiphop5782/pen/yLoPXLr>" %}

tree 구조를 통해 살펴보면 `n`이 1, 2, 3, 4로 변할 때 `2n`은 2, 4, 6, 8이므로 짝수 번째의 요소들이 선택되는 것을 확인할 수 있다.

```
div
  +-- h5 : nth-child(1)
  +-- h5 : nth-child(2) - n=1일 때 선택
  +-- h5 : nth-child(3)
  +-- h5 : nth-child(4) - n=2일 때 선택
div
  +-- h5 : nth-child(1)
  +-- h5 : nth-child(2) - n=1일 때 선택
  +-- h5 : nth-child(3)
  +-- h5 : nth-child(4) - n=2일 때 선택
```

#### :not()

`not` 상태는 **특정 요소를 제외**하기 위한 선택자이다.\
() 내부에 제외하고 싶은 내용에 대한 선택자를 기입하여 사용한다.

#### :hover

`hover` 상태는 **마우스가 올라간 상태**일 경우를 선택하는 선택자이다.\
마우스가 올라간 경우에만 적용되기 때문에 컴포넌트를 강조하는 용도로 자주 사용된다.

{% embed url="<https://codepen.io/hiphop5782/pen/jOLawPd>" %}

#### :focus

`focus` 상태는 **입력이 가능한 상태**일 경우를 선택하는 선택자이다.\
입력이 가능해야 하므로 input, textarea 등 입력 도구에서 사용한다.

{% embed url="<https://codepen.io/hiphop5782/pen/JjyOJYK>" %}

#### :checked

`checked` 상태는 **체크가 되어있는 상태**일 경우를 선택하는 선택자이다. 체크박스나 라디오와 같이 체크가 가능한 컴포넌트에서 사용한다. 또한 연계 선택자를 이용하여 체크 여부에 따라 인접 태그에 효과를 부여할 수 있다.

{% embed url="<https://codepen.io/hiphop5782/pen/wvqPeKx>" %}
