---
id: frontend-css-modern-features
title: Modern CSS — :has() / Subgrid / Color spaces / @scope
category: Coding
status: draft
source_trust_level: B
verification_status: conceptual
created_at: 2026-05-09
updated_at: 2026-05-09
tags: [frontend, css, vibe-coding]
tech_stack: { language: "CSS", applicable_to: ["Frontend"] }
applied_in: []
aliases: [:has, subgrid, OKLCH, color-mix, @scope, anchor positioning, popover]
---

# Modern CSS

> 2024-2026 = CSS 황금기. **:has() (parent selector), subgrid, OKLCH, @scope, anchor positioning, popover, container queries**. JS 없이 가능한 게 늘어남.

## 📖 핵심 개념
- :has(): parent selector (드디어).
- Subgrid: nested grid 가 parent grid 따름.
- OKLCH: perceptually uniform color.
- @scope: CSS scope (CSS-in-JS 의 native).
- Anchor positioning: tooltip / popover 자동 align.

## 💻 코드 패턴

### :has() — parent selector
```css
/* Card 안 image 가 있으면 padding 변경 */
.card:has(img) {
  padding: 0;
}

/* Form 안 :invalid input 가 있으면 button disable */
form:has(input:invalid) button {
  opacity: 0.5;
  pointer-events: none;
}

/* Sibling */
.card + .card:has(.featured) {
  border-color: gold;
}

/* :has + :not */
.list:has(:not(.read)) {
  background: yellow;
}
```

→ JS 없이 parent / sibling 반응. Chrome 105+ / Safari 15.4+ / FF 121+.

### Subgrid
```css
.parent {
  display: grid;
  grid-template-columns: 1fr 2fr 1fr;
  gap: 16px;
}

.parent > .nested {
  display: grid;
  grid-template-columns: subgrid;       /* parent 의 column 따름 */
  grid-column: 1 / -1;                   /* 모든 column */
}
```

→ Nested grid 가 parent column align.

### OKLCH (modern color)
```css
:root {
  --primary: oklch(60% 0.2 250);          /* L=60% C=0.2 H=250 */
  --primary-hover: oklch(55% 0.2 250);    /* darker */
  --primary-bg: oklch(95% 0.05 250);      /* lighter */
}

.button {
  background: var(--primary);
}
.button:hover {
  background: oklch(from var(--primary) calc(l - 5%) c h);
}
```

→ HSL 보다 perceptually uniform. Tailwind 4 가 default.

### color-mix
```css
.card {
  background: color-mix(in oklch, var(--brand) 80%, white);
  border-color: color-mix(in srgb, var(--brand) 50%, transparent);
}
```

→ 동적 color 변형.

### @scope
```css
@scope (.card) to (.card-content) {
  /* .card ~ .card-content 사이만 */
  h2 { color: red; }
  p { font-size: 14px; }
}
```

```html
<div class="card">
  <h2>...</h2>           <!-- styled -->
  <div class="card-content">
    <h2>...</h2>          <!-- not styled (out of scope) -->
  </div>
</div>
```

→ CSS module / CSS-in-JS 의 native 대안.

### Anchor positioning
```css
.tooltip {
  position-anchor: --anchor-1;  /* anchor name */
  position: absolute;
  top: anchor(bottom);
  left: anchor(center);
  translate: -50% 0;
}

.button {
  anchor-name: --anchor-1;
}
```

```html
<button class="button">Hover me</button>
<div class="tooltip">Tooltip text</div>
```

→ JS positioning 없이 자동 align. Chrome 125+.

### Popover API
```html
<button popovertarget="my-popover">Open</button>
<div id="my-popover" popover>
  <p>Popover content</p>
  <button popovertarget="my-popover" popovertargetaction="hide">Close</button>
</div>
```

```css
[popover] {
  border: none;
  border-radius: 8px;
  padding: 1rem;
}

[popover]::backdrop {
  background: rgba(0, 0, 0, 0.5);
}
```

→ Native modal / dropdown. 모든 modern browser.

