CSS Selector(선택기) 자세히 알아보기

안녕하세요?

오늘은 CSS 선택기(selector)에 대해 자세히 알아보겠습니다.

위 그림에서 보시면 CSS를 작성할 때 가장 많이 쓰이는 클래스 선택기의 한 예인데요.

선택기에는 클래스 선택기 외에도 여러 가지가 있습니다.

  1. Universal selector (유니버설 선택기)

모든 걸 선택한다는 뜻입니다.

* {
  color: hotpink;
}
  1. Type selector (타입 선택기)

HTML의 태그를 선택한다는 얘기입니다.

section {
  padding: 2em;
}
  1. Class selector (클래스 선택기)

우리가 자주 쓰는 클래스 선택기입니다.

<div class="my-class"></div>
<button class="my-class"></button>
<p class="my-class"></p>
.my-class {
  color: red;
}

클래스 선택기로 CSS를 선택할 때는 정확한 걸 고르는 게 아니라 포함된 걸 고릅니다

그래서 다음과 같이 클래스를 여러 개 사용해도 한 개만 맞으면 적용됩니다.

<div class="my-class another-class some-other-class"></div>

** 주의사항 **

클래스의 이름으로는 숫자로 시작하는 이름은 사용할 수 없으니 주의 바랍니다.

  1. ID selector (아이디 선택기)

HTML 태그에 id를 부여해서 그걸 선택하는 방식입니다.

<div id="rad"></div>
#rad {
  border: 1px solid blue;
}
  1. Attribute selector (속성 선택기)

HTML 태그에 속성을 부여하고 그걸 이용해서 CSS 선택하는 방식입니다.

<div data-type="primary"></div>
<div data-type="secondary"></div>
[data-type='primary'] {
  color: red;
}

위와 같이 속성에 특정값을 지정할 수도 있고 아래처럼 해당 속성이 있는 모든 걸 찾을 수 도 있습니다.

[data-type] {
  color: red;
}

** 옵션 **

속성 선택기로는 대소문자를 구분할 수 도 있고 안 할 수도 있는데요.

기본적으로는 대소문자를 구분합니다.

아래와 같이 끝에 'i'를 추가하면 대소문자를 구분 안 합니다.

[data-type='Primary' i] {
  color: red;
}

만약 아래와 같이 끝에 's'를 추가하면 대소문자를 구분합니다.

[data-type='Primary' s] {
  color: red;
}

** 옵션2 **

속성 선택기로는 더 많은 일을 할 수 있는데요.

/* "example.com"가 포함된 a link */
[href*='example.com'] {
  color: red;
}

/* https로 시작하는 a link */
[href^='https'] {
  color: green;
}

/* .com으로 끝나는 a link */
[href$='.com'] {
  color: blue;
}

선택기 여러 개 한 번에 쓰기

선택기는 아래처럼 여러 가지를 한꺼번에 쓸 수 있습니다.

strong,
em,
.my-class,
[data-type] {
  color: red;
}

Pseudo-classes

한국말로 가상 클래스라고 번역되어 사용되고 있긴 한데요.

선택자 뒤에 :가상이벤트를 붙이면 특정 이벤트마다 적용할 스타일을 설정할 수 있습니다.

  • :link - 방문한 적이 없는 링크
  • :visited - 방문한 적이 있는 링크
  • :hover - 마우스를 롤 오버 했을 때
  • :active - 마우스를 클릭했을 때
  • :focus - 포커스 되었을 때 (input 태그 등)
  • :first-child
  • :last-child
  • :nth-child
  • :nth-last-child
  • :first-of-type
  • :last-of-type
  • :nth-of-type
  • :nth-last-of-type
  • :checked
  • :enabled
  • :disabled

** 주의 사항 **

a:hover 가상 클래스는 무조건 a:link와 a:visited 뒤에 나와야 합니다.

또 a:active 가상 클래스는 a:hover 뒤에 와야 하고요.

그래서 보통 순서를 a:link, a:visited, a:hover, a:active 순으로 씁니다.

All CSS Pseudo Classes

