Basic CSS selectors

김동현·2026년 3월 17일

mdn 학습 번역 - CSS

목록 보기
2/190

선택자란 무엇인가요? (What is a selector?)

CSS 선택자는 'CSS 규칙(Rule)'의 가장 첫 번째 부분에 위치합니다. 브라우저에게 "이 중괄호 {} 안에 있는 CSS 속성값들을 어떤 HTML 요소들에 적용할까?"를 알려주는 일종의 패턴이나 조건식이라고 보시면 돼요. 선택자에 의해 선택된 하나 혹은 그 이상의 요소들을 '선택자의 대상(subject of the selector)'이라고 부릅니다.

h1 태그가 강조된 CSS 코드 이미지

💡 강사의 팁: > 방금 말씀드린 'CSS 규칙(Rule)'이라는 용어는 면접에서도 가끔 기본기를 확인하기 위해 물어보는 경우가 있어요. 선택자 { 속성: 값; } 이 전체 한 덩어리를 묶어서 CSS 룰셋(Rule-set) 또는 CSS 규칙이라고 부른다는 점, 꼭 기억해 두세요!

이전 글에서 여러분은 여러 가지 선택자를 만나보셨을 텐데요. 예를 들어 h1이라는 HTML 태그 자체를 선택하거나, .special이라는 특정 클래스를 선택하는 등 문서를 다양한 방식으로 조준하는 법을 배웠죠. 자, 그럼 이미 보셨던 핵심 선택자들부터 다시 한번 복습해 보겠습니다.


타입 선택자 (Type selectors)

타입 선택자는 문서 내의 특정 HTML 태그/요소를 직접 선택하기 때문에 종종 태그 이름 선택자(tag name selector) 또는 요소 선택자(element selector)라고도 불려요. 아래 예제에서는 span, em, strong 선택자를 사용해 보았습니다.

아래 예제를 직접 수정해 보세요! (MDN Playground에서 "Play" 버튼을 누르면 직접 코드를 쳐볼 수 있어요.) <h1> 요소를 선택해서 글자 색상을 파란색(blue)으로 바꾸는 CSS 규칙을 한번 추가해 보세요.

<h1>Type selectors</h1>
<p>
  Veggies es bonus vobis, proinde vos postulo essum magis
  <span>kohlrabi welsh onion</span> daikon amaranth tatsoi tomatillo melon azuki
  bean garlic.
</p>

<p>
  Gumbo beet greens corn soko <strong>endive</strong> gumbo gourd. Parsley
  shallot courgette tatsoi pea sprouts fava bean collard greens dandelion okra
  wakame tomato. Dandelion cucumber earthnut pea peanut soko zucchini.
</p>

<p>
  Turnip greens yarrow ricebean rutabaga <em>endive cauliflower</em> sea lettuce
  kohlrabi amaranth water spinach avocado daikon napa cabbage asparagus winter
  purslane kale. Celery potato scallion desert raisin horseradish spinach
</p>
body {
  font-family: sans-serif;
}

span {
  background-color: yellow;
}

strong {
  color: rebeccapurple;
}

em {
  color: rebeccapurple;
}

💡 강사의 팁:
타입 선택자는 보통 프로젝트 초기에 웹 페이지의 전반적인 기본 폰트나 여백, a 태그의 기본 색상 등을 싹 다 잡아줄 때(글로벌 스타일링) 아주 유용하게 쓰여요. 나중에 React나 Next.js로 개발하실 때 전역 스타일(Global Styles)을 설정하게 되는데, 그때 이 타입 선택자를 주로 다루게 되실 겁니다.


클래스 선택자 (Class selectors)

클래스 선택자는 대소문자를 구분하며, 점(.) 기호로 시작합니다. 이 선택자는 문서 내에서 해당 클래스가 적용된 모든 요소를 싹 다 선택해 줘요. 아래 예제에서는 highlight라는 클래스를 만들고 문서의 여러 곳에 적용해 보았어요. 이 클래스를 가진 모든 요소가 하이라이트 처리되는 걸 볼 수 있습니다.

