툴팁이나 드롭다운 메뉴를 배치할 때는 페이지의 다른 요소와 상대적으로 배치하는 것이 좋습니다. 절대 위치 지정을 사용하여 이 효과를 달성하는 방법이 있었지만, 더 복잡한 요구사항의 경우 이전에는 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-area
및 anchor()
함수의 두 가지 포지셔닝 방법을 제공합니다.
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 end
은 position-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: bottom
는 position-area: bottom span-all
와 동일하며, 위치가 지정된 요소는 앵커 아래에 있고 포함 블록의 전체 너비를 사용할 수 있습니다.
반면 키워드가 축을 명확하게 나타내지 않으면 반복됩니다. position-area: start
은 start 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 |
물리적 키워드는 앵커의 특정 측면에 해당하지만 설정 중인 배치된 요소의 인셋과 동일한 축에서만 사용할 수 있습니다. 예를 들어 |
측면 | inside , outside |
예를 들어 |
논리 | start , end , self-start , self-end |
논리적 키워드는 |
비율 | 0~100% |
백분율 값은 지정된 축에서 앵커의 시작부터 끝까지 축을 따라 배치된 요소를 배치합니다. |
이 예에서는 지정된 축에서 항상 시작부터 끝까지 백분율 값이 적용되는 방식을 보여줍니다.
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()
은 앵커의 너비를 반환합니다. 물리적 키워드 width
및 height
또는 논리적 키워드 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-block
및 flip-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-block
및 flip-inline
을 @position-try
대체 옵션에 추가하여 변형을 만들 수 있습니다.
#positioned-element {
position-try: --menu-below, flip-inline --menu-below;
}
위의 예에서 브라우저는 다음 단계를 따르며 오버플로되지 않는 솔루션을 찾는 즉시 중지합니다.
- 요소는 앵커의 오른쪽 하단에
position-area: end
로 배치됩니다. - 이 값이 오버플로되면
--bottom-span-right
라는 맞춤 대체 옵션으로 요소가 배치됩니다. 이 옵션은position-area: bottom span-right
로 요소를 배치하고 아래에 추가 여백을 둡니다. - 이 값이 오버플로되면 요소가
flip-inline --bottom-span-right
로 배치됩니다.flip-inline --bottom-span-right
는 맞춤 대체 옵션을flip-inline
와 결합하며, 이는 기본적으로position-area: bottom span-left
입니다. - 이 값이 오버플로되면
--use-alternate
맞춤 대체 옵션을 사용하여 요소가 배치되며, 이 옵션은 완전히 다른 앵커 아래에 요소를 배치합니다. - 이 값이 오버플로되면 오버플로가 발생한다는 것을 알고 있더라도 요소가
position-area: end
를 사용하여 원래 배치로 되돌아갑니다.
대체 주문
기본적으로 초기 위치가 오버플로되면 브라우저는 오버플로되지 않는 위치를 찾을 때까지 position-try-fallbacks
의 각 옵션을 시도합니다. position-try-order
를 사용하여 이 동작을 재정의하여 각 대체 옵션을 테스트하고 지정된 축에서 공간이 가장 많은 옵션을 사용할 수 있습니다.
논리적 키워드 most-block-size
및 most-inline-size
또는 실제 키워드 most-height
및 most-width
를 사용하여 축을 지정할 수 있습니다.
position-try-order
및 position-try-fallbacks
은 position-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
가 동일한 앵커가 여러 개 있으면 어떻게 되나요?