SelectorExampleDescription
:activea:activeSelects the active link
:checkedinput:checkedSelects every checked <input> element
:disabledinput:disabledSelects every disabled <input> element
:emptyp:emptySelects every <p> element that has no children
:enabledinput:enabledSelects every enabled <input> element
:first-childp:first-childSelects every <p> elements that is the first child of its parent
:first-of-typep:first-of-typeSelects every <p> element that is the first <p> element of its parent
:focusinput:focusSelects the <input> element that has focus
:hovera:hover Selects links on mouse over
:in-rangeinput:in-rangeSelects <input> elements with a value within a specified range
:invalidinput:invalidSelects all <input> elements with an invalid value
:lang(language)p:lang(it)Selects every <p> element with a lang attribute value starting with "it"
:last-childp:last-childSelects every <p> elements that is the last child of its parent
:last-of-typep:last-of-typeSelects every <p> element that is the last <p> element of its parent
:linka:linkSelects all unvisited links
:not(selector):not(p)Selects every element that is not a <p> element
:nth-child(n)p:nth-child(2)Selects every <p> element that is the second child of its parent
:nth-last-child(n)p:nth-last-child(2)Selects every <p> element that is the second child of its parent, counting from the last child
:nth-last-of-type(n)p:nth-last-of-type(2)Selects every <p> element that is the second <p> element of its parent, counting from the last child
:nth-of-type(n)p:nth-of-type(2)Selects every <p> element that is the second <p> element of its parent
:only-of-typep:only-of-typeSelects every <p> element that is the only <p> element of its parent
:only-childp:only-childSelects every <p> element that is the only child of its parent
:optionalinput:optionalSelects <input> elements with no "required" attribute
:out-of-rangeinput:out-of-rangeSelects <input> elements with a value outside a specified range
:read-onlyinput:read-onlySelects <input> elements with a "readonly" attribute specified
:read-writeinput:read-writeSelects <input> elements with no "readonly" attribute
:requiredinput:requiredSelects <input> elements with a "required" attribute specified
:rootrootSelects the document's root element
:target#news:targetSelects the current active #news element (clicked on a URL containing that anchor name)
:validinput:validSelects all <input> elements with a valid value
:visiteda:visitedSelects all visited links

Pseudo-element

의사 요소라고 한국어로 번역되어 있긴 하지만 선뜻 딱 머리에 들어오지는 않네요.

의사 요소는 CSS3에 와서는 아래와 같은 이유로 두 개의 콜론(::)을 사용합니다.

CSS1과 CSS2에서는 의사 클래스와 의사 요소를 나타낼 때 하나의 콜론(:)으로 함께 표기하였습니다. 하지만 CSS3에서는 의사 클래스의 표현과 의사 요소의 표현을 구분하기로 합니다. 따라서 CSS3에서는 의사 클래스는 하나의 콜론(:)을, 의사 요소에는 두 개의 콜론(::)을 사용하고 있습니다.

가장 많이 쓰이는 의사 요소입니다.

::first-letter

이 의사 요소(pseudo-element)는 텍스트의 첫 글자만을 선택합니다.

단, 블록(block) 타입의 요소에만 사용할 수 있습니다.

이 의사 요소를 통해 사용할 수 있는 속성은 다음과 같습니다.

  • font 속성

  • color 속성

  • background 속성

  • margin 속성

  • padding 속성

  • border 속성

  • text-decoration 속성

  • text-transform 속성

  • line-height 속성

  • float 속성

  • clear 속성

  • vertical-align 속성 (단, float 속성값이 none일 경우에만)

  • ::first-line

  • ::before

  • ::after

  • ::selection

::first-line

이 의사 요소는 텍스트의 첫 라인만을 선택합니다.

단, 블록(block) 타입의 요소에만 사용할 수 있습니다.

이 의사 요소를 통해 사용할 수 있는 속성은 다음과 같습니다.

  • font 속성
  • color 속성
  • background 속성
  • word-spacing 속성
  • letter-spacing 속성
  • text-decoration 속성
  • text-transform 속성
  • line-height 속성
  • clear 속성
  • vertical-align 속성

::before

이 의사 요소는 특정 요소의 내용(content) 부분 바로 앞에 다른 요소를 삽입할 때 사용합니다.

<style>
    p::before { content: url("/examples/images/img_penguin.png"); }
</style>

::after

이 의사 요소는 특정 요소의 내용(content) 부분 바로 뒤에 다른 요소를 삽입할 때 사용합니다.

<style>
    p::after { content: url("/examples/images/img_penguin.png"); }
</style>

All CSS Pseudo Elements

SelectorExampleDescription
::afterp::afterInsert content after every <p> element
::beforep::beforeInsert content before every <p> element
::first-letterp::first-letterSelects the first letter of every <p> element
::first-linep::first-lineSelects the first line of every <p> element
::selectionp::selectionSelects the portion of an element that is selected by a user

결합 선택자 (Combination Selector)

이제 CSS에서 가장 헷갈려하는 결합 선택자로 왔네요.

결합은 다층 구조에 있어 쉽게 선택할 수 있는 옵션을 주는데요.

다음과 같은 HTML이 있다고 가정해 봅시다.

<main>
  <section>
    <p>This is a paragraph.</p>
    <p>This is a paragraph.</p>
    <div>
      <p>This is a paragraph inside div.</p>
    </div>
  </section>
  <p>This is a paragraph.</p>
  <p data-type="primary">This is a paragraph.</p>