<h1 class="highlight">Class selectors</h1>
<p>
  Veggies es bonus vobis, proinde vos postulo essum magis
  <span class="highlight">kohlrabi welsh onion</span> daikon amaranth tatsoi
  tomatillo melon azuki bean garlic.
</p>

<p class="highlight">
  Gumbo beet greens corn soko <strong>endive</strong> gumbo gourd. Parsley
  shallot courgette tatsoi pea sprouts fava bean collard greens dandelion okra
  wakame tomato. Dandelion cucumber earthnut pea peanut soko zucchini.
</p>
body {
  font-family: sans-serif;
}

.highlight {
  background-color: yellow;
}

클래스 선택자로 놀아보기 (Playing with class selectors)

위 예제를 가지고 아래처럼 조금씩 변경해 보면서 감을 잡아보세요.
1. HTML을 수정해서 .highlight 스타일이 적용되는 부분을 바꿔보세요. 예를 들어, 기존 내용의 다른 부분에 <span> 태그를 씌우고 highlight 클래스를 줘보거나, 반대로 이미 있는 클래스를 지워보거나, 아예 새로운 텍스트를 추가해서 적용해 볼 수도 있겠죠?
2. CSS 코드로 가서 .highlight 규칙 안에 있는 선언들을 수정해 보세요. 원한다면 새로운 스타일 속성을 추가해 보시고요! highlight 클래스가 적용된 모든 요소의 디자인이 한 번에 싹 변하는 걸 확인해 보세요.
3. CSS에 완전히 새로운 클래스 규칙을 하나 더 만들어 보세요 (예를 들어 선택자 이름을 .highlight2로요). 그런 다음 HTML에 방금 만든 새로운 클래스를 적용해 보세요.

특정 요소에 있는 클래스만 콕 집어내기 (Targeting classes on particular elements)

특정 태그에 특정 클래스가 있을 때만! 스타일이 적용되도록 선택자를 만들 수도 있어요. 다음 예제에서는 똑같이 highlight 클래스를 가지고 있지만, <span> 요소의 하이라이트와 <h1> 요소의 하이라이트 모양을 다르게 만들어 볼 거예요.
어떻게 하냐고요? 우리가 원하는 타겟 태그(요소)를 먼저 적고, 띄어쓰기 없이 바로 이어서 점(.)과 클래스 이름을 붙여주면 됩니다.

<h1 class="highlight">Class selectors</h1>
<p>
  Veggies es bonus vobis, proinde vos postulo essum magis
  <span class="highlight">kohlrabi welsh onion</span> daikon amaranth tatsoi
  tomatillo melon azuki bean garlic.
</p>

<p class="highlight">
  Gumbo beet greens corn soko <strong>endive</strong> gumbo gourd. Parsley
  shallot courgette tatsoi pea sprouts fava bean collard greens dandelion okra
  wakame tomato. Dandelion cucumber earthnut pea peanut soko zucchini.
</p>
body {
  font-family: sans-serif;
}

span.highlight {
  background-color: yellow;
}

h1.highlight {
  background-color: pink;
}

이 방식을 사용하면 CSS 규칙이 적용되는 '범위(scope)'를 확 줄일 수 있어요. 오직 그 특정 태그와 특정 클래스의 조합일 때만 스타일이 먹히거든요. 만약 다른 요소에도 같은 스타일을 주고 싶다면, 쉼표를 써서 선택자를 하나 더 추가해 줘야 합니다.

여러 개의 클래스가 적용된 요소 타겟팅하기 (Target an element if it has more than one class applied)

하나의 HTML 요소에 여러 개의 클래스를 동시에 달아줄 수 있다는 거, 알고 계셨나요? 이때 각 클래스별로 스타일을 따로따로 지정할 수도 있고, 특정 클래스들이 '모두' 적용되어 있을 때만 스타일이 들어가도록 만들 수도 있어요. 이 방법은 웹사이트에서 다양한 방식으로 조립될 수 있는 '컴포넌트'를 만들 때 아주 유용합니다.

