앵커 배치

툴팁이나 드롭다운 메뉴를 배치할 때는 페이지의 다른 요소와 상대적으로 배치하는 것이 좋습니다. 절대 위치 지정을 사용하여 이 효과를 달성하는 방법이 있었지만, 더 복잡한 요구사항의 경우 이전에는 JavaScript를 사용하여 항목을 배치했습니다.

CSS 앵커 위치 지정은 다른 요소를 기준으로 요소를 선언적으로 배치하는 방법을 제공합니다.

요소 테더링

요소를 앵커로 만들려면 두 개의 대시로 시작하는 문자열의 anchor-name 값을 지정합니다. 이 식별자는 위치가 지정된 요소가 앵커를 찾는 데 사용되며, 구체적인 이름을 지정하는 것이 좋습니다. 요소가 다양한 방식으로 앵커로 사용되는 경우 요소에 여러 앵커 이름을 지정할 수도 있습니다.

위치가 지정된 요소가 테더링될 수 있도록 몇 가지 속성을 설정해야 합니다. 먼저 position: absolute 또는 position: fixed을 설정하여 문서의 흐름에서 요소를 빼내 떠다니도록 해야 합니다.

다음으로 position-anchor을 앵커에 설정한 앵커 이름으로 설정하여 테더링할 앵커를 설정해야 합니다.

마지막으로 앵커를 배치하는 방법을 설정해야 합니다. position-area에 대해서는 이 모듈의 후반부에서 자세히 알아보겠습니다.

#anchor {
   anchor-name: --my-anchor;
}

#positionedElement {
     position: absolute;
     position-anchor: --my-anchor;
     position-area: end;
}

암시적 테더

팝오버는 테더링하기가 훨씬 더 간단합니다. popovertarget가 있는 버튼을 사용하거나 showPopover({source})source를 설정하여 팝오버를 열면 팝오버에 이미 '암시적 앵커'가 설정되어 있습니다. 팝오버는 기본적으로 position: fixed로 이미 플로팅되어 있으므로 팝오버를 배치하려면 위치만 설정하면 됩니다.

#anchor{}

#positionedElement {
  position-area: end;
  margin: unset;
}

잠재적 앵커 범위 지정

여러 곳에서 드롭다운 메뉴와 같은 패턴을 사용할 수 있도록 구성요소의 일부로 앵커 위치 지정을 구현할 수 있습니다. 동일한 anchor-name를 여러 번 사용하는 경우 각 배치된 요소가 올바른 앵커를 찾도록 하려면 어떻게 해야 하나요?

JavaScript 솔루션에서는 각 앵커에 고유 ID를 추가한 다음 위치가 지정된 요소에서 이를 참조합니다. 이러한 방식은 번거로우며 CSS에는 anchor-scope를 사용한 더 간단한 솔루션이 있습니다.

anchor-scope 속성은 요소와 그 하위 요소 간에만 일치하는 앵커 이름을 설정합니다. 하나 이상의 앵커 이름 목록 또는 키워드 all를 허용하여 정의된 모든 앵커 이름의 범위를 제한합니다.

anchor-scope는 이상적으로 위치가 지정된 요소와 앵커 요소의 상위 요소에 추가되며, 이 상위 요소에는 이름이 동일한 다른 앵커 요소가 포함되지 않습니다. 이 속성은 재사용 가능한 구성요소의 루트에 있는 경우가 많습니다.

다음 예에서는 동일한 anchor-name로 반복되는 요소에 적용될 때 anchor-scope가 만드는 차이점을 보여줍니다. 이 예시에서 모든 <img> 요소와 이미지 배너는 --image 앵커 이름을 참조합니다. anchor-scope<li> 요소에 적용되면 position-anchor: --image는 배너와 동일한 <li> 요소 내의 <img> 요소만 일치시키고, 그렇지 않으면 마지막으로 렌더링된 <img>를 일치시킵니다.

포지셔닝

이제 요소를 앵커에 테더링했으므로 요소를 배치할 차례입니다. 앵커 포지셔닝은 position-areaanchor() 함수의 두 가지 포지셔닝 방법을 제공합니다.

position-area

position-area 속성을 사용하면 하나 또는 두 개의 키워드를 지정하여 앵커 주위에 요소를 배치할 수 있습니다. 이 방법은 일반적인 사용 사례를 많이 다루며 시작하기에 좋은 방법입니다.

position-area 작동 방식

position-area는 앵커의 가장자리와 위치가 지정된 요소의 원래 포함 블록으로 생성된 영역에 위치가 지정된 요소의 새 포함 블록을 만들어 작동합니다.

position-area에 사용할 수 있는 키워드는 많지만 이해하기 쉽도록 몇 가지 카테고리로 분류할 수 있습니다. Anchor-tool.com은 문법을 살펴볼 수 있는 유용한 도구입니다.

