- Published on
웹 표준 & CSS 2026 — Container Queries / View Transitions / Popover / Anchor Positioning / Scroll-driven Animations 심층 가이드
- Authors

- Name
- Youngju Kim
- @fjvbn20031
1장 · 2026년 웹 플랫폼 — 마침내 도착한 표준들
10년 전, 우리는 "곧 표준이 될 것"이라고 말하며 폴리필을 깔았다. 2026년, 우리는 표준이 곧 일상이 된 시대에 산다.
지금 이 순간, Chrome 130+, Safari 18+, Firefox 130+가 모두 다음을 안정 지원한다.
- Container Queries — 컴포넌트 시대의 미디어 쿼리
- View Transitions API — 단일 페이지 버전(2023) + 크로스-도큐먼트(2024)
- Popover API — 네이티브 모달 (2024년 전 브라우저 안정화)
- Anchor Positioning — Chrome 125(2024.4), Safari/Firefox 2025
- Scroll-driven Animations — Chrome 115(2023.7), Safari/Firefox 2025
- CSS Nesting — 2023년 안정화
- :has() 선택자 — 보편 지원
- color-mix() / light-dark() — 보편 지원
- @scope / @layer — Chrome/Safari/Firefox 모두 지원
- Subgrid — Chrome 117, Safari 16, Firefox 71 (보편 지원)
- Speculation Rules API — 미래 페이지 prerender
- WebGPU / WebTransport — 안정화
"오늘 새 프로젝트를 시작한다면 무엇을 써야 할까?"에 대한 답이 마침내 단순해졌다. 표준을 그대로 쓰면 된다. 이 글은 그 새로운 기본기를 한 장씩 짚는다.
이 글의 코드는 한 줄도 폴리필이 필요하지 않다. 2026년 evergreen 브라우저의 최신 안정 버전을 기준으로 작성했다.
2장 · Container Queries — 컴포넌트 시대의 미디어 쿼리
왜 미디어 쿼리는 부족한가
미디어 쿼리는 뷰포트 기준이다. 그러나 컴포넌트는 사이드바, 모달, 카드 그리드, 사이드패널 안에서 살아간다. 같은 카드 컴포넌트가 사이드바에 들어가면 좁아지고, 메인 영역에 들어가면 넓어진다. 뷰포트 폭은 똑같다. 컨테이너 폭만 다르다.
.card-container {
container-type: inline-size;
container-name: card;
}
@container card (min-width: 400px) {
.card {
display: grid;
grid-template-columns: 1fr 2fr;
gap: 1.5rem;
}
}
@container card (max-width: 399px) {
.card {
display: flex;
flex-direction: column;
}
}
container-type 세 가지
| 값 | 의미 |
|---|---|
inline-size | 가로 폭만 쿼리 가능 (가장 흔함) |
size | 가로/세로 모두 쿼리 가능 (성능 비용 큼) |
normal | 컨테이너 아님 (기본값) |
size는 자식의 높이가 부모에 영향을 줄 수 없도록 차단해야 해서 비용이 크다. 99%의 경우 inline-size로 충분하다.
Container Query Units
.hero-title {
font-size: clamp(1.5rem, 5cqi, 3rem);
}
cqi(container query inline-size), cqb(block-size), cqw, cqh, cqmin, cqmax. 뷰포트 단위 vw/vh의 컨테이너 버전이다.
실전 패턴
.product-grid {
container-type: inline-size;
display: grid;
grid-template-columns: repeat(auto-fill, minmax(min(280px, 100%), 1fr));
gap: 1rem;
}
@container (min-width: 900px) {
.product-card .image {
aspect-ratio: 4 / 3;
}
}
@container (max-width: 600px) {
.product-card .price {
font-size: 0.875rem;
}
}
같은 카드가 모달, 사이드바, 메인에 들어가도 자기 컨테이너 폭에 맞춰 자동 적응한다. 컴포넌트가 진짜 컴포넌트가 된다.
3장 · View Transitions API — 단일 페이지 → 크로스-도큐먼트 (2024)
Same-document 버전 (2023)
상태가 바뀔 때 자동으로 부드러운 전환을 만들어준다.
function updateList(newItems) {
if (!document.startViewTransition) {
renderList(newItems)
return
}
document.startViewTransition(() => renderList(newItems))
}
::view-transition-old(root) {
animation: fade-out 200ms ease-out;
}
::view-transition-new(root) {
animation: fade-in 200ms ease-in;
}
@keyframes fade-out { to { opacity: 0; } }
@keyframes fade-in { from { opacity: 0; } }
명명된 트랜지션
특정 엘리먼트만 별도 전환:
.product-card .image {
view-transition-name: product-image;
}
::view-transition-old(product-image),
::view-transition-new(product-image) {
animation-duration: 400ms;
}
상품 카드를 클릭해서 상세 페이지로 갈 때 이미지가 그대로 확대되는 네이티브 모바일 앱 같은 전환이 가능하다.
Cross-document 버전 (2024)
진짜 혁명은 여기다. MPA(Multi-Page App)에서도 페이지 전환을 매끄럽게 만들 수 있다.
@view-transition {
navigation: auto;
}
.hero-image {
view-transition-name: hero;
}
이전 페이지의 .hero-image와 새 페이지의 .hero-image가 같은 이름을 공유하면, 브라우저가 자동으로 두 엘리먼트 사이를 전환한다. SPA 라우터 없이도, Next.js의 <Link> 없이도. 그냥 <a href> 클릭만으로.
MPA 트랜지션의 의미
지난 10년간 우리가 SPA를 쓴 가장 큰 이유 중 하나가 "페이지 전환을 부드럽게 하고 싶다"였다. View Transitions API의 cross-document 버전은 그 이유를 사라지게 한다. Next.js, Astro, SvelteKit 모두 자동으로 활용한다.
주의점
- 트랜지션 중에는 사용자 입력이 잠깐 막힐 수 있다 → 짧게(200~300ms)
prefers-reduced-motion: reduce사용자를 위해 차단 옵션 제공view-transition-name은 페이지에서 유일해야 한다
4장 · Popover API (2024) — 네이티브 모달
왜 우리는 모달에서 매번 실패했나
- 포커스 트랩
- ESC로 닫기
- 외부 클릭으로 닫기
- 백드롭(backdrop)
- z-index 지옥
- 접근성 (role, aria, focus management)
이 모든 것을 브라우저가 해준다. 2024년부터.
<button popovertarget="my-popover">Open</button>
<div id="my-popover" popover>
<h2>Hello</h2>
<button popovertarget="my-popover" popovertargetaction="hide">Close</button>
</div>
이것만으로:
- ESC로 닫힘
- 외부 클릭으로 닫힘 (auto 모드)
- 포커스 자동 이동
- 항상 top layer에 렌더 (z-index 무관)
popover 두 가지 모드
| 값 | 동작 |
|---|---|
auto (기본) | ESC, 외부 클릭, 다른 popover 열면 닫힘 |
manual | 명시적으로만 닫힘 (토스트, 알림 등) |
백드롭 스타일링
[popover]::backdrop {
background: oklch(0% 0 0 / 0.6);
backdrop-filter: blur(8px);
}
Dialog와의 차이
<dialog>는 폼 통합과 modal/non-modal 구분이 있다. Popover는 더 가볍고 임의 엘리먼트에 적용 가능. 일반적으로:
- 풀 모달(폼 제출 등) →
<dialog> - 메뉴, 툴팁, 카드 hover → popover
5장 · Anchor Positioning (Chrome 125, 2024.4) — 툴팁/팝오버 배치
그 옛날의 악몽
툴팁 라이브러리 하나 쓰려면 Floating UI(이전 Popper.js)를 깔고, viewport 충돌 감지하고, 스크롤 이벤트 듣고, ResizeObserver 걸고… 진짜 미친 짓이었다.
이제는:
<button id="trigger" style="anchor-name: --my-button">Hover me</button>
<div popover id="tooltip">
Tooltip content
</div>
<style>
#tooltip {
position-anchor: --my-button;
top: anchor(bottom);
left: anchor(center);
translate: -50% 0;
}
</style>
브라우저가 자동으로 트리거 엘리먼트의 위치를 추적한다. 스크롤하든 리사이즈하든 따라온다.
position-try-fallbacks — 자동 viewport 충돌 회피
#tooltip {
position-anchor: --my-button;
position-area: bottom;
position-try-fallbacks: top, right, left;
}
기본은 아래 표시, 공간이 부족하면 위 → 오른쪽 → 왼쪽 순으로 자동 시도. Floating UI 한 줄 없이.
position-area — 9분면 단축
#tooltip {
position-area: top span-all;
}
top, bottom, left, right, center, span-all, start, end 등으로 표현. 9분면 그리드를 머릿속에 두면 직관적이다.
안 되는 것
- 한 엘리먼트가 여러 앵커를 동시에 참조 (CSS Anchor Positioning Level 2에서 검토 중)
position: fixed나absolute가 아니면 동작 안 함
Floating UI의 운명
여전히 유효하다 — 복잡한 충돌 감지, 화살표 자동 위치 같은 고급 기능은 아직 라이브러리가 낫다. 단, 80%의 단순 툴팁/팝오버는 이제 CSS만으로 충분하다.
6장 · Scroll-driven Animations (Chrome 115) — JS 없는 스크롤 효과
두 가지 스크롤 타임라인
| 타임라인 | 의미 |
|---|---|
scroll() | 스크롤 컨테이너의 전체 스크롤 진행도 |
view() | 특정 엘리먼트가 뷰포트를 가로지르는 진행도 |
scroll() — 진행 인디케이터
@keyframes grow-progress {
from { transform: scaleX(0); }
to { transform: scaleX(1); }
}
.progress-bar {
position: fixed;
top: 0;
left: 0;
right: 0;
height: 4px;
background: oklch(70% 0.2 250);
transform-origin: left;
animation: grow-progress linear;
animation-timeline: scroll();
}
스크롤하면 자동으로 차오른다. JavaScript 한 줄도 없다.
view() — 뷰포트 진입 페이드인
@keyframes fade-in {
from { opacity: 0; transform: translateY(40px); }
to { opacity: 1; transform: translateY(0); }
}
.card {
animation: fade-in linear;
animation-timeline: view();
animation-range: entry 0% cover 40%;
}
엘리먼트가 뷰포트 하단에 진입할 때 시작해서, 40% 보이면 끝난다. Intersection Observer 코드 한 줄 없이.
prefers-reduced-motion 대응
@media (prefers-reduced-motion: no-preference) {
.card {
animation: fade-in linear;
animation-timeline: view();
}
}
접근성을 잊지 말자.
성능
스크롤-드리븐 애니메이션은 컴포지터 스레드에서 실행된다. JavaScript scroll 이벤트와 달리 메인 스레드를 멈추지 않는다. 60fps가 기본이고 120fps도 가능하다.
7장 · CSS Nesting (2023) — Sass 없이 중첩
표준 문법
.card {
padding: 1rem;
border-radius: 0.5rem;
& .title {
font-size: 1.5rem;
font-weight: 600;
}
& .description {
color: oklch(50% 0 0);
}
&:hover {
transform: translateY(-2px);
}
@media (min-width: 768px) {
padding: 1.5rem;
}
}
Sass와의 차이는 미미하다. &가 더 자주 필요할 뿐(2023년 초기엔 의무였다가 완화됨).
Sass와의 차이점
- 변수는 표준이 아님 → CSS Custom Properties(
--var)를 쓴다 - mixin은 아직 검토 중
- **
@extend**는 표준화 가능성 낮음
마이그레이션
/* Before (Sass) */
.btn {
&.primary { background: blue; }
&.danger { background: red; }
}
/* After (native CSS nesting) */
.btn {
&.primary { background: oklch(60% 0.2 250); }
&.danger { background: oklch(60% 0.25 25); }
}
거의 그대로 동작한다.
8장 · :has() — 부모 선택자
"CSS의 부모 선택자가 없는 이유"는 끝났다
/* 카드에 이미지가 있으면 다른 레이아웃 */
.card:has(img) {
display: grid;
grid-template-columns: 1fr 2fr;
}
/* 폼에 invalid 입력이 있으면 제출 버튼 비활성 스타일 */
form:has(input:invalid) button[type="submit"] {
opacity: 0.5;
pointer-events: none;
}
/* 다크 모드를 선호하지 않고, html에 light 클래스가 없으면 다크 */
html:not(.light) {
color-scheme: dark;
}
실전 패턴
1) 부모-자식 동시 조건
.dropdown:has(:focus-visible) {
outline: 2px solid currentColor;
}
2) 형제 기반 스타일링
label:has(+ input:required)::after {
content: ' *';
color: oklch(60% 0.25 25);
}
3) 빈 상태 처리
.list:not(:has(.list-item)) {
display: none;
}
성능
:has()는 brute force가 아니라 invalidation 추적이 있다. 매우 큰 DOM에서도 실용적이다.
9장 · color-mix() / light-dark() — 색상 연산
color-mix() — 두 색을 섞다
.btn {
background: color-mix(in oklch, blue, white 20%);
}
.btn:hover {
background: color-mix(in oklch, blue, white 30%);
}
in oklch/in lab/in srgb/in hsl 등 색 공간을 명시. 일반적으로 oklch가 가장 자연스럽다(인간 지각에 가까운 균등 공간).
디자인 토큰과 결합
:root {
--brand: oklch(60% 0.2 250);
}
.btn {
background: var(--brand);
}
.btn:hover {
background: color-mix(in oklch, var(--brand), white 15%);
}
.btn:active {
background: color-mix(in oklch, var(--brand), black 15%);
}
색 변형을 일일이 정의할 필요 없이 하나의 brand로부터 파생.
light-dark() — 다크 모드 한 줄
:root {
color-scheme: light dark;
--bg: light-dark(white, oklch(15% 0 0));
--fg: light-dark(oklch(15% 0 0), white);
}
body {
background: var(--bg);
color: var(--fg);
}
prefers-color-scheme 미디어 쿼리를 두 번 쓸 필요 없이 한 줄. 단, color-scheme: light dark를 반드시 선언해야 동작한다.
OKLCH가 표준이 되는 이유
#hex나 rgb()는 RGB 색 공간이라 인간 지각과 일치하지 않는다. oklch(60% 0.2 250)은:
- L = 명도 (0~100%)
- C = 채도 (0~0.4)
- H = 색상 (0~360)
색상끼리 보간이 자연스럽고, 명도 변화가 직관적이다. 2026년의 디자인 시스템은 OKLCH가 사실상 표준이다.
10장 · @scope / @layer — 캡슐화와 캐스케이드
@scope — CSS의 진짜 스코프
@scope (.card) to (.card-content) {
h2 {
font-size: 1.25rem;
}
}
.card 안쪽이지만 .card-content까지는 적용 안 됨. lower boundary가 있는 진짜 스코프.
@scope (.dark-section) {
a {
color: white;
}
}
.dark-section 안의 <a>만 흰색.
@layer — 캐스케이드 레이어
@layer reset, base, components, utilities;
@layer reset {
* { margin: 0; padding: 0; }
}
@layer base {
body { font-family: system-ui; }
}
@layer components {
.btn { padding: 0.5rem 1rem; }
}
@layer utilities {
.text-center { text-align: center; }
}
레이어 순서가 늦을수록 우선. specificity와 무관하게 작동.
why 중요한가: Tailwind/UnoCSS의 utility-first는 specificity 폭주를 일으켰다. @layer utilities로 묶으면 항상 마지막 → utility가 specificity 싸움 없이 항상 이긴다.
Cascade Layers + Tailwind 4
Tailwind 4는 내부적으로 @layer를 사용한다. 우리 CSS는 다른 레이어에 두면 우선순위가 깔끔하게 정리된다.
11장 · Subgrid — 마침내 보편 지원
문제 정의
<ul class="cards">
<li class="card">
<h2>Short title</h2>
<p>Description</p>
<button>Buy</button>
</li>
<li class="card">
<h2>A much longer title that wraps to two lines</h2>
<p>Description</p>
<button>Buy</button>
</li>
</ul>
카드 안의 제목/설명/버튼이 카드끼리 가로로 정렬되길 원한다. 부모 grid의 그리드 라인을 자식이 상속받아야 한다.
Subgrid 해결
.cards {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 1rem;
}
.card {
display: grid;
grid-template-rows: subgrid;
grid-row: span 3;
}
grid-template-rows: subgrid로 부모의 행 구조를 상속. 제목들이 자동으로 같은 높이에 정렬된다.
Subgrid가 해결한 것들
- 카드 그리드의 제목/이미지/버튼 정렬
- 폼 라벨/입력 정렬
- 표 같은 컴포넌트의 칸 정렬
- 디자인 시스템의 일관된 spacing
12장 · Speculation Rules — 미래 페이지 prerender
무엇인가
사용자가 클릭할 것 같은 링크를 미리 렌더링한다. prefetch보다 강력하다 — DOM, JavaScript 실행까지 모두.
<script type="speculationrules">
{
"prerender": [
{
"where": { "href_matches": "/articles/*" },
"eagerness": "moderate"
}
]
}
</script>
/articles/로 시작하는 모든 링크에 대해, 사용자가 hover/touch start 같은 신호를 보이면 미리 페이지를 렌더링.
eagerness 단계
| 값 | 의미 |
|---|---|
immediate | 즉시 (조심해서 써야 함) |
eager | viewport에 보이면 |
moderate | hover 200ms 또는 mousedown |
conservative | mousedown만 |
효과
next-page LCP가 수 밀리초로 떨어진다. 사용자 입장에서는 "클릭과 동시에 다음 페이지가 이미 거기 있다."
Next.js와의 관계
Next.js App Router는 자동으로 prefetch한다(코드/데이터). Speculation Rules의 prerender는 DOM까지 렌더링하는 것이라 더 강력하다. Next.js 15+에서는 옵트인 가능.
13장 · WebGPU / WebTransport — 안정화
WebGPU
- Chrome 113(2023.5), Safari 18, Firefox 121+에서 안정 지원
- 셰이더 언어: WGSL
- 머신러닝 (transformers.js, MediaPipe, ONNX Runtime Web), 고급 그래픽, GPU 컴퓨트
- WebGL과 달리 컴퓨트 셰이더와 modern GPU 기능 노출
브라우저에서 LLM 추론(WebLLM), 이미지 처리, 시뮬레이션을 GPU 가속으로 돌릴 수 있다. ChatGPT를 브라우저 안에서 로컬로 돌리는 시대가 진짜로 왔다.
WebTransport
- HTTP/3 기반 양방향 통신
- WebSocket의 후계자 (UDP 기반의 신뢰성 옵션)
- 다중 스트림, head-of-line blocking 없음
- 실시간 게이밍, WebRTC 데이터 채널 대안
const transport = new WebTransport('https://example.com/wt')
await transport.ready
const stream = await transport.createBidirectionalStream()
const writer = stream.writable.getWriter()
await writer.write(new TextEncoder().encode('hello'))
그 외 안정화된 것들
- Custom Highlight API — 브라우저 selection 외에 사용자 정의 하이라이트
- content-visibility: auto — 화면 밖 콘텐츠 렌더링 비용 절감
- Performance.measureUserAgentSpecificMemory — 정확한 메모리 측정
- Storage Access API, CHIPS — 3rd-party 쿠키 시대 대응
14장 · 한국 / 일본 웹 표준 컨텐츠 — 네이버 D2, html5.jp, mizchi
한국
- 네이버 D2 (d2.naver.com) — 웹 표준, 브라우저 내부, 성능 최적화 글이 꾸준히 올라온다. 2024~2025년 View Transitions, Container Queries 관련 분석 글들이 좋다.
- TOAST UI 블로그 — 표준 + 자체 라이브러리 구현 노하우
- Frontender 카카오톡 오픈채팅 / Frontier 컨퍼런스 — 한국어로 표준 따라잡기 좋은 커뮤니티
- MDN 한국어 번역 — 여전히 일부지만, 새 기능들의 한글화가 이전보다 빨라졌다
일본
- html5.jp — 오래된 사이트지만 사양 번역이 가장 빠르고 정확
- mizchi 블로그 — 프런트엔드 트렌드/사양 동향 분석. 비판적 시각이 강해서 표준의 한계를 보여준다
- Web Developer Conference (Tokyo) — 매년 표준 관련 발표 풍부
- CodeGrid (Pixel Grid) — 유료지만 깊이 있는 CSS 표준 해설
- MDN 일본어 — 영어판과 거의 동시 업데이트
영어권
- web.dev — Google 공식, 새 기능 가이드의 정전
- CSS Tricks — 여전히 좋다 (2025년부터 새 글 페이스가 줄긴 했지만)
- Smashing Magazine — 깊이 있는 글 다수
- State of CSS / State of JS — 매년 트렌드 조사
- Una Kravets, Adam Argyle, Bramus의 블로그 — Chrome DevRel의 1차 정보원
일본 표준 활동의 특이점
W3C 일본 노드 활동이 매우 활발하다. 한국과 달리 일본은 사양 번역 문화가 강하고, 사양에 대해 한 문장 한 문장 곱씹는 글이 많다. 표준의 "왜"를 알고 싶다면 html5.jp의 글을 찾아 읽는 것을 권한다.
15장 · 마이그레이션 전략 — 어디부터 도입할까
우선순위
1티어 — 지금 당장 도입 가능 (보편 지원)
- Container Queries
- CSS Nesting
:has()color-mix(),light-dark()@layer- Subgrid
- Popover API
- View Transitions (same-document)
2티어 — 점진 도입 (대부분 지원, 그레이스풀 폴백 권장)
- View Transitions (cross-document)
- Anchor Positioning
- Scroll-driven Animations
@scope
3티어 — 옵트인 (특정 시나리오)
- Speculation Rules API
- WebGPU (ML/그래픽)
- WebTransport (실시간)
점진적 향상의 전형
.tooltip {
/* fallback: 기본 absolute positioning */
position: absolute;
top: 100%;
left: 50%;
transform: translateX(-50%);
}
@supports (position-anchor: --x) {
.tooltip {
position-anchor: --trigger;
top: anchor(bottom);
left: anchor(center);
transform: translateX(-50%);
}
}
@supports로 분기. 새 기능이 있으면 강화, 없으면 기존 동작.
디자인 시스템 마이그레이션 체크리스트
- OKLCH 색상 마이그레이션 — 디자인 토큰부터
color-mix(in oklch, ...)기반으로 - 모달 라이브러리 → Popover API — 폼이 들어가면 dialog, 아니면 popover
- Floating UI → Anchor Positioning — 단순 툴팁/팝오버부터 이전
- Intersection Observer → Scroll-driven Animations — fade-in류부터
- Tailwind/Sass 변수 →
@layer정리 — 우선순위 충돌 끝 - 반응형 컴포넌트 → Container Queries — 미디어 쿼리를 컨테이너 쿼리로
- SPA 라우터 트랜지션 → View Transitions (cross-document) — 점진 도입
흔한 함정
view-transition-name은 페이지 내 유일해야 함 → 동적 리스트면 ID 기반- Anchor Positioning은
position: absolute/fixed만 동작 - Scroll-driven Animations에
prefers-reduced-motion분기 필수 - Popover의
popovertarget은 ID 참조 → React에서 동적 ID 신중히 - Container Queries는
container-type이 layout containment를 강제 → 일부 레이아웃 깨짐 가능
결론 — 2026년의 기본기
이 글의 모든 기능은 2026년 evergreen 브라우저의 기본기다. "고급 CSS"가 아니라 그냥 CSS다. 라이브러리를 한 번 더 깔기 전에, "이거 표준에 있지 않을까?"를 한 번 더 확인하자. 대부분 답은 "있다"이다.
2026년의 웹 개발은, 표준에 베팅하면 이기는 시대다.
참고 / References
- MDN Web Docs — CSS Container Queries
- MDN — View Transitions API
- MDN — Popover API
- MDN — CSS Anchor Positioning
- MDN — CSS Scroll-driven Animations
- MDN — CSS Nesting
- MDN —
:has()selector - MDN —
color-mix() - MDN —
light-dark() - MDN — CSS
@scope - MDN — CSS Cascade Layers (
@layer) - MDN — CSS Subgrid
- MDN — Speculation Rules API
- MDN — WebGPU API
- MDN — WebTransport API
- MDN — CSS Custom Highlight API
- MDN —
content-visibility - web.dev — Container queries land in stable browsers
- web.dev — Cross-document view transitions
- web.dev — Introducing the popover API
- web.dev — CSS anchor positioning API
- web.dev — Scroll-driven animations
- web.dev — Speculation Rules API
- Bramus van Damme blog — scroll-driven-animations.style
- Una Kravets blog — una.im
- Adam Argyle — nerdy.dev
- 네이버 D2 — d2.naver.com
- TOAST UI 블로그 — ui.toast.com/weekly-pick
- html5.jp — html5.jp
- mizchi blog — zenn.dev/mizchi
- CodeGrid — www.codegrid.net
- State of CSS — stateofcss.com
- W3C CSS Working Group — drafts.csswg.org
- Baseline (web platform feature status) — web.dev/baseline
- Can I Use — caniuse.com