아래 예제를 보면 안내 문구를 담고 있는 <div> 박스가 있어요. 이 박스에 notebox라는 클래스가 있으면 회색 테두리가 생깁니다. 그런데 여기에 warning이나 danger라는 클래스를 추가로 달아주면, 테두리 색상(border-color)이 바뀌게 만들어 놨어요.

브라우저에게 "이 요소가 두 개의 클래스를 동시에 가지고 있을 때만 스타일을 적용해 줘!"라고 알려주려면, 띄어쓰기 없이 클래스 선택자들을 연달아 다닥다닥 붙여서 쓰면 됩니다.
HTML 코드의 맨 마지막 <div>를 보시면 아시겠지만, 이 녀석은 스타일이 전혀 적용되지 않았어요. 왜냐고요? danger 클래스만 덩그러니 가지고 있거든요. 제대로 된 경고 박스 스타일을 얻으려면 기본 틀인 notebox 클래스도 함께 있어야 한답니다.

<div class="notebox">This is an informational note.</div>

<div class="notebox warning">This note shows a warning.</div>

<div class="notebox danger">This note shows danger!</div>

<div class="danger">
  This won't get styled — it also needs to have the notebox class
</div>
body {
  font-family: sans-serif;
}

.notebox {
  border: 4px solid #666666;
  padding: 0.5em;
  margin: 0.5em;
}

.notebox.warning {
  border-color: orange;
  font-weight: bold;
}

.notebox.danger {
  border-color: red;
  font-weight: bold;
}

💡 강사의 실무 밀착 팁:
이 '다중 클래스' 개념은 정말정말 중요합니다! Storybook 같은 도구를 활용해서 컴포넌트 주도 개발(CDD)을 하실 때, 이 패턴을 밥 먹듯이 쓰게 될 거예요. 예를 들어, 기본 <Button> 컴포넌트의 뼈대를 깎아놓고, 상황에 따라 primary, danger, outline 같은 상태(State) 클래스를 clsxclassnames 같은 라이브러리로 동적으로 뗐다 붙였다 하면서 UI를 구성하게 되거든요. 이 개념이 튼튼해야 확장성 있는 프론트엔드 컴포넌트를 설계할 수 있답니다.


ID 선택자 (ID selectors)

대소문자를 구분하는 ID 선택자는 클래스의 점(.) 대신 해시(#) 기호로 시작합니다. 작성하는 방법은 클래스 선택자와 거의 똑같아요.

하지만 결정적인 차이점이 있습니다! ID는 웹 페이지 전체 문서에서 딱 한 번, 오직 유일하게 하나만 사용해야 해요. 그리고 HTML 요소도 단 하나의 id 값만 가질 수 있죠.

ID 선택자는 이렇게 유일무이한 특정 id를 가진 요소를 딱 꼬집어 냅니다. 클래스에서 했던 것처럼, 태그명#아이디 형식으로 앞에 요소(태그) 선택자를 붙여서 그 태그이면서 동시에 그 ID를 가진 경우에만 적용되도록 더 구체적으로 작성할 수도 있어요. 아래 예제에서 두 가지 방식을 모두 확인해 보세요.

<h1 id="heading">ID selector</h1>
<p>
  Veggies es bonus vobis, proinde vos postulo essum magis kohlrabi welsh onion
  daikon amaranth tatsoi tomatillo melon azuki bean garlic.
</p>

<p id="one">
  Gumbo beet greens corn soko <strong>endive</strong> gumbo gourd. Parsley
  shallot courgette tatsoi pea sprouts fava bean collard greens dandelion okra
  wakame tomato. Dandelion cucumber earthnut pea peanut soko zucchini.
</p>
body {
  font-family: sans-serif;
}

#one {
  background-color: yellow;
}

h1#heading {
  color: rebeccapurple;
}

