차세대 웹 스타일 지정

최신 CSS의 흥미로운 기능을 알아보세요.

현재 CSS에서는 수많은 흥미로운 일들이 일어나고 있으며, 그 중 상당수는 이미 오늘날의 브라우저에서 지원됩니다. 아래에서 시청하실 수 있는 CDS 2019의 강연에서는 관심을 가져야 할 몇 가지 새로운 기능과 출시 예정 기능을 다룹니다.

이 게시물에서는 현재 사용할 수 있는 기능을 중점적으로 다루므로 Houdini와 같은 출시 예정 기능에 관한 자세한 논의를 시청해야 합니다. 설명한 모든 기능에 대한 데모는 CSS@CDS 페이지에서 확인할 수 있습니다.

목차

스크롤 스냅

스크롤 스냅을 사용하면 사용자가 콘텐츠를 세로, 가로 또는 둘 다로 스크롤할 때 맞추기 지점을 정의할 수 있습니다. 스크롤 관성 및 감속 기능이 내장되어 있으며 터치가 지원됩니다.

이 샘플 코드는 하위 <picture> 요소의 왼쪽에 맞춰진 지점이 있는 <section> 요소의 가로 스크롤을 설정합니다.

section {
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory;
}

section > picture {
  scroll-snap-align: start;
}

이는 다음과 같은 방식으로 이루어집니다.

  • 상위 <section> 요소에서
    • 가로 스크롤이 가능하도록 overflow-xauto로 설정합니다.
    • overscroll-behavior-xcontain로 설정하여 사용자가 <section> 요소의 스크롤 영역 경계에 도달했을 때 상위 요소가 스크롤되지 않도록 합니다. 맞추기 위해 반드시 필요한 것은 아니지만 일반적으로 이렇게 하는 것이 좋습니다.
    • scroll-snap-typex(가로 맞추기)으로 설정하고 mandatory로 설정하여 표시 영역이 항상 가장 가까운 맞추기 지점에 맞춰지도록 합니다.
  • 하위 <picture> 요소에서 scroll-snap-align가 시작으로 설정되어 각 사진의 왼쪽에 맞추기 지점을 설정합니다 (directionltr로 설정되었다고 가정).

다음은 라이브 데모입니다.

세로 스크롤 스냅매트릭스 스크롤 스냅에 관한 데모도 살펴보세요.

:focus-within

:focus-within는 오랫동안 지속된 접근성 문제를 해결합니다. 보조 기술 사용자가 UI에 액세스할 수 있도록 하위 요소에 포커스를 맞추면 상위 요소의 표시에 영향을 주어야 하는 경우가 많습니다.

예를 들어, 여러 항목이 포함된 드롭다운 메뉴가 있는 경우 일부 항목에 포커스가 있는 동안 메뉴는 계속 표시되어야 합니다. 그렇지 않으면 키보드 사용자에게 메뉴가 표시되지 않습니다.

:focus-within는 포커스가 지정된 요소의 하위 요소에 있을 때 스타일을 적용하도록 브라우저에 지시합니다. 메뉴 예시로 돌아가서 메뉴 요소에 :focus-within를 설정하면 메뉴 항목에 포커스가 있을 때 계속 표시되도록 할 수 있습니다.

.menu:focus-within {
  display: block;
  opacity: 1;
  visibility: visible;
}

포커스와 포커스 내 동작의 차이를 보여주는 그림

아래 데모에서 포커스 가능 요소를 탭으로 이동해 보세요. 메뉴 항목에 포커스를 맞추면 메뉴가 계속 표시됩니다.

미디어 쿼리 레벨 5

새로운 미디어 쿼리는 사용자의 기기 환경설정에 따라 앱의 사용자 환경을 조정하는 강력한 방법을 제공합니다. 기본적으로 브라우저는 미디어 쿼리의 prefers-* 그룹을 사용하여 CSS에서 응답할 수 있는 시스템 수준 환경설정의 프록시 역할을 합니다.

시스템 수준의 사용자 환경설정을 해석하는 미디어 쿼리를 보여주는 다이어그램

다음은 개발자가 가장 관심을 가질 만한 새로운 쿼리입니다.

이러한 검색어는 접근성 면에서 큰 도움이 됩니다. 이전에는 사용자가 OS를 고대비 모드로 설정했다는 사실을 알 수 없었습니다. 브랜드에 충실한 웹 앱용 고대비 모드를 제공하려면 사용자에게 앱 내의 UI에서 선택하도록 요청해야 했습니다. 이제 prefers-contrast를 사용하여 OS에서 고대비 설정을 감지할 수 있습니다.

이러한 미디어 쿼리의 한 가지 흥미로운 의미는 다양한 사용자 환경설정과 접근성 요구사항을 수용하기 위해 시스템 수준의 사용자 환경설정의 여러 조합을 설계할 수 있다는 것입니다. 사용자가 어두운 환경에서 고대비 어두운 모드를 원하는 경우 그렇게 할 수 있습니다.