### CSS nesting
```css
/* Modern — Sass-like */
.card {
  padding: 16px;
  
  & .title {
    font-size: 24px;
    
    &:hover {
      color: blue;
    }
  }
  
  &:has(img) {
    padding: 0;
  }
}
```

→ Sass / PostCSS 없이.

### Logical properties (RTL friendly)
```css
.card {
  /* 옛 */
  margin-left: 16px;
  padding-right: 8px;
  
  /* 새 — RTL 자동 */
  margin-inline-start: 16px;
  padding-inline-end: 8px;
}
```

### Cascade layers (@layer)
```css
@layer reset, base, components, utilities;

@layer reset {
  * { margin: 0; }
}

@layer components {
  .button { ... }
}

@layer utilities {
  .mt-4 { margin-top: 1rem; }
}
```

→ Specificity 충돌 해결 — layer 가 우선순위.

### Container queries (위 별 문서)
```css
.container { container-type: inline-size; }

@container (min-width: 400px) { ... }
```

### Aspect ratio
```css
.video { aspect-ratio: 16 / 9; width: 100%; }
.avatar { aspect-ratio: 1; height: 50px; }
```

### clamp / min / max
```css
.responsive-font {
  font-size: clamp(1rem, 2vw, 2rem);  /* min 1rem, max 2rem, 2vw 사이 */
}

.container {
  width: min(90%, 1200px);
}
```

### CSS variables + dynamic
```css
.button {
  --hue: 220;
  background: oklch(60% 0.2 var(--hue));
}

.button.warning { --hue: 30; }
.button.danger { --hue: 0; }
```

### Scrollbar gutter
```css
html { scrollbar-gutter: stable; }
```

→ Scrollbar 가 layout 안 흔들림.

### text-wrap: balance / pretty
```css
h1 { text-wrap: balance; }   /* 균등 line break */
p { text-wrap: pretty; }      /* 마지막 줄 홀로 안 됨 */
```

### accent-color
```css
:root { accent-color: oklch(60% 0.2 250); }
/* Form element (checkbox, radio) 자동 brand */
```

### color-scheme
```css
:root {
  color-scheme: light dark;
}
```

→ Browser 가 system 따라 자동 dark mode (form element, scrollbar).

### Container query units (위 문서)
```css
.text { font-size: 5cqi; }
```

### print stylesheet
```css
@media print {
  .no-print { display: none; }
  body { font-size: 12pt; }
  
  a::after { content: " (" attr(href) ")"; }  /* URL 표시 */
  
  .page-break { page-break-after: always; }
}
```

### Browser support 검사
```
caniuse.com
mdn.dev/learn 

새 기능 = polyfill / fallback 디자인.
```

```css
@supports (color: oklch(60% 0.2 250)) {
  .button { background: oklch(...); }
}

@supports not (color: oklch(60% 0.2 250)) {
  .button { background: hsl(...); }  /* fallback */
}
```

### Tailwind 4
```
- OKLCH default
- Container query @container
- :has() variants
- @scope
- 모든 modern feature 친화
```

## 🤔 의사결정 기준
| 기능 | 사용 |
|---|---|
| Parent selector | :has() |
| Nested grid align | Subgrid |
| 색 계산 | OKLCH + color-mix |
| Component scope | @scope |
| Tooltip / popover | Anchor + Popover API |
| CSS-in-JS 대안 | @scope + cascade layers |

## ❌ 안티패턴
- **JS 가 모든 거 — CSS 가능한데**: :has + container 가 더 빠름.
- **CSS-in-JS 무 reason**: @scope 가 native.
- **HSL 만 + brand 변형**: OKLCH 가 perceptual.
- **!important 남발**: cascade layers.
- **Browser support 무 fallback**: @supports.
- **Tooltip JS positioning + 옛 ancho-positioning 가능**: native.

## 🤖 LLM 활용 힌트
- :has() / Subgrid / Container query / @scope = 새 standards.
- OKLCH > HSL.
- Native popover + anchor = JS 줄임.
- Tailwind 4 가 modern features 친화.

## 🔗 관련 문서
- [[Frontend_Container_Queries]]
- [[Frontend_Tailwind_Architecture]]
- [[Frontend_Animation_Motion]]