⚠️ 주의사항 (Warning):
하나의 문서 내에서 똑같은 ID를 여러 번 사용해도 겉보기에는 CSS 스타일이 정상적으로 들어가는 것처럼 보일 수는 있어요. 하지만 절대 그렇게 하시면 안 됩니다. 이건 명백히 문법에 어긋나는(invalid) 코드이며, 자바스크립트 동작이나 접근성 측면 등 여러 곳에서 아주 이상한 버그를 만들어낼 거예요.

💡 강사의 팁:
최신 프론트엔드 환경(React, Next.js 등)에서는 재사용 가능한 '컴포넌트' 단위로 코딩을 하잖아요? 그렇기 때문에 화면에 똑같은 컴포넌트가 여러 개 렌더링 될 수 있어서, 스타일링을 위해 ID 선택자를 사용하는 경우는 이제 실무에서 거의 멸종(?)되었다고 보셔도 무방합니다.

하지만! ID가 쓸모없어진 건 절대 아니에요. 시각 장애인분들이 사용하는 스크린 리더기를 위한 웹 접근성(a11y) 작업(예: aria-labelledby, <label for="...">)을 하거나, Next.js에서 앵커(anchor) 스크롤 이동을 구현할 때는 여전히 핵심적인 역할을 하니 ID의 유일성을 꼭 기억해 주세요. 곧 있으실 기술/임원 면접에서도 "왜 요즘은 스타일링에 ID를 잘 쓰지 않나요?"라는 질문에 방금 말씀드린 '컴포넌트의 재사용성'을 언급하신다면 아주 좋은 점수를 얻으실 수 있을 거예요!

ID 선택자로 놀아보기 (Playing with ID selectors)

위 예제를 다음과 같이 직접 수정해 보세요:
1. HTML 코드를 수정해서 #one 스타일이 두 번째 문단이 아닌, 첫 번째 문단에 적용되도록 바꿔보세요.
2. CSS 코드로 가서 ID 선택자 안의 스타일 속성들을 변경해 보고, HTML이 어떻게 시각적으로 변하는지 관찰해 보세요.


선택자 목록 (Selector lists)

완전히 똑같은 CSS 스타일을 여러 개의 다른 요소들에 동시에 적용하고 싶다면 어떻게 해야 할까요? 똑같은 코드를 여러 번 복사 붙여넣기 할 필요 없이, 개별 선택자들을 쉼표(,)로 연결해서 하나의 '선택자 목록(Selector list)'으로 만들면 됩니다! 이렇게 하면 그 규칙이 목록에 있는 모든 선택자에게 똑같이 적용돼요.

예를 들어, h1 태그와 .special 클래스에 똑같은 CSS를 주고 싶을 때, 원래라면 이렇게 두 번 나눠서 써야겠죠.

h1 {
  color: blue;
}

.special {
  color: blue;
}

하지만 이 둘 사이에 쉼표를 딱! 찍어서 하나의 목록으로 합칠 수 있습니다.

h1, .special {
  color: blue;
}

쉼표 앞뒤로 공백이나 줄바꿈을 넣어도 문법적으로 전혀 문제가 없어요. 오히려 선택자가 많아지면 아래처럼 한 줄에 하나씩 적어주는 게 나중에 눈으로 읽고 파악하기 훨씬 편하답니다.

h1,
.special {
  color: blue;
}

선택자 목록으로 놀아보기 (Playing with selector lists)

아래 예제를 보세요. CSS 코드를 살펴보면 완전히 똑같은 스타일 선언(color: rebeccapurple;)을 가지고 있는 두 개의 선택자가 보일 거예요. 이 둘을 쉼표를 사용해 하나로 합쳐보세요! 코드를 합친 후에도 결과물 화면의 모습은 전과 똑같이 보여야 정답입니다.

<h1>Type selectors</h1>
<p>
  Veggies es bonus vobis, proinde vos postulo essum magis
  <span>kohlrabi welsh onion</span> daikon amaranth tatsoi tomatillo melon azuki
  bean garlic.
</p>

