웹사이트를 만들 때 자주 마주치는 한계가 있다. "이 체크박스가 켜져 있으면 폼 전체의 테두리 색을 바꿔 줘", "이 카드 안에 이미지가 있으면 그리드 한 칸을 두 칸으로 늘려 줘". 디자인에서는 쉬워 보이지만, 코드로 옮기려는 순간 자바스크립트를 꺼내 들어야 했다. 이유는 단순하다. CSS는 자식과 형제로 내려갈 수는 있어도, 자식의 상태를 보고 부모를 바꾸지는 못했기 때문이다.
이 마지막 한 칸을 채우는 선택자가 :has()다. 2024년 모든 주요 브라우저가 안정적으로 지원하기 시작했고, 2026년 지금은 자바스크립트 없이도 폼과 카드, 표와 모달이 사용자의 입력에 반응한다.
CSS는 왜 오랫동안 부모를 못 봤을까
브라우저는 HTML을 위에서 아래로 한 번에 읽어 스타일을 입힌다. 자식의 상태가 바뀔 때마다 부모로 거슬러 올라가 모든 스타일을 다시 그려야 한다면 성능이 무너진다. 그래서 부모 선택자는 "원리적으로 어렵다"는 이유로 오래 미뤄졌다. 그러나 브라우저 엔진이 충분히 빨라진 시대가 왔고, 마침내 부모도 자식을 본다.
:has()의 문법은 한 줄이다
형태는 단순하다. 부모:has(자식)으로 쓰면 "이런 자식을 가진 부모"를 선택한다. article:has(img)는 이미지를 가진 글에만 스타일을 입히고, label:has(input:checked)는 체크된 입력의 라벨만 강조한다. 형제 결합자도 안에서 자유롭게 쓸 수 있어, 거의 모든 관계를 한 줄로 표현할 수 있다.
자바스크립트가 사라지는 다섯 가지 실전 패턴
1. 입력이 있는 필드만 라벨이 떠오른다
.field:has(input:not(:placeholder-shown)) label 한 줄이면 "내용이 입력된 필드는 라벨을 위로 띄운다"가 끝난다. 플로팅 라벨 패턴을 만들려고 자바스크립트로 입력 이벤트를 듣지 않아도 된다.
2. 이미지가 있는 카드만 그리드 두 칸을 차지한다
.card:has(img) { grid-column: span 2 }. 블로그 목록처럼 콘텐츠가 동적으로 들어오는 화면에서, 사진이 있는 글만 자연스럽게 강조할 수 있다.
3. 체크된 행만 표가 강조된다
tr:has(input:checked) { background: #fff6e0 }. 관리자 화면의 다중 선택이 자바스크립트 없이도 동작한다. tbody:has(input:checked) ~ .footer처럼 형제 결합자를 이어 붙이면, 한 행이라도 선택된 순간 하단의 일괄 처리 버튼을 띄우는 패턴도 한 줄로 가능하다.
4. 비어 있는 영역에 안내가 자동으로 나타난다
.list:not(:has(li))::before { content: "표시할 항목이 없습니다" }. 빈 상태 메시지를 서버에서 따로 그릴 필요가 없다. 항목 하나가 들어오는 순간 안내는 사라진다.
5. 모달이 열린 동안 본문 스크롤이 잠긴다
body:has(dialog[open]) { overflow: hidden }. 모달과 본문을 자바스크립트로 묶어 두지 않아도, 모달이 열린 그 순간 본문 스크롤만 깔끔하게 멈춘다.
한 가지 주의: 너무 넓은 범위는 피한다
크롬, 사파리, 파이어폭스 모두 안정 버전에서 :has()를 지원한다. 다만 너무 넓은 조상에 걸어 둔 선택자—예를 들어 body:has(.card:hover)처럼 마우스 움직임마다 전체 페이지의 스타일을 다시 계산해야 하는 패턴—은 피하는 편이 좋다. 변경의 범위를 가능한 한 가까운 조상까지로 좁히는 것이 핵심이다. :has()는 강력한 만큼, 어디에 걸어 두는지에 따라 성능 부담이 크게 달라진다.
인터페이스를 가볍게 만드는 새로운 기본기
지난 십 년 동안 우리는 자바스크립트로 부모의 상태를 흉내 내 왔다. 입력을 감지하는 리스너, 클래스를 토글하는 함수, 상태를 따로 보관하는 변수—모두 디자인의 의도와는 거리가 먼 보조 코드였다. :has()는 그 코드를 한 줄짜리 CSS로 되돌려 놓는다. 번들 크기가 줄고, 사용자 입력에 대한 반응 속도가 빨라지며, 무엇보다 디자인 의도가 마크업과 스타일 안에 그대로 머문다.
CYAN은 새로운 CSS 표준을 일찍 도입해, 가볍고 빠르며 오래 유지되는 웹사이트를 만든다. 자바스크립트 없이도 잘 동작하는 인터페이스가 더 적합한 자리가 어디인지, 함께 살펴 드린다.