목차14개 항목
출처와 참고
Rachel Andrew의 「CSS 그리드로 미지원 브라우저 지원하기」(2018.01)·「CSS 그리드 레이아웃을 지금 사용해도 정말 괜찮을까」(2017.11)와 Daniel Tonon의 「IE에서 CSS 그리드 사용하기」 시리즈(2018~2020, 웹액츄얼리 번역)를 바탕으로 재구성한 노트다. 지원 등급은 Yahoo의 「Graded Browser Support」와 Filament Group의 「Grade components, not browsers」(2013)를 바탕으로 더했다. 우아한 저하와의 비교, 기능 감지의 변천, 「특정 브라우저에서만 깨질 때」는 Front End Interview Handbook의 「CSS 질문」을 바탕으로 지금 기준으로 고쳐 보강했다.
점진적 향상이란
점진적 향상(Progressive Enhancement)은 모든 브라우저에 쓸 만한 기본 경험을 주고, 새 기능을 지원하는 브라우저에는 더 나은 경험을 얹는 방식이다. 출발점은 "지원"의 뜻을 정하는 것이다.
| "지원"의 뜻 | 결과 |
|---|---|
| 모든 브라우저에서 똑같이 보인다 | 새 기능은 가장 오래된 대상 브라우저가 지원할 때까지 못 쓴다 |
| 모든 브라우저에서 콘텐츠를 무리 없이 쓸 수 있다 | 새 기능을 지금 쓰고, 옛 브라우저에는 단순한 레이아웃을 준다 |
모든 브라우저에서 똑같아야 한다면 그 기능을 쓰지 않는다. 새 기능은 이전에 불가능했던 일을 하려고 쓰는 것이지, 옛 디자인을 똑같이 재현하려고 쓰는 것이 아니다.
반대 방향에서 출발하는 짝 개념이 우아한 저하(Graceful Degradation)다.
| 점진적 향상 | 우아한 저하 | |
|---|---|---|
| 출발점 | 모든 브라우저가 쓸 수 있는 기본 경험 | 최신 브라우저용 완성된 경험 |
| 방향 | 지원하는 브라우저에 기능을 얹는다 | 지원하지 않는 브라우저에서도 망가지지 않게 깎아 낸다 |
| 기능이 빠진 환경 | 처음부터 설계에 들어 있다 | 나중에 점검하는 예외로 남기 쉽다 |
결과가 비슷해 보여도 점진적 향상이 기본 경험을 먼저 확정하므로 빠뜨리는 환경이 적다. 두 방식 모두 출발점은 대상 브라우저와 기능별 지원 현황(Can I use, Baseline)을 확인하는 일이다.
CSS 그리드·플렉스박스는 이제 모든 주요 브라우저가 지원한다. 같은 원칙이 지금은 지원 시기가 엇갈린 새 기능에 그대로 적용된다. Baseline 연도는 Chrome·Edge·Firefox·Safari가 모두 지원하게 된 해다(Newly available). 그로부터 30개월이 지나면 Widely available이 된다.
| 기능 | Baseline |
|---|---|
캐스케이드 레이어 @layer | 2022 |
컨테이너 크기 쿼리 @container, 서브그리드, :has(), 네이티브 중첩, oklch(), color-mix() | 2023 |
상대 색상 문법(oklch(from …)), light-dark(), font-size-adjust, @property, @starting-style·transition-behavior, popover 속성, 블록 레이아웃의 align-content, round() | 2024 |
같은 문서 뷰 트랜지션(document.startViewTransition(), View Transitions), @scope, abs()·sign() | 2025 |
앵커 위치 지정(팝오버와 앵커 위치 지정), shape(), text-box-trim | 2026 |
text-wrap: pretty, 그리드 레인(display: grid-lanes, 메이슨리) | 아직 아님 (2026년 10월 기준 pretty는 Firefox 미지원, 그리드 레인은 Safari 26.4만 정식 지원) |
최신 상태는 web.dev Baseline과 Can I use에서 확인한다.
지원 대상 정하기
- 추측하지 말고 실제 방문자 분석 데이터를 본다. 모바일에서 못 쓰는 사이트라면 모바일 방문이 적게 잡혀 데이터가 왜곡된다.
- 데이터가 없으면 Can I Use의 지역별 사용 통계나 Baseline(웹 플랫폼 기능이 모든 주요 브라우저에서 쓸 수 있는지 표시하는 기준)을 참고한다.
- 사이트의 대상 지역을 잊지 않는다. 저사양 기기와 데이터 절약형 브라우저가 많은 시장에서는 새 기능 지원이 늦다.
지원 등급: 브라우저가 아니라 컴포넌트에 매긴다
지원 범위를 문서로 정하는 고전적인 틀은 Yahoo의 등급별 브라우저 지원(Graded Browser Support) 이다. 「지원」을 똑같은 경험이 아니라 등급으로 나눴다.
| 등급 | 받는 것 | QA |
|---|---|---|
| A | 전체 경험(스타일·스크립트·고급 기능) | 모두 테스트하고 버그를 고친다 |
| C | 시맨틱 HTML만으로 된 핵심 콘텐츠와 기능 | 대표 브라우저 한두 개, 또는 CSS·JS를 끈 최신 브라우저로 테스트 |
| X | 알 수 없는·드문 브라우저. 유능하다고 가정하고 A와 같은 것을 준다 | 테스트하지 않는다 |
C 등급은 블랙리스트, A 등급은 화이트리스트로 브라우저를 미리 분류했다. 막 나온 A 등급 브라우저의 새 버전은 아직 테스트 전이라 X 등급이다.
브라우저 단위 등급에는 한계가 있다. 지금 방문자 대부분은 A 등급이고, 한 브라우저가 어떤 기능은 지원하고 어떤 기능은 지원하지 않는다. 지원 범위는 사다리가 아니라 산점도다. 그래서 컴포넌트마다 등급을 매긴다.
- 컴포넌트마다 기본 경험과 향상된 경험(필요하면 중간 단계)을 정한다. 예: 데이터 시각화는 기본이 HTML 표, 향상이 Canvas 차트. 내비게이션은 기본이 페이지 이동 링크, 향상이
fetch+history.pushState로 부분 갱신. - 어느 단계를 줄지는 브라우저 이름이 아니라 그 컴포넌트가 쓰는 기능의 지원 여부(
@supports,'x' in window)로 정한다. - 과거에는 페이지 전체를 두 등급으로 가르는 컷 더 머스터드(Cut the Mustard) 검사를 많이 썼다.
'querySelector' in document && 'addEventListener' in window처럼 몇 가지 기능이 있으면 향상 스크립트를 싣고 없으면 HTML만 준다. 지금은<script type="module">을 이해하는 브라우저에만 최신 번들을 싣는 것이 같은 역할을 한다. - UA로 브라우저를 판별하는 것은 기능 감지가 불가능한 마지막 경우에만 쓴다.
CSS가 이미 가진 두 가지 장치
1. 모르는 CSS는 무시된다
브라우저는 이해하지 못하는 속성과 값을 건너뛴다. 그래서 옛 방식으로 먼저 쓰고 그 아래에 새 방식을 쓰면, 옛 브라우저는 앞부분만, 새 브라우저는 둘 다 읽는다. 같은 선언 안에서도 통한다.
.card {
background: #3a7; /* 폴백 */
background: oklch(65% 0.15 160); /* 지원하면 이 값이 이긴다 */
}2. 새 레이아웃은 옛 레이아웃을 안다
명세에 "그리드·플렉스 아이템이 되면 무엇이 무효가 되는지"가 정의돼 있다. 대부분의 폴백이 자동으로 꺼진다.
| 폴백으로 쓴 것 | 부모가 display: grid가 되면 |
|---|---|
float, clear | 무시된다 |
display: inline-block | 아이템에 효과가 없다 |
display: table-cell | 그리드 아이템이 되어 테이블처럼 동작하지 않는다 |
vertical-align | 무시된다. 대신 박스 정렬(align-self 등)을 쓴다 |
flex, flex-grow 등 | 무시된다 |
다단 column-count, column-width | 아이템 자신의 다단은 그대로 남는다. 다단 컨테이너 자체를 display: grid로 바꿀 때 무시된다 |
피처 쿼리로 틈새 메우기
자동으로 꺼지지 않는 값도 있다. 대표적인 것이 아이템에 준 너비다. float 폴백에서 width: 33%를 줬다면, 그리드에서는 이 33%가 컨테이너가 아니라 그리드 영역 기준이 되어 아이템이 셀의 3분의 1만 차지한다.
피처 쿼리(@supports)는 미디어 쿼리처럼 동작하되, 화면 크기 대신 브라우저가 특정 CSS를 지원하는지 묻는다.
/* 1. 폴백: 모든 브라우저가 읽는다 */
.item { float: left; width: 33.333%; }
/* 2. 새 레이아웃 */
.wrapper { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1rem; }
/* 3. 틈새로 새는 폴백 값만 되돌린다 */
@supports (display: grid) {
.item { width: auto; }
}
/* 선택자 지원 여부도 물을 수 있다 */
@supports selector(:has(> img)) {
.card:has(> img) { grid-template-rows: auto 1fr; }
}피처 쿼리 안에는 새 코드 전체가 아니라 "되돌리거나 덧붙일 값"만 넣는다. @supports not (…)으로 미지원 브라우저 전용 규칙을 쓸 수도 있다. 폴리필도 핵도 아닌, 명세에 정의된 CSS만으로 처리하는 방법이다.
JavaScript에서는 같은 질문을 CSS.supports('display', 'grid')나 CSS.supports('selector(:has(a))')로 한다. 과거에는 Modernizr 같은 기능 감지 라이브러리가 페이지 로드 때 기능을 하나씩 시험해 <html class="flexbox no-cssgrid">처럼 클래스를 붙이고, CSS는 그 클래스로 분기했다. 지금은 @supports와 CSS.supports()로 충분하다.
무거운 폴리필을 피하는 이유
- 레이아웃 전체를 계산하는 기능을 자바스크립트로 흉내 내면 높이·위치를 다시 계산하느라 로딩이 불안정해진다.
- 미지원 브라우저는 대개 오래되거나 느린 기기다. 가장 약한 기기에 가장 무거운 스크립트를 얹는 셈이다.
- 줄어들 사용자층 때문에 개발·테스트 시간이 크게 는다.
동작 범위가 좁고 가벼운 폴리필은 예외가 될 수 있다.
변환 도구의 한계
PostCSS·Autoprefixer·Lightning CSS 같은 도구는 접두사를 붙이거나 새 문법을 옛 문법으로 바꿔 준다(예: 네이티브 중첩 → 펼친 선택자, 논리 속성 → 물리 속성). 도구는 문법을 옮길 뿐 동작까지 옮기지는 못한다. 대응 문법이 없는 기능은 조용히 깨지므로 경고를 읽고 결과를 실제 브라우저에서 확인한다.
특정 브라우저에서만 깨질 때
어떤 브라우저의 어떤 버전에서 깨지는지 먼저 좁힌 뒤, 아래 순서로 손댄다. 브라우저를 판별하지 않고 기능과 값을 다룬다.
| 순서 | 방법 | 내용 |
|---|---|---|
| 1 | 기본 스타일 맞추기 | 리셋이나 노멀라이즈로 브라우저 기본값 차이를 없애고, 남는 차이는 값을 명시한다(리셋과 노멀라이즈) |
| 2 | 접두사·문법 변환 자동화 | Autoprefixer·postcss-preset-env(또는 Lightning CSS)가 browserslist에 적은 대상에 맞춰 공급자 접두사를 붙이고 새 문법을 옮긴다(PostCSS) |
| 3 | 피처 쿼리로 분기 | 지원 여부에 따라 폴백 값을 되돌리거나 덧붙인다(위 「피처 쿼리로 틈새 메우기」) |
| 4 | 검증된 라이브러리에 맡기기 | 폼 요소·대화 상자처럼 브라우저 차이가 큰 부분은 이미 차이를 흡수한 컴포넌트 라이브러리를 쓴다 |
| 5 | 버그 우회 | 특정 엔진의 버그면 우회 코드에 버그 링크와 지울 조건을 주석으로 남긴다. 고쳐지면 지운다 |
과거에는 IE 조건부 주석(<!--[if IE 8]>…<![endif]-->)이나 서버의 User-Agent 판별로 브라우저 전용 스타일시트를 따로 불렀다. User-Agent 문자열은 흉내 내기 쉽고 버전이 바뀌면 틀리므로 지금은 쓰지 않는다.
폴백 테스트
- 확실한 방법은 기능을 지원하지 않는 실제 브라우저로 보는 것이다. 구버전 브라우저(자동 업데이트를 끈 설치본)나 BrowserStack 같은 원격 테스트 서비스를 쓴다.
@supports (display: gridx)처럼 일부러 틀린 값으로 미지원 상태를 흉내 내지 않는다. 피처 쿼리 밖의 새 코드는 여전히 적용돼 거짓 양성이 나기 쉽다.- 테스트 대상은 "지원 / 미지원" 두 묶음이면 충분하다.
도입을 설득하는 근거
| 근거 | 내용 |
|---|---|
| 개발 시간 | 새 기능이 복잡도를 줄여 지금과 이후 유지보수 시간을 아낀다 |
| 디자인 | 새 기능 없이는 견고하게 만들 수 없는 디자인이다 |
| 성능 | 무거운 레이아웃 프레임워크나 스크립트를 걷어낼 수 있다 |
| 지원 추세 | 에버그린 브라우저는 자동 업데이트되어 미지원 비율이 빠르게 준다 |
역사
과거에는 IE10·11이 그리드 초기 명세를 -ms-grid 접두사로만 지원했다. 자동 배치·gap·auto-fill이 없어 아이템을 하나씩 배치하고 간격을 빈 트랙으로 흉내 냈으며, Autoprefixer의 그리드 변환 옵션으로 grid-template-areas를 옮기기도 했다. IE는 2022년 지원이 끝나 이런 우회법은 필요 없다. 피처 쿼리도 IE만 지원하지 않았다.
정리
- "지원"은 똑같이 보이는 것이 아니라 쓸 수 있는 것이다.
- 폴백을 먼저 쓰고 새 기능을 아래에 쓴다. 모르는 CSS는 무시되고, 새 레이아웃은 옛 레이아웃을 덮어쓴다.
- 새어 나오는 값만
@supports안에서 되돌린다. 선택자 지원은@supports selector()로 묻는다. - 무거운 폴리필 대신 단순한 경험을 준다. 변환 도구 결과는 실제 브라우저로 확인한다.
관련 노트: CSS 그리드 레이아웃, Float와 Flexbox 레이아웃, CSS 커스텀 속성으로 색상 체계 짜기, 반응형 디자인과 다국어 타이포그래피, PostCSS와 CSS 변환 도구, CSS Houdini: 렌더링 엔진에 끼어드는 API
원본 기록12
- 원문 (새 창) webactually.com/2018/01/19/css-그리드로-미지원-브라우저-지원하기/
- 원문 (새 창) webactually.com/2017/11/30/css-그리드-레이아웃을-지금-사용해도-정말-괜찮을까요/
- 원문 (새 창) webactually.com/2020/01/29/ie에서의-css-그리드-사용하기-일반적인-ie-그리드-오해를/
- 원문 (새 창) webactually.com/2018/10/02/ie에서-css-그리드-사용하기-css-그리드와-autoprefixer/
- 원문 (새 창) webactually.com/2018/11/13/ie에서-css-그리드-사용하기-간격으로-자동-배치/
- 원문 (새 창) webactually.com/2020/07/27/ie에서-css-그리드-사용하기-중복된-그리드-영역-이름/
- 원문 (새 창) web.dev/baseline
- 원문 (새 창) web.dev/blog/same-document-view-transitions-are-now-baseline-newly-available
- 원문 (새 창) developer.mozilla.org/en-US/docs/Web/CSS/anchor-name
- GitHub 원문 (새 창) github.com/yui/yui3/wiki/Graded-Browser-Support
- 원문 (새 창) www.filamentgroup.com/lab/grade-the-components.html
- 원문 (새 창) www.frontendinterviewhandbook.com/css-questions