<p>
  Gumbo beet greens corn soko <strong>endive</strong> gumbo gourd. Parsley
  shallot courgette tatsoi pea sprouts fava bean collard greens dandelion okra
  wakame tomato. Dandelion cucumber earthnut pea peanut soko zucchini.
</p>

<p>
  Turnip greens yarrow ricebean rutabaga <em>endive cauliflower</em> sea lettuce
  kohlrabi amaranth water spinach avocado daikon napa cabbage asparagus winter
  purslane kale. Celery potato scallion desert raisin horseradish spinach
</p>
body {
  font-family: sans-serif;
}
span {
  background-color: yellow;
}

strong {
  color: rebeccapurple;
}

em {
  color: rebeccapurple;
}

선택자 목록 안에 잘못된 문법이 섞여 있다면? (Invalid selectors in selector lists)

선택자들을 쉼표로 묶어줄 때 주의해야 할 점이 딱 하나 있습니다. 묶여있는 선택자들 중에서 단 하나라도 문법적으로 잘못된(invalid) 선택자가 껴있다면, 브라우저는 그 전체 규칙을 통째로 무시해 버립니다.

아래 예시를 볼까요? 두 개의 개별 규칙으로 나뉘어 있을 때는, 두 번째 클래스 선택자(..special - 점이 두 개 들어간 오타)가 잘못되었기 때문에 무시되지만, 첫 번째 h1에 대한 규칙은 정상적으로 스타일이 들어갑니다.

h1 {
  color: blue;
}

..special {
  color: blue; /* 잘못된 문법이지만 얘만 무시됨 */
}

하지만 이 둘을 쉼표로 묶어버리면? 연대책임을 물게 됩니다. h1도 애먼 피해를 봐서 스타일이 적용되지 않고, 전체 CSS 블록이 버려지게 돼요.

h1, ..special {
  color: blue; /* 에러! 전체 규칙이 통째로 무시됩니다. */
}

전체 선택자 (The universal selector)

전체 선택자는 별표(*, 애스터리스크) 기호로 표시합니다. 말 그대로 문서 안에 있는 모든 요소를 모조리 선택해 버리는 강력한 녀석이죠.

만약 이 *하위 결합자(Descendant combinator)와 함께 체이닝해서 쓰면, 특정 부모 요소 안에 있는 '모든 자손 요소'를 선택하게 됩니다. 예를 들어 p *라고 쓰면, <p> 태그 안에 중첩되어 있는 모든 자식 요소들을 선택한다는 뜻이에요.

아래 예제에서는 전체 선택자를 이용해 웹페이지의 모든 요소가 가지고 있는 기본 마진(margin) 여백을 0으로 없애버렸습니다. 브라우저가 기본적으로 제공하는 널찍널찍한 여백 스타일 대신, 모든 제목과 문단들이 다닥다닥 좁게 붙어있는 걸 확인하실 수 있을 거예요.

<h1>Universal selector</h1>
<p>
  Veggies es bonus vobis, proinde vos postulo essum magis
  <span>kohlrabi welsh onion</span> daikon amaranth tatsoi tomatillo melon azuki
  bean garlic.
</p>

<p>
  Gumbo beet greens corn soko <strong>endive</strong> gumbo gourd. Parsley
  shallot courgette tatsoi pea sprouts fava bean collard greens dandelion okra
  wakame tomato. Dandelion cucumber earthnut pea peanut soko zucchini.
</p>
body {
  font-family: sans-serif;
}

* {
  margin: 0;
}

이렇게 모든 요소의 스타일을 싹 다 날려버리는 패턴은 보통 브라우저의 제각각인 기본 스타일을 통일시켜주는 "초기화 스타일시트(Reset stylesheets)"에서 자주 볼 수 있습니다. 전체 선택자는 이처럼 전역적으로 거대한 변화를 일으키기 때문에, 생각보다 실무에서 마구잡이로 쓰지는 않고 방금 말씀드린 초기화 작업이나, 아래 설명해 드릴 아주 특수한 상황에서만 제한적으로 사용된답니다.

