HTML id와 class 차이
HTML 요소를 구분할 때 id와 class를 자주 사용한다.
둘 다 CSS와 JavaScript에서 요소를 찾는 데 쓸 수 있지만, 표현하는 관계가 다르다.
id는 문서 안에서 하나의 요소를 식별한다.class는 같은 특징이나 역할을 공유하는 여러 요소를 묶는다.
한 요소에 둘을 함께 사용할 수도 있다.
중요한 것은 선택자 문법보다 그 이름이 단일 식별자인지 재사용 가능한 그룹인지다.
id의 역할
id는 HTML 문서 전체에서 특정 요소 하나를 가리키는 식별자다.
같은 문서 안의 id 값은 서로 달라야 한다.
<main id="content">
<h1>게시글 목록</h1>
</main>위 문서에서 content는 이 main 요소를 식별한다.
다른 요소에 같은 id="content"를 다시 사용하지 않는다.
id 값에는 ASCII 공백을 넣을 수 없다.
한 요소는 하나의 id 값만 가진다.
<!-- 잘못된 값: 공백이 들어가 있다. -->
<main id="main content"></main>
<!-- 하나의 식별자로 작성한다. -->
<main id="main-content"></main>브라우저가 공백이 있는 값을 그대로 처리할 수는 있지만 CSS 선택자와 JavaScript 코드에서 다루기 불편해진다.
처음부터 CSS identifier로 쓰기 쉬운 이름을 선택하는 편이 안전하다.
class의 역할
class는 공통 특징을 가진 요소를 그룹으로 묶는다.
같은 class를 여러 요소에 반복해서 사용할 수 있다.
<article class="card">첫 번째 글</article>
<article class="card">두 번째 글</article>
<article class="card">세 번째 글</article>세 요소는 모두 card라는 같은 역할과 스타일을 공유한다.
한 요소에 여러 class를 공백으로 구분해 넣을 수도 있다.
<button class="button button-primary is-loading" type="button">
저장 중
</button>이 버튼에는 button, button-primary, is-loading 세 class가 있다.
기본 버튼 스타일, 강조 변형, 현재 상태를 각각 분리해서 표현할 수 있다.
id와 class의 핵심 차이
두 속성은 다음 기준으로 구분할 수 있다.
id는 문서 안에서 유일한 요소를 식별한다.class는 여러 요소가 공유할 수 있는 그룹 이름이다.- 한 요소는 하나의
id값을 가진다. - 한 요소는 여러 class 값을 동시에 가질 수 있다.
id는 fragment 이동과 다른 HTML 속성의 참조 대상이 될 수 있다.class는 반복되는 스타일과 상태를 묶는 데 자연스럽다.
페이지의 유일한 본문 영역을 가리킨다면 id="content"가 어울린다.
여러 게시글 카드를 같은 모양으로 꾸민다면 class="card"가 어울린다.
CSS에서 id 선택하기
CSS에서는 # 기호로 id를 선택한다.
#content {
max-width: 720px;
margin-inline: auto;
}이 규칙은 id="content"인 요소를 선택한다.
id selector는 class selector보다 specificity가 높다.
나중에 class로 스타일을 덮어쓰려고 할 때 예상보다 강하게 남을 수 있다.
#save-button {
background: gray;
}
.button-primary {
background: blue;
}두 선택자가 같은 요소에 적용되면 id selector의 우선순위가 더 높다.
단순한 작성 순서만으로 .button-primary가 이기지 못할 수 있다.
그래서 재사용하는 컴포넌트 스타일은 보통 class 중심으로 작성하는 편이 관리하기 쉽다.
id는 문서 식별과 참조에 사용하고, 시각적 스타일은 class에 맡기는 방식이 예측 가능하다.
CSS에서 class 선택하기
CSS에서는 . 기호로 class를 선택한다.
.card {
padding: 20px;
border: 1px solid #d8dee4;
}class="card"를 가진 모든 요소에 같은 스타일이 적용된다.
여러 class를 조합해 특정 상태만 선택할 수도 있다.
.button {
padding: 10px 16px;
}
.button.button-primary {
background: #1769e0;
color: #fff;
}
.button.is-loading {
cursor: wait;
opacity: 0.6;
}기본 형태와 변형, 상태를 작은 class로 나누면 같은 HTML 요소에 필요한 조합을 만들 수 있다.
요소의 block과 inline 동작이 헷갈린다면 CSS display block inline inline-block 차이를 함께 보면 좋다.
JavaScript에서 id 찾기
JavaScript에서는 document.getElementById()로 id를 가진 요소를 찾을 수 있다.
const dialog = document.getElementById('confirm-dialog')
dialog?.showModal()CSS selector 문법을 사용하는 querySelector()도 가능하다.
const dialog = document.querySelector('#confirm-dialog')getElementById()에는 #을 붙이지 않는다.querySelector()에는 CSS id selector인 #을 붙인다.
id 값이 window 객체의 property처럼 노출되는 브라우저 동작에 기대는 것은 피하는 편이 좋다.
// 피하는 편이 좋은 방식
console.log(window.content)
// 의도가 분명한 방식
const content = document.getElementById('content')브라우저에 같은 이름의 API가 추가되거나 전역 변수와 충돌하면 예상하지 못한 결과가 생길 수 있다.
JavaScript에서 class 찾기
같은 class를 가진 여러 요소는 querySelectorAll()로 찾을 수 있다.
const cards = document.querySelectorAll('.card')
for (const card of cards) {
card.classList.add('is-visible')
}첫 번째 요소 하나만 필요하면 querySelector()를 사용한다.
const firstCard = document.querySelector('.card')class를 추가하거나 제거할 때는 문자열 전체를 직접 바꾸기보다 classList를 사용하는 편이 안전하다.
const menu = document.querySelector('.menu')
menu?.classList.toggle('is-open')기존 class를 보존하면서 상태 class만 변경할 수 있다.
fragment 링크에서 id 사용하기
URL의 # 뒤에 붙는 fragment identifier는 문서 안의 id를 가리킬 수 있다.
<a href="#comments">댓글로 이동</a>
<section id="comments">
<h2>댓글</h2>
</section>링크를 선택하면 브라우저는 id="comments"인 요소로 이동한다.
목차, 본문 건너뛰기 링크, 긴 문서의 특정 섹션 공유에 유용하다.
이때 중복 id가 있으면 어느 요소가 목적지인지 문서 구조가 모호해진다.
id를 유일하게 유지해야 하는 이유가 단순한 코딩 스타일에 그치지 않는다.
이동과 동작에 어떤 HTML 요소를 선택할지는 HTML button과 a 태그 차이에서 정리했다.
다른 HTML 속성에서 id 참조하기
id는 다른 요소가 특정 요소를 참조할 때도 사용된다.
<label for="email">이메일</label>
<input id="email" name="email" type="email" />label의 for 값은 연결할 form control의 id와 같아야 한다.
사용자가 label을 눌렀을 때 input에 초점이 이동하고 보조 기술도 관계를 이해할 수 있다.
ARIA 관계에서도 id를 참조할 수 있다.
<button aria-describedby="delete-help" type="button">삭제</button>
<p id="delete-help">삭제한 항목은 복구할 수 없습니다.</p>aria-describedby는 설명 요소의 id를 값으로 사용한다.
이런 참조 대상은 같은 문서에서 명확하게 하나여야 한다.
중복 id 문제
반복 목록을 만들면서 같은 id를 복사하면 중복 id가 생기기 쉽다.
<!-- 피해야 하는 구조 -->
<article id="card">첫 번째 글</article>
<article id="card">두 번째 글</article>스타일은 겉으로 적용되는 것처럼 보일 수 있다.
하지만 fragment 이동, label 연결, JavaScript 탐색, 접근성 tree에서는 관계가 불명확해진다.
반복되는 요소라면 class를 사용한다.
<article class="card">첫 번째 글</article>
<article class="card">두 번째 글</article>각 항목에 정말 고유한 식별자가 필요하다면 실제 데이터의 고유 값을 포함한다.
<article id="post-101" class="card">첫 번째 글</article>
<article id="post-102" class="card">두 번째 글</article>class 이름 작성 기준
class 이름은 현재 보이는 색이나 위치보다 요소의 역할을 나타내는 편이 오래 간다.
<!-- 표현에 묶인 이름 -->
<p class="red-text">오류가 발생했습니다.</p>
<!-- 역할을 나타내는 이름 -->
<p class="error-message">오류가 발생했습니다.</p>디자인이 빨간색에서 다른 표현으로 바뀌어도 error-message라는 이름은 여전히 의미가 있다.
상태는 is-open, is-selected, is-loading처럼 구분하면 읽기 쉽다.
<nav class="menu is-open"></nav>프로젝트에 이미 BEM, CSS Modules, utility class 같은 규칙이 있다면 그 규칙을 우선한다.
중요한 것은 같은 의미를 같은 방식으로 표현하는 일관성이다.
id를 스타일에 사용하지 않는 기준
id selector가 금지된 것은 아니다.
문서에서 정말 하나뿐인 영역을 빠르게 지정할 수 있다.
다만 컴포넌트 스타일에 id를 많이 사용하면 재사용이 어려워지고 specificity가 높아진다.
같은 컴포넌트를 두 번 렌더링하는 순간 id의 유일성도 깨질 수 있다.
.site-header {
min-height: 64px;
}<header id="site-header" class="site-header"></header>위처럼 id는 fragment나 script 참조에 사용하고 class는 스타일에 사용하는 식으로 역할을 분리할 수 있다.
선택 기준
문서 안에서 단 하나의 요소를 식별하거나 다른 HTML 속성에서 참조해야 한다면 id를 사용한다.
<main id="main-content"></main>여러 요소가 같은 스타일, 역할, 상태를 공유한다면 class를 사용한다.
<article class="post-card"></article>
<article class="post-card"></article>한 요소가 고유한 식별자와 재사용 스타일을 모두 가져야 한다면 둘을 함께 사용한다.
<section id="profile" class="panel panel-highlighted"></section>정리
id는 HTML 문서 전체에서 하나의 요소를 식별한다.
fragment 링크, label 연결, ARIA 참조, JavaScript의 단일 요소 탐색에 사용된다.
class는 여러 요소가 공유할 수 있는 그룹 이름이다.
한 요소에 여러 class를 조합할 수 있고 반복되는 스타일과 상태 표현에 적합하다.
CSS에서는 #id와 .class로 선택하지만, 선택자 문법만 보고 둘을 고르면 부족하다.
하나를 가리키는 식별자면 id, 반복 가능한 역할이면 class라는 의미부터 정하는 편이 좋다.
참고 자료
















