CSS 앵커 배치 API 소개

게시일: 2024년 5월 10일

CSS Anchor Positioning API는 앵커라고 하는 다른 요소를 기준으로 요소를 기본적으로 배치할 수 있으므로 웹 개발의 판도를 바꿀 획기적인 기술입니다. 이 API는 메뉴 및 하위 메뉴, 도움말, 선택, 라벨, 카드, 설정 대화상자와 같은 많은 인터페이스 기능의 복잡한 레이아웃 요구사항을 간소화합니다. 브라우저에 앵커 위치 지정이 내장되어 있으므로 서드 파티 라이브러리에 의존하지 않고 계층화된 사용자 인터페이스를 빌드할 수 있어 창의적인 가능성의 세계가 열립니다.

앵커 위치 지정은 Chrome 125부터 사용할 수 있습니다.

브라우저 지원

  • Chrome: 125.
  • Edge: 125.
  • Firefox: 지원되지 않음
  • Safari: 지원되지 않음

소스

핵심 개념: 앵커 및 배치된 요소

이 API의 핵심은 앵커위치 지정된 요소 간의 관계입니다. 앵커는 anchor-name 속성을 사용하여 참조점으로 지정된 요소입니다. 배치된 요소는 position-anchor 속성을 사용하여 앵커를 기준으로 배치되거나 배치 로직에서 anchor-name를 명시적으로 사용하는 요소입니다.

앵커 요소 및 배치된 요소

앵커 설정

앵커를 만드는 방법은 간단합니다. 선택한 요소에 앵커 이름 속성을 적용하고 고유 식별자를 할당합니다. 이 고유 식별자는 CSS 변수와 마찬가지로 앞에 이중 대시를 추가해야 합니다.

.anchor-button {
    anchor-name: --anchor-el;
}

앵커 이름이 할당되면 .anchor-button는 앵커 역할을 하여 다른 요소의 배치를 안내할 수 있습니다. 이 앵커를 다른 요소에 연결하는 방법은 다음 두 가지 중 하나입니다.

암시적 앵커

앵커를 다른 요소에 연결하는 첫 번째 방법은 다음 코드 예와 같이 암시적 앵커를 사용하는 것입니다. position-anchor 속성은 앵커에 연결하려는 요소에 추가되며 앵커의 이름 (이 경우 --anchor-el)을 값으로 갖습니다.

.positioned-notice {
    position-anchor: --anchor-el;
}

암시적 앵커 관계를 사용하면 첫 번째 인수에서 앵커 이름을 명시적으로 지정하지 않고도 anchor() 함수를 사용하여 요소를 배치할 수 있습니다.

.positioned-notice {
    position-anchor: --anchor-el;
    top: anchor(bottom);
}

명시적 앵커