물리적 키워드

top, left, bottom, right, center 실제 키워드를 사용할 수 있습니다. 예를 들어 position-area: top right는 배치된 요소를 앵커의 위쪽과 오른쪽에 배치합니다. 이러한 키워드에는 y-start, x-start, y-end, x-end와 같은 물리적 축에 상응하는 키워드도 있습니다.

논리 키워드

논리 키워드(block-start, block-end, inline-start, inline-end)를 사용할 수도 있습니다. 예를 들어 position-area: block-end inline-start는 영어와 같은 언어에서 위치가 지정된 요소를 앵커 아래와 왼쪽에 배치하거나 문서의 쓰기 모드에서 블록 축의 앵커 뒤와 인라인 축의 앵커 앞에 배치합니다. center는 논리 키워드와 함께 사용할 수도 있습니다.

블록 축을 먼저, 인라인 축을 두 번째로 사용하여 논리적 키워드를 지정하는 경우 축을 생략할 수도 있습니다. position-area: start endposition-area: block-start inline-end 또는 position-area: inline-end block-start과 동일합니다.

여러 그리드 영역에 걸쳐 있음

지금까지는 이러한 옵션을 사용하면 위치가 지정된 요소를 단일 그리드 공간에만 배치할 수 있었습니다. 물리적 또는 논리적 속성에 span 접두사를 추가하면 인접한 중앙 그리드 공간이 추가됩니다. position-area: span-top right는 앵커의 오른쪽에 배치되고 앵커의 하단에서 배치된 요소의 원래 포함 블록 상단까지 배치됩니다.

드롭다운 메뉴의 일반적인 위치 영역은 position-area: block-end span-inline-end입니다.

span-all 키워드는 3개의 행 또는 열에 걸쳐 있습니다.

단일 키워드

키워드를 하나만 설정하면 다른 축이 자동으로 설정됩니다. 이 기능은 예상대로 작동하지만 작동 방식을 이해하는 것이 유용할 수 있습니다.

제공된 키워드가 축에 관해 명확한 경우 다른 축은 span-all로 계산됩니다. 즉, position-area: bottomposition-area: bottom span-all와 동일하며, 위치가 지정된 요소는 앵커 아래에 있고 포함 블록의 전체 너비를 사용할 수 있습니다.

반면 키워드가 축을 명확하게 나타내지 않으면 반복됩니다. position-area: startstart start과 동일하며 왼쪽에서 오른쪽으로 진행되는 언어에서는 앵커의 왼쪽 상단에 배치됩니다.

anchor() 함수

고급 사용 사례의 경우 position-area가 요구사항을 충족하지 않을 수 있습니다. anchor() 함수를 사용하면 다른 요소의 위치에 따라 개별 인셋 속성을 설정할 수 있습니다. 이 값은 CSS 길이로 변환되므로 계산에 사용하거나 다른 CSS 함수와 함께 사용할 수 있습니다. 또한 여러 면을 여러 앵커에 연결할 수도 있습니다.

anchor() 함수는 앵커 이름과 앵커 측면을 사용합니다. 요소에 position-anchor로 설정되거나 암시적으로(예: 팝오버를 통해) 설정된 기본 앵커가 있는 경우 앵커 이름을 생략할 수 있습니다.

.positionedElement {
  block-start: anchor(--my-anchor start);
  /*  OR  */
  position-anchor: --my-anchor;
  block-start: anchor(start);
}

대체 값

anchor() 함수의 앵커를 찾을 수 없는 경우 전체 선언이 무효화됩니다. 앵커가 위치가 지정된 요소 뒤에 렌더링되거나 일치하는 anchor-name가 있는 요소가 없는 경우 이러한 문제가 발생할 수 있습니다. 이 문제를 처리하려면 대체 길이 또는 비율을 설정하면 됩니다.

.positionedElement {
   block-start: anchor(--my-anchor, 100px)
}

위의 예에서 위치가 지정된 요소의 왼쪽 값은 --focused-anchor에 고정되지만 anchor-name은 첫 번째 버튼에 마우스를 가져가거나 포커스가 있을 때만 존재합니다. anchor() 함수는 길이로 확인되므로 다른 앵커를 대체로 사용할 수 있습니다. 대체 요소를 제공하지 않으면 위치가 지정된 요소가 배치되지 않습니다.

앵커 측면 키워드

앵커 측면 값은 앵커의 어느 가장자리를 기준으로 배치할지 선택합니다. position-area와 마찬가지로 앵커 측 값은 여러 유형의 구문을 지원합니다.

유형 설명
물리적 top, left, bottom, right

물리적 키워드는 앵커의 특정 측면에 해당하지만 설정 중인 배치된 요소의 인셋과 동일한 축에서만 사용할 수 있습니다.