</main>

main 태그 밑에 section 태그가 있고, section 태그 밑에 p 태그, div 태그가 있습니다.

그리고 div 태그 밑에는 p 태그가 또 있는데요.

CSS 결합 선택자를 공부하기 전에 조상과 자손, 그리고 부모와 자식, 형제에 대해 알아 두어야 합니다.

위의 HTML 예에서 main 태그가 조상이 됩니다.

root 조상이죠.

그 밑에 자손(descendants)들이 어떤 게 있을까요?

자손들은 단수가 아니라 복수입니다. 그래서 여러 가지가 있을 수 있죠.

section, p, div 등 main 태그 밑에 있는 모든 게 바로 자손이 됩니다.

그러면 자식(child)은 뭔가요?

자식은 바로 부모 밑에 있는 단계잖아요.

그래서 main이 부모라면 자식은 section 태그가 자식이 됩니다.

section이 부모라면 자식은 그 밑에 있는 p와 div가 자식이 되죠.

그런데 div 밑에 있는 p는 section의 자식이 아닙니다. 자손인 거죠(손주 인거죠).

이걸 헷갈려하시면 안 됩니다.

그리고 형제(sibling)는 같은 단계의 태그인데요.

section 바로 밑에 있는 두 개의 p 태그가 서로 형제(sibling)인 거죠.

그럼, 결합 선택자로 넘어가 보겠습니다.

자손(descendants) 선택자

말 그대로 자손들입니다.

<main>
  <section>
    <p>This is a paragraph.</p>
    <p>This is a paragraph.</p>
    <div>
      <p>This is a paragraph inside div.</p>
    </div>
  </section>
  <p>This is a paragraph.</p>
  <p data-type="primary">This is a paragraph.</p>
</main>
section p {
  color: blue;
  font-weight: bold;
}

위의 예제로 보시면 section 태그 밑에 있는 모든 p가 되죠.

그럼 실행 결과를 볼까요?

main 태그 바로 밑에 있는 p 태그는 선택되지 않았습니다.

왜냐하면 section의 자손을 선택하라고 한 것이기 때문이죠.

그리고 section 태그 밑에 div 태그가 있고 그 밑에 p 태그가 있는데 이것도 선택됐습니다.

왜냐하면 div 태그 밑에 있는 p 태그는 손자가 되며 손자도 자손들 인거죠.

자식들(children) 선택자

그러면 자손들 말고 자식(child) 또는 자식들(children) 선택자에 대해 알아볼까요?

자식(child) 선택자는 직계 가족입니다.

아들, 딸이 바로 자식이죠.

손주는 아닌 거죠.

section > p {
  color: blue;
  font-weight: bold;
}

'>' 를 이용해서 section 태그의 자식들 중에 p 태그를 고르라고 한 겁니다.

실행 결과를 볼까요?

위 그림처럼 div 태그 밑에 있는 p 태그는 선택되지 않았는데요.

div 태그 밑에 있는 p는 손주(자손)인거죠.

자식을 선택하는 거는 많이 쓰이니까 꼭 외워두셔야 합니다.

형제(sibling) 선택자

이제 형제, 자매 선택자로 왔는데요.

먼저, 모든 형제, 자매를 선택하는 선택자가 있습니다.

바로 '~'를 사용하는데요.

section ~ p {
  color: blue;
  font-weight: bold;
}

section과 형제인 모든 p를 구하라는 뜻입니다.

실행 결과를 볼까요?

모든 형제이기 때문에 2개가 골라졌네요.

그럼 형제, 자매 중에 바로 다음에 붙어 있는 동생 형제만을 고르는 선택자를 알아볼까요?

바로 '+' 선택자를 씁니다.

section + p {
  color: blue;
  font-weight: bold;
}

section의 형제 중에 바로 다음에 나오는 첫번 째 형제를 고르는 선택자입니다.

실행 결과를 볼까요?

역시 한 개만 선택되었죠.

** 응용 **

section > * + * {
  color: blue;
  font-weight: bold;
}

뭔가 복잡한 코드 같은데요.

section 다음에 '>'가 왔다는 뜻은 자손이 아니라 자식을 고르라는 건데요.

그다음에는 '*'가 왔습니다.

즉, section 자식(child) 중에 모든 태그가 해당하고요.

그다음에는 '+'가 왔는데요. 즉, 첫번 째 형제(sibling)를 고르라는 뜻입니다.

실행 결과를 볼까요?

어떤가요? 뭔가 감이 오시죠.

결합 선택자를 외울 때는

표기법
빈칸자손(descendants)
'>'자식들(children)
'~'모든 형제, 자매들(sibling)
'+'바로 밑 동생 형제만(sibling)

이렇게 외워두면 쉽습니다.

그럼.