💡 강사의 팁:
현업에서 프론트엔드 환경 세팅을 할 때 가장 먼저 하는 일 중 하나가 바로 브라우저 간의 미세한 스타일 차이를 없애는 것입니다. 보통 reset.cssnormalize.css 등을 적용하게 되는데, 이런 초기화 파일들을 뜯어보시면 이 전체 선택자(*)를 활용해 box-sizing: border-box를 설정하거나 마진, 패딩을 날려버리는 코드를 아주 쉽게 발견하실 수 있을 거예요!

가독성을 높이기 위해 전체 선택자 활용하기 (Using the universal selector to make your selectors easier to read)

전체 선택자의 또 다른 쓰임새는 복잡한 선택자 조합을 조금 더 직관적이고 읽기 편하게 만들어 준다는 데 있습니다.

예를 들어볼게요. <article> 요소의 첫 번째 자식이거나 그 자손들 중에서 부모의 첫 번째 자식인 모든 요소를 선택하고 싶다고 해보죠. (말이 조금 어렵죠?) 이때 우리는 :first-child라는 가상 클래스(pseudo-class)를 사용할 수 있습니다. (가상 클래스와 가상 요소에 대해서는 가상 클래스와 가상 요소 챕터에서 나중에 더 자세히 배울 테니 지금은 느낌만 보세요!)

article :first-child {
  font-weight: bold;
}

위 코드를 잘 보면 article:first-child 사이에 띄어쓰기(하위 결합자)가 있습니다. 그런데 이걸 얼핏 잘못 보면, article:first-child (띄어쓰기 없음. 즉, 자신이 누군가의 첫 번째 자식인 <article> 태그를 의미)와 헷갈리기 딱 좋습니다.

이런 오해를 방지하고 "아, <article> 하위에 있는 모든(*) 요소들 중에 첫 번째 자식인 것들을 싹 다 고르라는 거구나!"라고 훨씬 명확하게 의미를 전달하기 위해, 띄어쓰기 자리에 전체 선택자(*)를 명시적으로 끼워 넣어줄 수 있어요.

article *:first-child {
  font-weight: bold;
}

이 두 가지 코드는 브라우저 입장에선 100% 똑같이 동작합니다. 하지만 코드를 읽고 유지 보수해야 하는 사람(동료 개발자 등)의 입장에서는 두 번째 방식이 훨씬 가독성이 좋고 오해의 소지가 없다고 느끼는 경우가 많습니다.

📝 참고사항 (Note):
실제 상용 웹사이트의 소스 코드에서 이 기법이 아주 흔하게 쓰이는 건 아닙니다. 저희 MDN 내부 코드에서도 잘 쓰지 않고요. 하지만 코드를 작성하다가 "이거 나중에 다른 사람이(혹은 미래의 내가) 읽었을 때 헷갈리지 않을까?"라는 생각이 든다면, 이해를 돕기 위해 전체 선택자를 추가하는 방식을 충분히 고려해 볼 만합니다.


요약 (Summary)

이번 문서에서는 우리가 HTML 요소들에 예쁜 스타일을 적용하기 위해 어떤 식으로 대상에 조준해야 하는지, 즉 CSS 선택자에 대해 쭉 복습해 보았습니다. 특히 타입, 클래스, ID 선택자의 특징들을 이전보다 조금 더 깊이 있게 파고들어 봤죠.

탄탄하게 뼈대를 잡으셨으니, 다음 문서에서는 요소가 가지고 있는 속성값을 이용해 디테일하게 요소를 선택하는 속성 선택자(Attribute selectors)의 세계로 풍덩 빠져보겠습니다.

📝 참고사항 (Note):
세상에 존재하는 모든 CSS 선택자 리스트를 한눈에 보고 싶으시다면, MDN의 CSS 선택자 레퍼런스 가이드(CSS selectors reference)를 꼭 참고해 보세요!

profile
프론트에_가까운_풀스택_개발자

0개의 댓글