WeniVooks

검색

HTML/CSS 에센셜

가상 클래스 심화

1. 고급 포커스 선택자

1.1 :focus-visible

:focus와 유사하지만 :focus는 포커스된 요소에 항상 적용되는 반면, :focus-visible은 좀 더 선택적으로 작동합니다.

:focus-visible은 주로 키보드를 사용하여 페이지를 탐색할 때나 스크립트를 통해 포커스가 관리될 때 활성화됩니다. 이는 사용자가 현재 어떤 요소에 포커스가 있는지 시각적으로 확인해야 하는 상황에서 유용합니다. 그러나 마우스나 터치 인터페이스를 사용하여 요소에 물리적으로 포커스를 설정할 때는 일반적으로 :focus-visible이 활성화되지 않습니다. 이는 사용자가 이미 자신이 어떤 요소를 선택했는지 알고 있기 때문입니다.

:focus-visible의 주요 목적은 사용자 경험을 개선하는 것입니다. 이 가상 클래스를 사용함으로써 불필요한 시각적 표시를 줄여 인터페이스를 깔끔하게 유지할 수 있습니다. 동시에 키보드 사용자에게는 명확한 포커스 표시를 제공하여 웹 접근성을 향상시킬 수 있습니다.

주의

:focus-visible의 정확한 동작은 브라우저에 따라 약간 다를 수 있습니다. 일부 브라우저에서는 마우스 클릭으로도 :focus-visible이 트리거될 수 있습니다.

1.2 :focus-within

요소 또는 그 자식 요소가 포커스를 받았을 때 적용됩니다.

:focus-within은 폼 디자인에 특히 유용합니다. 사용자가 특정 입력 필드에 포커스를 맞출 때 전체 폼 그룹의 스타일을 변경할 수 있습니다.

2. 상태 관련 가상 클래스 선택자

2.1 :enabled

활성화된 상태의 폼 요소를 선택합니다.

2.2 :disabled

비활성화된 상태의 폼 요소를 선택합니다.

2.3 :checked

체크된 상태의 라디오 버튼이나 체크박스를 선택합니다.

3. 구조적 가상 클래스 선택자 고급

3.1 :root

:root는 문서 트리의 루트 요소를 선택합니다. HTML에서는 <html> 요소를 가리킵니다. 이는 전역 CSS 변수를 선언할 때 주로 사용됩니다. CSS 변수는 --로 시작하는 이름을 가지며, var() 함수를 사용하여 값을 참조할 수 있습니다. 이를 통해 스타일을 더 쉽게 재사용하고 관리할 수 있습니다.

위니브 디자인 시스템

CSS Variables(CSS 사용자 정의 속성)는 특히 브랜드 디자인 시스템을 구축할 때 매우 유용하며, 일관된 스타일을 유지하고 유지보수를 용이하게 합니다. 브랜드 디자인 시스템을 구축할 때는 주로 색상 시스템, 그리드 시스템, 아이콘 시스템 등의 카테고리로 나누어 변수를 관리할 수 있습니다.

CSS Variables의 주요 장점으로는 우선 유지보수성 향상을 들 수 있습니다. 스타일 값을 한 곳에서 중앙 집중식으로 관리할 수 있어, 전체적인 디자인 일관성을 유지하기 쉽고 값을 변경할 때도 한 곳만 수정하면 됩니다. 두 번째로 JavaScript를 통해 동적으로 값을 변경할 수 있어 실시간 테마 변경이나 다크 모드 구현이 용이합니다. 세 번째로 calc() 함수와 함께 사용하여 동적 계산이 가능하므로 반응형 디자인 구현에 효과적입니다.

3.1.1 테마 전환

CSS 변수는 테마 전환에 특히 유용합니다. 다크 모드와 라이트 모드를 쉽게 구현할 수 있습니다.

:root {
  /* 라이트 모드 (기본) */
  --background-color: #ffffff;
  --text-color: #333333;
  --accent-color: #0066cc;
}
 
[data-theme='dark'] {
  /* 다크 모드 */
  --background-color: #222222;
  --text-color: #f0f0f0;
  --accent-color: #4d9fff;
}
 
body {
  background-color: var(--background-color);
  color: var(--text-color);
}
 
a {
  color: var(--accent-color);
}
:root {
  /* 라이트 모드 (기본) */
  --background-color: #ffffff;
  --text-color: #333333;
  --accent-color: #0066cc;
}
 
[data-theme='dark'] {
  /* 다크 모드 */
  --background-color: #222222;
  --text-color: #f0f0f0;
  --accent-color: #4d9fff;
}
 
body {
  background-color: var(--background-color);
  color: var(--text-color);
}
 
a {
  color: var(--accent-color);
}

JavaScript에서는 간단히 아래와 같이 테마를 전환할 수 있습니다.

// 다크 모드로 전환
document.documentElement.setAttribute('data-theme', 'dark');
 