예를 들어 top: anchor(bottom)은 요소의 상단을 앵커의 하단에 배치하지만 left: anchor(top)은 작동하지 않습니다.

측면 inside, outside

inside 키워드는 인셋 속성과 동일한 측면에 해당하고 outside 키워드는 동일한 축의 반대 측면에 해당합니다.

예를 들어 inset-block-start: anchor(inside)는 앵커의 block-start 측면을 나타내고 inset-inline-end: (outside)는 앵커의 inline-start 측면을 나타냅니다.

논리 start, end, self-start, self-end

논리적 키워드는 self-startself-end을 사용하여 배치된 요소의 쓰기 모드 또는 startend을 사용하여 배치된 요소의 포함 블록의 쓰기 모드를 기반으로 앵커의 측면을 참조합니다.

비율 0~100%

백분율 값은 지정된 축에서 앵커의 시작부터 끝까지 축을 따라 배치된 요소를 배치합니다. 0%는 앵커의 start 측면에 있고 100%는 앵커의 끝 측면에 있습니다. center50%와 동일합니다. bottom와 같은 끝쪽 인셋에 백분율을 사용하는 경우 이는 반전되지 않습니다. 0%은 여전히 앵커의 start 측면입니다.

이 예에서는 지정된 축에서 항상 시작부터 끝까지 백분율 값이 적용되는 방식을 보여줍니다.

anchor() 사용

anchor()는 길이이므로 매우 유연합니다. max()calc()과 같은 CSS 함수를 사용하여 값을 조작할 수 있습니다.

한 가지 제한사항은 인셋 속성에만 anchor() 함수를 사용할 수 있다는 점입니다.

위의 예에서는 열린 세부정보 패널 뒤에 배경을 추가합니다. 이 배경은 다른 패널이 열릴 때 부드럽게 애니메이션 처리되고 마우스를 가져간 세부정보 패널을 포함하도록 늘어납니다. 이를 위해 min()를 사용하여 두 앵커 사이에서 더 작은 길이를 선택합니다.

#indicator{
/*  Use the smaller of the 2 values:  */
  inset-block-start: min(
/*   1. The start side of the default anchor, which is the open `<details>` element  */
    anchor(start),
/*   2. The start side of the hovered `<details>` element.    */
    anchor(--hovered start,
/*     If no `<details>` element is hovered, this falls back to infinity px, so that the other value is smaller, and therefore used.   */
       var(calc(1px * infinity)))
  );
}

이 예에서는 calc()를 사용하여 열린 패널 주위에 인라인 공간을 추가합니다.

앵커 크기 사용

anchor-size() 함수를 사용하여 위치가 지정된 요소의 크기, 위치 또는 여백에 앵커의 크기를 사용할 수도 있습니다.

anchor-size()는 앵커 이름을 가져오거나 기본 앵커를 사용합니다. 기본적으로 사용되는 축의 앵커 크기를 사용하므로 width: anchor-size()은 앵커의 너비를 반환합니다. 물리적 키워드 widthheight 또는 논리적 키워드 block, inline, self-block, self-inline를 사용하여 원하는 길이를 지정하여 다른 축을 사용할 수도 있습니다.

오버플로 처리

드롭다운 메뉴 구성요소를 만들고 앵커 위치 지정을 사용하여 드롭다운 메뉴를 원하는 위치에 배치했습니다. 하지만 메뉴를 화면의 다른 쪽으로 이동하거나 사용자 메뉴에 사용했는데 사용자 이름이 너무 깁니다. 갑자기 드롭다운이 화면에서 사라집니다. 이제 어떻게 해야 할까요?

CSS 앵커 포지셔닝에는 포지셔닝된 요소가 포함 블록 외부에 있는 경우 강력한 대체 집합을 빠르게 빌드할 수 있는 내장 시스템이 있습니다.

대체 옵션

position-try-fallbacks 규칙은 대체 옵션 목록을 사용합니다. 기본 위치가 오버플로되면 오버플로되지 않는 위치가 있을 때까지 각 옵션이 순서대로 시도됩니다.

position-area 값을 대체 옵션으로 사용할 수 있습니다. 이 예에서 영어와 같은 왼쪽에서 오른쪽으로 쓰는 모드에서는 위치가 지정된 요소가 앵커 하단에 위치하여 가운데 열과 오른쪽 열에 걸쳐 표시됩니다. 이 영역이 오버플로되면 왼쪽과 가운데 열에 걸쳐 앵커 하단에 배치하려고 시도합니다. 이것도 오버플로되면 오버플로되더라도 위치가 기본 위치로 되돌아갑니다.

.positioned-element {
  position-area: block-end span-inline-end;
  position-try-fallbacks: block-end span-inline-start;
}

