스크랩
라이브러리 없이 끝내는 UI, 브라우저가 이미 다 갖고 있었다

새 프레임워크 대신 브라우저 기본기부터
요즘 웹 개발 하다 보면 모달 하나, 아코디언 하나 만들 때도 라이브러리부터 검색하게 되죠. 그런데 사실 최신 브라우저는 HTML·CSS·JS만으로도 꽤 많은 걸 네이티브하게 처리할 수 있습니다. GeekNews에 소개된 'HTMLcat' 레퍼런스 사이트는 이런 작은 팁 42개를 모아둔 곳인데, 오늘은 그중 핵심만 골라 정리해봤습니다.
입력 방식을 추측하지 말고 물어보자
any-pointer,any-hover미디어 쿼리를 쓰면 User-Agent로 모바일인지 데스크톱인지 눈치 볼 필요 없이, 실제로 연결된 입력 장치가 정밀 포인터인지 터치인지 Hover가 가능한지 바로 알 수 있습니다.- 터치스크린 노트북처럼 두 가지 입력이 공존하는 기기도 자연스럽게 커버됩니다. 단, Hover에만 의존한 기능은 키보드·터치 사용자를 소외시키니 항상 대체 경로를 마련해두세요.
CSS 셀렉터로 상태 관리 줄이기
:has()는 자식이나 형제 조건으로 부모를 선택할 수 있어서,form:has(:invalid)처럼 하위 요소 상태에 따라 부모 스타일을 바꾸는 게 가능해졌습니다.:target은 URL의#fragment가 가리키는 요소를 선택하니, 딥링크 강조나 간단한 패널 전환을 JS 상태 없이 구현할 수 있어요.:where()는 여러 셀렉터를 묶으면서 Specificity를 0으로 만들어주기 때문에, 나중에 쉽게 덮어쓸 수 있는 기본 스타일 작성에 유용합니다.classList.toggle(class, boolean)처럼 두 번째 인자에 boolean을 넘기면 상태를 '반전'시키는 대신 명시적으로 동기화할 수 있습니다.
레이아웃, 이제 트릭이 필요 없다
- 중앙 정렬은
display: grid; place-items: center두 줄이면 끝. 1차원 배치는 Flexbox가 여전히 더 적합합니다. @scope는 네임스페이스 클래스를 매번 붙이지 않고도 특정 DOM 영역으로 CSS 적용 범위를 제한할 수 있습니다. 다만 상속 속성과 커스텀 프로퍼티는 경계를 넘나드니 완전한 캡슐화는 아니라는 점 기억하세요.- Container Query를 쓰면 뷰포트가 아니라 컴포넌트가 실제로 받은 공간을 기준으로 카드 레이아웃을 바꿀 수 있습니다.
- CSS Grid Lanes는 네이티브 Masonry를 목표로 개발 중이지만 아직 실험 단계라 프로덕션에는 조심스럽게 접근해야 합니다.
스크롤·전환 효과도 CSS 선에서
scrollbar-width: none으로 스크롤 기능은 유지하면서 스크롤바만 숨길 수 있고,scroll-behavior: smooth만으로 앵커 이동을 부드럽게 만들 수 있습니다.prefers-reduced-motion사용자를 위한 배려도 잊지 마세요.- 고정 헤더 때문에 앵커 이동 후 제목이 가려지는 흔한 문제는
scroll-margin-block-start한 줄로 해결됩니다. - View Transitions API는 두 DOM 상태 사이의 전환을 브라우저가 알아서 애니메이션해주고, 미지원 환경에서는 기존 방식으로 자연스럽게 폴백됩니다.
텍스트와 색상 다루기
clamp(min, fluid, max)로 브레이크포인트별 분기 없이 글자 크기·여백을 자연스럽게 조절할 수 있습니다.text-wrap: balance(제목용)와text-wrap: pretty(본문용)는 줄바꿈을 훨씬 자연스럽게 만들어줍니다.- CSS Custom Highlight API는
<span>을 삽입하지 않고도 임의의 텍스트 범위를 강조할 수 있어 검색 결과나 에디터 오버레이에 특히 유용해요. light-dark()로 라이트·다크 두 색상을 한 선언에 정의하고,color-mix()로 반투명 색상을 손쉽게 만들 수 있습니다.accent-color하나면 체크박스·라디오·프로그레스바 강조색을 한 번에 바꿀 수 있고요.
JS 없이 되는 UI들
<dialog>는 모달을 Top Layer에 띄우고 포커스 트랩, Escape 닫기까지 알아서 처리해줍니다.- Popover API는 비모달 메뉴·패널을 위한 것으로, 바깥 클릭·Escape 닫기를 브라우저가 담당합니다.
- 여러
<details>에 같은name을 주면 아코디언이 상태 관리 JS 없이 완성됩니다. inert속성으로 특정 DOM 영역을 포커스·포인터·접근성 트리에서 통째로 제외시킬 수도 있습니다.
정리하며
핵심은 하나입니다 — 뭔가를 직접 구현하기 전에, 브라우저가 이미 제공하지 않는지 먼저 확인해보자는 것. 다만 :has()나 Container Query처럼 안정적인 기능도 있지만, CSS Grid Lanes나 Scroll Snap Events처럼 아직 Experimental 단계인 기능도 섞여 있으니 @supports로 감싸거나 기존 구현을 폴백으로 남겨두는 점진적 향상 전략은 꼭 챙기시길 바랍니다.