// 라이트 모드로 전환
document.documentElement.removeAttribute('data-theme');
// 다크 모드로 전환
document.documentElement.setAttribute('data-theme', 'dark');
 
// 라이트 모드로 전환
document.documentElement.removeAttribute('data-theme');
의사 클래스 - MDN사용자 지정 CSS 속성 사용하기 - MDN
3.2 :is() and :where()

:is():where()는 여러 개의 선택자를 한꺼번에 지정할 수 있는 간편한 방법을 제공합니다. :is()는 여러 개의 선택자를 지정할 때 사용하며, :where():is()와 유사하지만, 우선순위가 낮습니다.

여러 개의 선택자를 선택하는 것은 기존에도 아래와 같은 방법으로 가능했습니다.

h1,
h2,
h3 {
  color: blue;
}
h1,
h2,
h3 {
  color: blue;
}

다만 만약 h1과 h2와 h3 안에 있는 요소를 선택하고 싶다면 아래와 같이 하나씩 선택자를 지정해야 했습니다.

h1 a,
h2 a,
h3 a {
  color: blue;
}
h1 a,
h2 a,
h3 a {
  color: blue;
}

이러한 경우 :is()를 사용하면 아래와 같이 간단하게 표현할 수 있습니다.

:is(h1, h2, h3) a {
  color: blue;
}
:is(h1, h2, h3) a {
  color: blue;
}

역시 익스플로러를 제외하고 대부분의 브라우저에서 지원하고 있으므로 충분히 실무에서 사용할 수 있습니다.

브라우저 지원 여부

where():is()와 유사하지만, 우선순위가 낮습니다. 아래 예제를 보며 is()where()를 동시에 사용했을 경우 어떻게 처리되는지 확인해 보도록 하겠습니다. 확인이 되었다면 is()를 삭제해 보세요.

3.2.1 :where() 활용

:where()의 가장 큰 장점은 우선순위(specificity)가 0이라는 점입니다. 이는 스타일 재정의가 필요한 상황에서 매우 유용합니다. 예를 들어, 기본 스타일을 정의하면서도 필요한 경우 쉽게 재정의할 수 있게 해줍니다.

/* 기본 스타일 - 낮은 우선순위 */
:where(button, .btn, [type='submit']) {
  padding: 0.5em 1em;
  background-color: #e0e0e0;
  border: 1px solid #ccc;
}
 
/* 특정 컨테이너의 버튼에 다른 스타일 적용 - 쉽게 재정의 가능 */
.form-container button {
  background-color: #0066cc;
  color: white;
}
/* 기본 스타일 - 낮은 우선순위 */
:where(button, .btn, [type='submit']) {
  padding: 0.5em 1em;
  background-color: #e0e0e0;
  border: 1px solid #ccc;
}
 
/* 특정 컨테이너의 버튼에 다른 스타일 적용 - 쉽게 재정의 가능 */
.form-container button {
  background-color: #0066cc;
  color: white;
}

만약 :is() 대신 :where()를 사용하지 않았다면, 두 번째 선택자를 더 구체적으로 만들어야 재정의가 가능했을 것입니다.

3.3 :has()

:has()는 2022년에 도입된 의사 클래스입니다. 이 의사 클래스는 특정 요소가 자식 요소를 포함하고 있는지를 검사할 수 있게 해주며, CSS 선택자의 강력한 기능을 제공합니다. 다른 요소 안에 특정 요소가 포함되어 있는지 여부에 따라 스타일을 적용할 수 있어 매우 유용합니다.

역시 익스플로러를 제외하고 대부분의 브라우저에서 지원하고 있으므로 충분히 실무에서 사용할 수 있습니다.

has() 브라우저 지원 여부

예를 들어, 특정 요소가 자식으로 링크를 포함하고 있는 경우에만 스타일을 적용하고 싶을 때 사용할 수 있습니다. 아래 예시에서는 div 요소가 a 요소를 포함하고 있는 경우에만 배경색을 변경합니다.

3.3.1 실용적인 활용

:has() 선택자는 특히 조건부 스타일링에 강력합니다.

  • 이미지가 포함된 카드만 다르게 스타일링
.card:has(img) {
  padding-top: 0;
}
.card:has(img) {
  padding-top: 0;
}
  • 필수 입력 필드(*)가 있는 라벨 강조
label:has(.required) {
  font-weight: bold;
}
label:has(.required) {
  font-weight: bold;
}
  • 빈 목록 표시 방식 변경
ul:not(:has(li)) {
  display: none;
}
ul:not(:has(li)) {
  display: none;
}

이러한 활용 방식은 기존에는 JavaScript로만 가능했던 조건부 스타일링을 순수 CSS로 구현할 수 있게 해줍니다.

10.3 가상 클래스와 가상 요소 기초10.5 선택자 우선순위