아담에게 중요한 점은 '감소된 모션을 선호'하는 것이 '움직임 없음'으로 구현되지 않는다는 것입니다. 사용자는 애니메이션을 원하지 않는 것이 아니라 더 적은 모션을 선호한다고 말합니다. 줄어든 움직임은 움직임이 없는 것이 아니라고 주장합니다. 다음은 사용자가 모션을 줄이는 것을 선호할 때 크로스페이드 애니메이션을 사용하는 예입니다.

논리 속성

논리적 속성은 국제화를 다루는 개발자가 많아짐에 따라 드러난 문제를 해결합니다. marginpadding와 같은 많은 레이아웃 속성은 위에서 아래로, 왼쪽에서 오른쪽으로 읽는 언어를 가정합니다.

기존 CSS 레이아웃 속성을 보여주는 다이어그램

쓰기 모드가 다양한 여러 언어로 페이지를 디자인할 때 개발자는 여러 요소에 걸쳐 이러한 모든 속성을 개별적으로 조정해야 했고, 이는 곧 유지관리가 악몽이 됩니다.

논리 속성을 사용하면 변환 및 쓰기 모드 전반에서 레이아웃 무결성을 유지할 수 있습니다. 공간 배열이 아닌 콘텐츠의 시맨틱 순서에 따라 동적으로 업데이트됩니다. 논리 속성이 있는 각 요소는 다음과 같은 두 가지 차원을 가집니다.

  • 블록 크기는 선 안의 텍스트 흐름과 수직입니다. (영어에서 block-sizeheight와 동일합니다.)
  • 인라인 크기는 선의 텍스트 흐름과 평행입니다. (영어에서 inline-sizewidth와 동일합니다.)

이러한 크기 이름은 모든 논리적 레이아웃 속성에 적용됩니다. 예를 들어 영어에서 block-starttop와 같고 inline-endright와 같습니다.

새로운 CSS 논리적 레이아웃 속성을 보여주는 다이어그램

논리적 속성을 사용하면 개별 요소에서 수십 개의 레이아웃 속성을 업데이트하는 대신 페이지의 writing-modedirection 속성을 변경하기만 하면 다른 언어의 레이아웃을 자동으로 업데이트할 수 있습니다.

<body> 요소의 writing-mode 속성을 다른 값으로 설정하여 아래 데모에서 논리적 속성이 작동하는 방식을 확인할 수 있습니다.

position: sticky

position: sticky가 있는 요소는 화면에서 벗어나기 시작할 때까지 블록 흐름에 남아 있으며, 이때 페이지의 나머지 부분과 함께 스크롤을 중지하고 요소의 top 값으로 지정된 위치에 고정됩니다. 이 요소에 할당된 공간은 흐름에 유지되고 사용자가 다시 위로 스크롤하면 요소가 그 위치로 돌아옵니다.

고정 위치를 사용하면 이전에는 JavaScript가 필요했던 여러 유용한 효과를 만들 수 있습니다. 몇 가지 가능성을 보여주기 위해 몇 가지 데모를 제작했습니다. 각 데모는 대체로 동일한 CSS를 사용하며 각 효과를 만들기 위해 HTML 마크업을 약간만 조정합니다.

고정 스택

이 데모에서는 모든 고정 요소가 동일한 컨테이너를 공유합니다. 즉, 사용자가 아래로 스크롤할 때 각 고정 요소가 이전 요소 위로 슬라이드됩니다. 고정 요소는 동일한 고정 위치를 공유합니다.

고정 슬라이드

여기서 고정 요소는 사촌입니다. 즉, 부모는 형제자매입니다. 고정 요소가 컨테이너의 하한선에 도달하면 고정 요소가 컨테이너와 함께 위쪽으로 이동하여 하위 고정 요소가 위쪽 고정 요소가 위로 올라간다는 인상을 줍니다. 즉, 고정된 위치를 두고 경쟁하는 것처럼 보입니다.

스티키 데스페라도

고정 슬라이드와 마찬가지로 이 데모의 고정 요소는 사촌입니다. 그러나 2열 그리드 레이아웃으로 설정된 컨테이너에 배치되었습니다.

backdrop-filter

backdrop-filter 속성을 사용하면 요소 자체가 아닌 요소 영역에 그래픽 효과를 적용할 수 있습니다. 따라서 이전에는 복잡한 CSS 및 JavaScript 해킹을 사용해서만 달성할 수 있었던 여러 멋진 효과를 CSS 한 줄로 수행할 수 있습니다.

예를 들어 이 데모에서는 backdrop-filter를 사용하여 OS 스타일의 블러를 적용합니다.

이미 backdrop-filter에 관한 유용한 게시물이 있으니 확인해 보세요.

:is()