일반적인 대체 사례를 처리하는 여러 flip- 키워드도 있습니다. flip-blockflip-inline은 블록 및 인라인 축을 기준으로 요소를 뒤집습니다. flip-block flip-inline와 결합하여 두 축을 모두 뒤집을 수도 있습니다. flip-start 값은 앵커의 시작 모서리에서 끝 모서리까지의 대각선 위로 배치된 요소를 뒤집습니다.

@position-try를 사용하여 맞춤 대체 옵션을 만들 수도 있습니다. 이렇게 하면 여백, 정렬을 설정하고 앵커를 변경할 수 있습니다.

@position-try --menu-below {
  position-area: bottom span-right;
  margin-top: 1em;
}

#positioned-element {
  position-try: --menu-below;
}

flip-blockflip-inline@position-try 대체 옵션에 추가하여 변형을 만들 수 있습니다.

#positioned-element {
  position-try: --menu-below, flip-inline --menu-below;
}

위의 예에서 브라우저는 다음 단계를 따르며 오버플로되지 않는 솔루션을 찾는 즉시 중지합니다.

  1. 요소는 앵커의 오른쪽 하단에 position-area: end로 배치됩니다.
  2. 이 값이 오버플로되면 --bottom-span-right라는 맞춤 대체 옵션으로 요소가 배치됩니다. 이 옵션은 position-area: bottom span-right로 요소를 배치하고 아래에 추가 여백을 둡니다.
  3. 이 값이 오버플로되면 요소가 flip-inline --bottom-span-right로 배치됩니다. flip-inline --bottom-span-right는 맞춤 대체 옵션을 flip-inline와 결합하며, 이는 기본적으로 position-area: bottom span-left입니다.
  4. 이 값이 오버플로되면 --use-alternate 맞춤 대체 옵션을 사용하여 요소가 배치되며, 이 옵션은 완전히 다른 앵커 아래에 요소를 배치합니다.
  5. 이 값이 오버플로되면 오버플로가 발생한다는 것을 알고 있더라도 요소가 position-area: end를 사용하여 원래 배치로 되돌아갑니다.

대체 주문

기본적으로 초기 위치가 오버플로되면 브라우저는 오버플로되지 않는 위치를 찾을 때까지 position-try-fallbacks의 각 옵션을 시도합니다. position-try-order를 사용하여 이 동작을 재정의하여 각 대체 옵션을 테스트하고 지정된 축에서 공간이 가장 많은 옵션을 사용할 수 있습니다.

논리적 키워드 most-block-sizemost-inline-size 또는 실제 키워드 most-heightmost-width를 사용하여 축을 지정할 수 있습니다.

position-try-orderposition-try-fallbacksposition-try 약어와 결합할 수 있으며 순서가 먼저 옵니다.

스크롤

사용자는 스크롤할 때 페이지가 부드럽게 움직이기를 기대합니다. 이를 위해 브라우저에는 스크롤할 때 앵커 위치를 사용할 수 있는 방법에 제한이 있습니다.

위치가 지정된 요소를 서로 다른 스크롤 컨테이너의 앵커에 연결할 수 있지만 요소는 앵커 중 하나의 스크롤에만 반응하여 이동합니다. 이는 팝오버의 암시적 앵커 또는 position-anchor의 값인 기본 앵커가 됩니다.

앵커가 뷰에서 스크롤되어도 위치가 지정된 요소는 계속 표시됩니다. 앵커가 숨겨져 있을 때 위치가 지정된 요소를 숨기려면 position-visibility: anchors-visible를 설정합니다. 이는 앵커가 오버스크롤된 경우뿐만 아니라 visibility: hidden와 같이 다른 방식으로 숨겨진 경우에도 적용됩니다.

이해도 확인

anchor()의 측면에 유효한 값은 무엇인가요?

inside
정답입니다.
25%
정답입니다.
25px
오답입니다. 25px와 같은 길이를 대체 값으로 사용할 수 있지만 측면에는 백분율만 사용할 수 있습니다.
block-start
오답
start
정답입니다.

position-area에 유효한 값은 무엇인가요?

top
정답입니다.
block-end inline-end
정답입니다.
block-start block-end
오답입니다. 각 축에는 하나의 열 또는 행만 정의할 수 있습니다.

어떤 속성이 anchor() 함수를 지원하나요?

top
정답입니다.
margin-left
오답입니다.
inset-block-start
정답입니다.
transform
오답입니다.

anchor-name가 동일한 앵커가 여러 개 있으면 어떻게 되나요?

위치가 지정된 요소가 중복되고 각 일치 항목에 연결됩니다.
오답입니다.
위치가 지정된 요소는 문서의 첫 번째 요소에 연결됩니다.
오답입니다.
위치가 지정된 요소가 문서의 마지막 요소에 연결됩니다.
정답입니다.
위치가 지정된 요소가 가장 가까운 앵커에 연결됩니다.
오답입니다.