또는 앵커 함수에서 직접 앵커 이름을 사용할 수 있습니다 (예: top: anchor(--anchor-el bottom). 이를 명시적 앵커라고 하며 여러 요소에 고정하려는 경우에 유용합니다 (아래 예 참고).

.positioned-notice {
    top: anchor(--anchor-el bottom);
}

앵커를 기준으로 요소 배치

물리적 속성이 있는 앵커 배치 다이어그램

앵커 위치 지정은 CSS 절대 위치 지정을 기반으로 합니다. 위치 지정 값을 사용하려면 배치된 요소에 position: absolute를 추가해야 합니다. 그런 다음 anchor() 함수를 사용하여 위치 지정 값을 적용합니다. 예를 들어 고정된 요소를 고정 요소의 왼쪽 상단에 배치하려면 다음과 같은 위치 지정을 사용합니다.

.positioned-notice {
    position-anchor: --anchor-el;
    /* absolutely position the positioned element */
    position: absolute;
    /* position the right of the positioned element at the right edge of the anchor */
    right: anchor(right);
    /* position the bottom of the positioned element at the top edge of the anchor */
    bottom: anchor(top);
}
배치된 요소의 가장자리 배치 다이어그램

이제 다음 이미지와 같이 한 요소가 다른 요소에 고정되었습니다.

데모 스크린샷

이러한 값에 논리적 순서를 사용하려면 다음과 같이 대응합니다.

  • top = inset-block-start
  • left= inset-inline-start
  • bottom = inset-block-end
  • right= inset-inline-end

anchor-center를 사용하여 배치된 요소 가운데 정렬

앵커에 비해 앵커 위치 요소를 더 쉽게 가운데에 배치할 수 있도록 justify-self, align-self, justify-items, align-items 속성과 함께 사용할 수 있는 anchor-center라는 새 값이 있습니다.

이 예에서는 justify-self: anchor-center를 사용하여 위치 지정된 요소를 앵커 위에 가운데로 배치하여 이전 예를 수정합니다.

.positioned-notice {
  position: absolute;
  /*  Anchor reference  */
  position-anchor: --anchor-el;
  /*  Position bottom of positioned elem at top of anchor  */
  bottom: anchor(top);
  /*  Center justification to the anchor */
  justify-self: anchor-center;
}

데모 스크린샷

여러 앵커

요소는 두 개 이상의 앵커에 연결할 수 있습니다. 즉, 두 개 이상의 앵커를 기준으로 배치되는 위치 값을 설정해야 할 수 있습니다. anchor() 함수를 사용하고 첫 번째 인수에서 참조하는 앵커를 명시적으로 지정하면 됩니다. 다음 예에서 배치된 요소의 왼쪽 상단은 한 앵커의 오른쪽 하단에 고정되고 배치된 요소의 오른쪽 하단은 두 번째 앵커의 왼쪽 상단에 고정됩니다.

.anchored {
  position: absolute;
  top: anchor(--one bottom);
  left: anchor(--one right);
  right: anchor(--two left);
  bottom: anchor(--two top);
}

데모 스크린샷

inset-area로 위치 지정

절대 위치 지정으로부터의 기본 방향 위치 지정 외에도 앵커링 API에 삽입 영역이라는 새로운 레이아웃 메커니즘이 포함되어 있습니다.

삽입 영역을 사용하면 각 앵커를 기준으로 앵커 위치 요소를 쉽게 배치할 수 있으며, 앵커링 요소가 중앙에 있는 9개 셀 그리드에서 작동합니다.

9개 셀 그리드에 표시된 다양한 인셋 영역 배치 옵션

절대 위치 지정 대신 삽입 영역을 사용하려면 물리적 또는 논리적 값과 함께 inset-area 속성을 사용하세요. 예를 들면 다음과 같습니다.

  • 상단 중앙: inset-area: top 또는 inset-area: block-start
  • 왼쪽 중앙: inset-area: left 또는 inset-area: inline-start
  • 가운데 하단: inset-area: bottom 또는 inset-area: block-end
  • 오른쪽 가운데: inset-area: right 또는 inset-area: inline-end

데모 스크린샷

anchor-size()로 요소 크기 조절

anchor-size() 함수(앵커 위치 지정 API의 일부)는 앵커의 크기(너비, 높이 또는 인라인 및 블록 크기)를 기반으로 앵커 위치 지정된 요소의 크기를 조절하거나 위치를 지정하는 데 사용할 수 있습니다.

다음 CSS는 높이에 이를 사용하는 예를 보여줍니다. calc() 함수 내에서 anchor-size(height)를 사용하여 도움말의 최대 높이를 앵커 높이의 두 배로 설정합니다.

.positioned-notice {
  position-anchor: --question-mark;

  /*  set max height of the tooltip to 2x height of the anchor  */
  max-height: calc(anchor-size(height) * 2);
}

데모 스크린샷

팝오버 및 대화상자와 같은 최상위 레이어 요소에 앵커 사용

앵커 배치는 popover와 같은 최상위 레이어 요소와 함께 사용하면 매우 효과적입니다. 및 <dialog>. 이러한 요소는 나머지 DOM 하위 트리와 별도의 레이어에 배치되지만 앵커 위치 지정을 사용하면 최상위 레이어에 없는 요소와 함께 다시 연결하고 스크롤할 수 있습니다. 이는 계층형 인터페이스에 큰 이점입니다.

다음 예에서는 버튼을 사용하여 도움말 팝오버 세트가 열리도록 트리거됩니다. 버튼은 앵커이고 도움말은 위치가 지정된 요소입니다. 다른 앵커 요소와 마찬가지로 위치가 지정된 요소의 스타일을 지정할 수 있습니다. 이 예에서 anchor-nameposition-anchor는 버튼 및 도움말의 인라인 스타일입니다. 각 앵커에는 고유한 앵커 이름이 필요하므로 동적 콘텐츠를 생성할 때는 인라인 처리가 가장 쉬운 방법입니다.

데모 스크린샷

@position-try로 앵커 위치 조정

초기 앵커 위치를 설정한 후 앵커가 포함 블록의 가장자리에 도달하면 위치를 조정할 수 있습니다. 대체 앵커 위치를 만들려면 position-try-options 속성과 함께 @position-try 디렉티브를 사용하면 됩니다.

다음 예에서는 메뉴 오른쪽에 하위 메뉴가 표시됩니다. 메뉴와 하위 메뉴는 트리거 버튼에 고정되는 경향이 있으므로 팝오버 속성과 함께 앵커 위치 지정 API를 사용하는 것이 좋습니다.

이 하위 메뉴의 경우 가로 공간이 충분하지 않으면 메뉴 아래로 이동할 수 있습니다. 이렇게 하려면 먼저 초기 위치를 설정합니다.

#submenu {
  position: absolute;
  position-anchor: --submenu;

  /* initial position */
  margin-left: var(--padding);
  inset-area: right span-bottom;
}

그런 다음 @position-try를 사용하여 대체 고정 위치를 설정합니다.

/* alternate position */
@position-try --bottom {
  margin: var(--padding) 0 0 var(--padding);
  inset-area: bottom;
}

마지막으로 position-try-options로 두 개를 연결합니다. 전체적으로 다음과 같이 표시됩니다.