:is() 의사 클래스는 실제로 10년이 넘었으나 여전히 충분히 활용되지 못하고 있습니다. 이 메서드는 쉼표로 구분된 선택기 목록을 인수로 취하고 목록의 모든 선택기와 일치합니다. 이러한 유연성 덕분에 매우 편리하고 제공하는 CSS의 양을 크게 줄일 수 있습니다.

간단한 예 보기:

button.focus,
button:focus {
  …
}

article > h1,
article > h2,
article > h3,
article > h4,
article > h5,
article > h6 {
  …
}

/* selects the same elements as the code above */
button:is(.focus, :focus) {
  …
}

article > :is(h1,h2,h3,h4,h5,h6) {
  …
}

gap

CSS 그리드 레이아웃에 한동안 gap (이전의 grid-gap)가 있었습니다. 하위 요소 주변 간격 대신 포함하는 요소의 내부 간격을 지정하여 gap는 여러 일반적인 레이아웃 문제를 해결합니다. 예를 들어 간격을 사용하면 하위 요소의 여백으로 인해 포함된 요소의 가장자리 주위에 원치 않는 공백이 생길 염려가 없습니다.

간격 속성이 컨테이너 요소의 가장자리 주위에 의도하지 않은 간격을 피하도록 하는 방법을 보여주는 그림

더 좋은 소식: gap가 Flexbox에 도입되어 그리드에서 제공하는 다음과 같은 동일한 간격 혜택을 모두 누릴 수 있습니다.

  • 공백 선언이 많지 않고 하나만 있습니다.
  • 어떤 하위 요소에 간격이 있어야 하는지에 대한 프로젝트 규칙을 설정할 필요가 없습니다. 대신 포함된 요소가 공백을 소유합니다.
  • lobotomized Owl과 같은 이전 전략보다 코드를 더 쉽게 이해할 수 있습니다.

다음 동영상은 그리드 레이아웃과 Flex 레이아웃의 두 요소에 단일 gap 속성을 사용할 때의 이점을 보여줍니다.

지금은 FireFox만 Flex 레이아웃에서 gap를 지원하지만, 다음 데모를 보면서 작동 방식을 확인해 보세요.

CSS 후디니

Houdini는 브라우저의 렌더링 엔진용 하위 수준 API로, 맞춤 CSS를 해석하는 방법을 브라우저에 알려줄 수 있습니다. 즉, CSS 개체 모델에 액세스하여 자바스크립트를 통해 CSS를 확장할 수 있습니다. 이렇게 하면 다음과 같은 몇 가지 장점이 있습니다.

  • 맞춤 CSS 기능을 훨씬 더 효과적으로 만들 수 있습니다.
  • 렌더링 문제를 애플리케이션 로직과 쉽게 분리할 수 있습니다.
  • 브라우저가 더 이상 스크립트를 파싱하고 두 번째 렌더링 주기를 수행할 필요가 없으므로 현재 JavaScript로 하는 CSS 폴리필보다 성능이 뛰어납니다. Houdini 코드는 첫 번째 렌더링 주기에서 파싱됩니다.

기존 JavaScript 폴리필과 Houdini의 작동 방식을 비교한 그림

Houdini는 여러 API의 포괄적인 이름입니다. 자세한 정보 및 현재 상태는 Is Houdini 준비된?를 참조하세요. 이 강연에서는 현재 가장 많이 지원되는 Properties and Values API, Paint API, Animation Worklet에 관해 알아봤습니다. 이처럼 흥미로운 각 API에 대한 전체 게시물을 쉽게 전할 수도 있지만, 지금은 API로 무엇을 할 수 있는지 알 수 있는 개요와 멋진 데모에 대한 강연을 확인해 보세요.

오버플로

논의하고자 하는 부분이 몇 가지 더 있는데 자세히 설명해 드릴 수는 없지만 간단히 살펴보았습니다.

  • size: 높이와 너비를 동시에 설정할 수 있는 속성
  • aspect-ratio: 기본적으로 가로세로 비율이 없는 요소의 가로세로 비율을 설정하는 속성
  • min(), max(), clamp(): 너비와 높이뿐만 아니라 모든 CSS 속성에 숫자 제약 조건을 설정할 수 있는 함수
  • 기존 속성인 list-style-type가 곧 그림 이모티콘과 SVG를 비롯한 더 광범위한 값을 지원할 예정입니다.
  • display: outer inner: display 속성이 곧 두 매개변수를 허용하므로 inline-flex와 같은 복합 키워드를 사용하는 대신 외부 및 내부 레이아웃을 명시적으로 지정할 수 있습니다.
  • CSS 영역: 콘텐츠가 드나들 수 있는 직사각형이 아닌 지정된 영역을 채울 수 있습니다.
  • CSS 모듈: JavaScript가 CSS 모듈을 요청하고 작업을 수행하기 쉬운 풍부한 객체를 돌려받을 수 있습니다.