- 최근 웹사이트 성능 저하의 주요 원인은 과도한 JavaScript 사용과 추적 스크립트이며, 많은 경우 HTML/CSS만으로도 충분히 대체 가능함
- CSS 네스팅, 상대 색상, 새로운 뷰포트 단위(lvh, svh, dvh) 등 최근 추가된 기능들은 과거 JS나 전처리기에 의존했던 작업을 간단히 해결할 수 있게 함
- CSS는 단순한 스타일 도구가 아니라 애니메이션, 입력 검증, 다크 모드 테마, 아코디언 메뉴까지 구현 가능한 강력한 언어임
- 성능 측면에서도 CSS는 GPU 가속과 별도 스레드에서 동작해 애니메이션과 전환 효과에서 JS보다 매끄럽고 효율적임
- 글쓴이는 CSS를 단순한 실용 도구를 넘어 표현과 예술의 수단으로 강조하며, 웹 개발자들이 현대 CSS의 잠재력을 더 활용하길 권장함
서론: 웹의 복잡성, 그리고 새로운 시도
- 많은 웹사이트가 JavaScript 프레임워크의 과도한 사용으로 성능 저하와 복잡성을 겪음
- React 앱은 로딩에 몇 초가 걸리고, NextJS는 하이드레이션 오류를 발생시킴
- node_modules 폴더는 수 기가바이트의 용량을 차지함
- JavaScript 없이도 HTML과 CSS만으로 강력한 기능을 구현할 수 있음
- 전자상거래 사이트의 복잡한 장바구니나 대시보드 외에는 JavaScript가 필수적이지 않을 수 있음
- 이 글은 CSS의 최신 기능을 소개하며, 개발자들이 JavaScript에만 의존하지 않고도 다양한 가능성을 탐구하도록 유도함
CSS에 대한 오해와 인식
CSS는 정말 어렵고 불편한가?
- CSS에 대한 부정적 인식은 기본 학습 부족에서 비롯됨
- 많은 개발자가 CSS 기초를 건너뛰고 JavaScript나 TypeScript에 집중함
- CSS는 단순한 스타일링 도구가 아닌, 도메인 특화 언어로 강력한 기능 제공
- CSS는 플렉스박스(flexbox) 와 같은 도구로 복잡한 레이아웃을 쉽게 구현 가능
- 예:
display: flex와justify-content: center로 div 중앙 정렬이 간단함 - 브라우저 개발자 도구는 플렉스박스 속성을 시각적으로 조정할 수 있는 위젯 제공
- 예:
- 한 쪽(예: JS)만 깊게 파고 CSS를 소홀히 하면 당연히 부담이 커짐
CSS 작성의 고통, 그리고 변화
- 예전에는 CSS가 썩 편하지 않았기에 Sass, Tailwind와 같은 도구가 등장함
- 예:
.post > .buttons .like:hover처럼 긴 선택자 체인을 관리해야 함
- 예:
- 최근에는 품질 개선 기능(네스팅 등)이 추가되어 기본 CSS만으로도 쾌적하게 개발 가능해짐
- CSS 중첩(nesting) 은 관련 스타일을 한 곳에 모아 가독성을 높임
- 예:
.post { & > .buttons { .like { &:hover { ... } } } } - 부모-자식 관계가 명확해져 짧고 간단한 클래스명 사용 가능
- 예:
- CSS 중첩(nesting) 은 관련 스타일을 한 곳에 모아 가독성을 높임
- 상대 색상(relative colors) 은 색상 조정을 쉽게 함
hsl(from #123456 h s calc(l + 10))로 밝기 조정 가능color-mix()로 두 색상을 혼합하여 동적 색상 생성
- 미디어 쿼리 범위 문법은
(width <= 768px)처럼 직관적인 조건 설정 가능 - lh 단위는 줄 높이에 맞춘 스타일링을 지원
- scrollbar-gutter 속성은 스크롤바로 인한 레이아웃 이동 문제를 해결
- Baseline은 주요 브라우저에서 기능 호환성을 보장
- 신규 기능(newly available) 은 최신 브라우저에서 작동
- 널리 지원(widely available) 은 2.5년 전 브라우저까지 지원
- 예: CSS 중첩은 2023년 12월부터 모든 브라우저에서 지원됨
왜 CSS/HTML만으로 개발하는가?
- 일부 사용자는 JavaScript를 기본적으로 비활성화함(보안, 개인정보 보호 등 이유)
- 순수 CSS/HTML만으로 웹사이트를 제공하면, 이런 사용자도 사이트 이용 가능성 높음
- 개발 및 사용자 입장에서 CSS/HTML만 사용할 때 속도, 접근성, CPU/배터리 사용 면에서의 이점이 큼
- CSS 애니메이션은 컴포지터 스레드에서 실행되어 CPU 부담 감소
- JavaScript는 이벤트 루프를 통해 실행되며, 약간의 지연 발생 가능
- 접근성과 사용 편의성 향상
- 버튼 호버 효과, 토스트 애니메이션, 입력 검증 등은 CSS로 간단히 구현 가능
CSS의 실질적 예시와 주요 기능들
@starting-style로 자연스러운 시작 애니메이션 구현
- 이전에는 요소 등장 애니메이션 구현에 keyframes, JS 트리거 등 복잡한 구조 필요
- @starting-style 도입으로 시작 상태 지정이 간단해짐. 요소의 초기 상태 애니메이션(예: 페이드인)을 쉽게 구현
transition: opacity 1s; @starting-style { opacity: 0; }로 설정- 별도의
@keyframes나 JavaScript 없이도 동작
- 단순히 transition과 함께 초기 상태만 명시하면 애니메이션 자연 적용됨
- 예: 토스트 메시지의 투명도와 위치 전환을 부드럽게 처리
다크/라이트 모드 손쉬운 테마 설정
- color-scheme: light dark는 사용자 선호에 따라 테마 자동 전환
- light-dark(#000, #FFF) 함수는 밝은/어두운 모드에 맞는 색상 지정
- 라디오 버튼과 :has 선택자로 사용자 테마 선택 지원
- JavaScript 없이 CSS만으로 테마 전환 가능
- JavaScript로 테마 저장/로드를 선택적으로 추가 가능
라디오/체크박스와 :has, :checked 등으로 커스텀 UI 생성
- 탭, 아코디언, 토글 등 복잡한 인터랙션도 JavaScript 없이 구현 가능
- 라디오 버튼은 :checked와 :has로 커스텀 스타일링
- 예:
label:has(input:checked)로 선택된 버튼 스타일 지정 opacity: 0으로 입력 요소를 숨기되, 화면 판독기 접근성 유지
- 예:
- details 요소는 FAQ와 같은 아코디언 메뉴 구현에 적합
name속성으로 단일 열림 상태 제어 가능[open]상태에 따라 애니메이션 추가 가능
입력 검증과 상태 반영
- pattern, required 등 HTML 속성과 CSS 가상 클래스(:valid, :invalid, :user-valid 등) 조합으로 실시간 검증 및 시각적 피드백 제공
- 입력 필드에 대한 outline/border 스타일 변경 등 사용자 경험 향상
- HTML의 pattern 속성으로 입력 필드 유효성 검증
- 예:
\w{3,16}으로 3~16자의 알파벳/숫자/밑줄 허용
- 예:
- CSS의 :valid와 :invalid로 유효성에 따라 스타일링
- :user-valid와 :user-invalid는 사용자가 입력한 후에만 스타일 적용
- :has 선택자로 입력 상태에 따라 다른 요소 스타일링 가능
- 일부 경우(예: 복잡한 입력 조건)는 JS가 필요하지만, 대부분은 CSS/HTML로 충분
뷰포트 단위의 올바른 사용법
- vw/vh 단위는 모바일에서 주소(네비게이션) 바 등장/숨김에 따라 정확성 이슈 발생
- lvh/svh/dvh(largest/smallest/dynamic viewport height) 등 신형 뷰포트 단위 사용 권장
- lvh: 전체 화면용 (예: 전체 배경)
- svh: 항상 화면에 보여야 하는 버튼, 링크 등에 활용
- dvh: 스크롤 등 변화에 따라 유동적으로 크기 할당
- 키보드 오버레이는 interactive-widget 속성이나 VirtualKeyboard API로 처리
<meta name="viewport" content="width=device-width, interactive-widget=resizes-content">- Chromium 기반 브라우저에서는
navigator.virtualKeyboard.overlaysContent = true
CSS 위시리스트(아쉽거나 바라는 기능)
- 재사용 가능한 블록: 클래스 내 다른 클래스 적용 (예:
@apply border) - 결합된 미디어 쿼리 선택자:
@media와 클래스 선택자 결합 - nth-child 변수:
span { --nth: nth-child(); }로 동적 스타일링 - nth-letter 선택자: 특정 글자 스타일링 (예:
p::nth-letter(2)) - 단위 제거:
calc(100vw / 1px)로 단위 없는 값 생성 - image() 함수: 대체 색상과 이미지 조각 지원
- body 내 style 태그: 공식 표준 지원으로 FOUC 문제 완화
마무리: CSS, 그리고 웹의 예술성
- CSS는 단순한 도구가 아닌, 창의적 표현 수단
- AI 도구나 빌드 체인(린터, 최소화 도구)은 창의성을 제한할 수 있음
- CSS는 성능, 접근성, 예술적 표현을 동시에 충족
- 이 글은 약 49kB의 JavaScript 없는 HTML/CSS로 작성됨
- 모든 인터랙티브 위젯과 시각 요소는 수작업으로 구현
- 예: CSS 클릭 게임은 CSS의 프로그래밍 언어적 가능성 증명