#submenu {
  position: absolute;
  position-anchor: --submenu;
  /* initial position */
  margin-left: var(--padding);
  inset-area: right span-bottom;
  */ connect with position-try options */
  position-try-options: --bottom;
}

/* alternate position */
@position-try --bottom {
  margin: var(--padding) 0 0 var(--padding);
  inset-area: bottom;
}

앵커 위치 자동 전환 키워드

위에서 아래로 또는 왼쪽에서 오른쪽으로 (또는 둘 다) 뒤집는 등의 기본 조정이 있는 경우 맞춤 @position-try 선언을 만드는 단계를 건너뛰고 flip-blockflip-inline와 같은 브라우저에서 지원되는 기본 제공 뒤집기 키워드를 사용할 수도 있습니다. 이는 맞춤 @position-try 선언의 대체 항목으로 작동하며 서로 조합하여 사용할 수 있습니다.

position-try-options: flip-block, flip-inline, flip-block flip-inline;

플립 키워드를 사용하면 앵커 코드를 크게 간소화할 수 있습니다. 몇 줄이면 다른 위치로 완전한 기능의 앵커를 만들 수 있습니다.

#my-tooltip {
  position-anchor: --question-mark;
  inset-area: top;
  position-try-options: flip-block;
}

하위 스크롤러의 앵커의 경우 position-visibility

페이지의 하위 스크롤 내에 요소를 고정하고 싶은 경우가 있습니다. 이 경우 position-visibility를 사용하여 앵커의 가시성을 제어할 수 있습니다. 앵커는 언제 화면에 표시되나요? 언제 사라지나요? 이 기능을 사용하면 이러한 옵션을 제어할 수 있습니다. 앵커가 표시되지 않을 때까지 배치된 요소가 표시되도록 하려면 position-visibility: anchors-visible를 사용합니다.

#tooltip {
  position: fixed;
  position-anchor: --anchor-top-anchor;
  position-visibility: anchors-visible;
  bottom: anchor(top);
}

또는 position-visibility: no-overflow를 사용하여 앵커가 컨테이너를 오버플로하지 않도록 할 수 있습니다.

#tooltip {
  position: absolute;
  position-anchor: --anchor-top-anchor;
  position-visibility: no-overflow;
  bottom: anchor(top);
}

기능 감지 및 폴리필

현재 브라우저 지원이 제한되어 있으므로 이 API를 사용할 때는 몇 가지 예방 조치를 취하는 것이 좋습니다. 먼저 @supports 기능 쿼리를 사용하여 CSS에서 직접 지원을 확인할 수 있습니다. 이렇게 하려면 다음과 같이 앵커 스타일을 래핑합니다.

@supports (anchor-name: --myanchor) {

  /* Anchor styles here */

}

또한 Firefox 54, Chrome 51, Edge 79, Safari 10에서 작동하는 Oddbird의 CSS 앵커 위치 지정 폴리필을 사용하여 앵커 위치 지정 기능을 폴리필할 수 있습니다. 이 폴리필은 대부분의 기본 앵커 위치 기능을 지원하지만 현재 구현은 완전하지 않으며 일부 오래된 문법이 포함되어 있습니다. unpkg 링크를 사용하거나 패키지 관리자에서 직접 가져올 수 있습니다.

접근성 관련 참고사항

앵커 위치 지정 API를 사용하면 요소를 다른 요소에 비해 배치할 수 있지만, 본질적으로 요소 간에 의미 있는 시맨틱 관계를 만들지는 않습니다. 앵커 요소와 배치된 요소 간에 실제로 의미론적 관계가 있는 경우(예: 배치된 요소가 앵커 텍스트에 관한 사이드바 주석인 경우) aria-details를 사용하여 앵커 요소에서 배치된 요소를 가리키는 방법이 있습니다. 스크린 리더 소프트웨어는 아직 aria-details를 처리하는 방법을 학습하고 있지만 지원이 개선되고 있습니다.

<div class="anchor" aria-details="sidebar-comment">Main content</div>
<div class="positioned" id="sidebar-comment">Sidebar content</div>
.anchor {
  anchor-name: --anchor;
}

.positioned {
  position: fixed;
  position-anchor: --anchor;
}

popover 속성 또는 <dialog> 요소와 함께 앵커 위치 지정을 사용하는 경우 브라우저가 적절한 접근성을 위해 포커스 탐색 수정을 처리하므로 팝오버 또는 대화상자를 DOM 순서대로 배치할 필요가 없습니다. 사양의 접근성에 관한 메모에서 자세히 알아보세요.

결론

이 기능은 완전히 새로운 기능이며 개발자 여러분이 이 기능으로 무엇을 빌드할지 기대됩니다. 지금까지 차트, 연결선, 각주, 시각적 교차 참조의 동적 라벨 등 커뮤니티에서 정말 유용한 사용 사례를 살펴보았습니다. 앵커 포지셔닝을 실험하는 동안 의견을 듣고 싶습니다. 버그를 발견하면 알려주세요.

추가 자료