마우스를 가져가면 도움말 표시

사용자는 컨텍스트를 완전히 변경하지 않고도 추가 관련 정보를 볼 수 있기를 기대합니다. 사용자가 추가 정보에 관심이 있을 때 도움말을 표시하면 용어의 정의를 제공하거나, 아이콘 전용 버튼이 수행할 작업을 명확히 하거나, 추가 양식 필드 안내를 제공하는 데 유용할 수 있습니다.

도움말 만들기

<div> 또는 기타 의미론적으로 적절한 요소에 popover="hint" 속성을 추가하여 필요한 동작이 있는 팝오버를 만들 수 있습니다. 사용자가 도움말을 열면 다른 popover="hint" 도움말은 숨겨지지만 auto 또는 manual 도움말은 숨겨지지 않습니다. 또한 중첩된 도움말 닫기도 처리합니다.

또한 가벼운 닫기 동작을 제공하므로 사용자가 팝오버 외부를 클릭하거나 포커스를 맞추면 팝오버가 닫힙니다.

도움말 요소에는 고유한 값이 있는 id 속성이 있어야 합니다.

<!-- MANDATORY: The tooltip container `<div>` must have a `popover` attribute.
     the value of `"hint"` ensures it can be "light dismissed". -->
<div popover="hint" id="tooltip">Tooltip content</div>

사용자가 <a> 또는 <button> 요소에 마우스를 가져가거나 포커스를 두어 추가 정보에 관심을 표현합니다. 요소에는 도움말의 id 속성과 일치하는 interestfor 속성이 있어야 합니다.

<!-- The `interestfor` attribute can be applied to a `<button>` element: -->
<button interestfor="tooltip">Tooltip trigger</button>

<!-- The `interestfor` attribute can also be applied to an `<a>` element: -->
<a interestfor="tooltip" href="">Tooltip trigger</a>

트리거에는 트리거와 상호작용하여 추가 정보를 사용할 수 있음을 나타내는 시각적 표시기가 있어야 합니다.

interestfor에 기본 제공되는 접근성 기능

interestfor를 사용하면 브라우저가 보조 기술 연결을 처리합니다.

  • 암시적 시맨틱스: popover="hint"가 있는 타겟은 암시적 최소 역할 tooltip를 얻습니다. role="tooltip"를 직접 설정하지 마세요.
  • 암시적 연결: 브라우저는 타겟이 일반 텍스트인 경우 aria-describedby를 통해, 타겟에 상호작용 콘텐츠가 포함된 경우 aria-details를 통해 소스 요소를 타겟과 암시적으로 연결합니다. 트리거에 aria-describedby 또는 aria-details를 추가하지 마세요.
  • 상호작용 콘텐츠: 필요에 따라 연결이 aria-details로 전환되므로 타겟에 상호작용 콘텐츠 (예: '관심분야 카드' 내 링크)를 포함할 수 있습니다.

접근성 제약조건 (WCAG 1.4.13)

interestfor가 위의 시맨틱스를 처리하더라도 구현은 여전히 WCAG 1.4.13(마우스 오버 또는 포커스 시 콘텐츠)을 충족해야 합니다(MUST).

  • 닫기 가능: 사용자는 포인터 마우스 오버 또는 키보드 포커스를 이동하지 않고도 도움말을 닫을 수 있어야 합니다 (예: Escape 키 누르기). 네이티브 popover 속성은 이 바인딩을 자동으로 관리합니다.
  • 마우스 오버 가능: 포인터가 도움말 콘텐츠 위로 이동할 수 있어야 하며 도움말이 사라지지 않아야 합니다. 이렇게 하면 확대 도구를 사용하는 사용자가 도움말 텍스트를 안전하게 읽을 수 있습니다.
  • 지속성: 도움말은 마우스 오버 또는 포커스 트리거가 삭제되거나, 사용자가 명시적으로 닫거나, 콘텐츠가 더 이상 유효하지 않을 때까지 계속 표시되어야 합니다.

도움말 위치 지정

도움말은 CSS 앵커 포지셔닝을 사용하여 배치됩니다. interestfor를 사용하여 도움말을 열면 트리거 요소가 자동으로 팝오버의 암시적 앵커가 됩니다.

네이티브 앵커 위치 지정을 지원하는 최신 브라우저에서는 트리거에 anchor-name를 정의하거나 툴팁에 position-anchor를 정의할 필요가 없습니다. position-area를 사용하여 암시적 앵커를 기준으로 도움말을 직접 배치하고 position-try-fallbacks를 사용하여 충돌 뒤집기를 처리할 수 있습니다.

[popover] {
  /* Implicit anchor from interestfor: no anchor-name or position-anchor needed */
  position-area: top;
  position-try-fallbacks: flip-block;
  margin: unset;
}

대체 전략

관심 인보커의 대체 및 브라우저 지원

관심 요소 호출자는 NPM의 interestfor 폴리필 패키지를 사용하여 조건부로 폴리필해야 합니다. CDN을 사용하는 것보다 폴리필을 번들로 묶는 것이 좋습니다.

필수: HTMLButtonElement.prototype에서 interestForElement 속성을 확인하여 기능을 감지하고 네이티브 지원이 누락된 경우에만 폴리필을 로드합니다.

<script type="module">
  if (!HTMLButtonElement.prototype.hasOwnProperty("interestForElement")) {
    // CDN link only used for example, prefer bundling.
    await import("https://unpkg.com/interestfor@latest");
  }
</script>

CSS 폴리필 주의사항

폴리필을 사용할 때는 네이티브 의사 클래스 및 속성 지원 부족을 고려하여 CSS API가 약간 변경됩니다.

  • 의사 클래스: 폴리필은 실제 :interest-source 및 :interest-target 의사 클래스를 정의할 수 없으므로 대신 .interest-source 및 .interest-target 클래스를 적용합니다. 필수: :is()와 결합하여 네이티브 상태와 폴리필 상태를 모두 지원합니다.
/* Styles to apply when the effect is being previewed */
:is(:interest-source, .interest-source) { /* ... */ }
:is(:interest-target, .interest-target) { /* ... */ }
  • CSS 속성: interest-delay, interest-delay-start, interest-delay-end의 경우 폴리필은 모든 브라우저에서 맞춤 속성을 직접 읽을 수 없으므로 CSS 변수를 사용해야 합니다.
/* Adjust the start and end delay for interest invokers */
[interestfor] {
  --interest-delay-start: 0.2s;
  interest-delay-start: var(--interest-delay-start);
  --interest-delay-end: 0.1s;
  interest-delay-end: var(--interest-delay-end);
}

Popover의 대체 및 브라우저 지원

Popover API는 대부분 점진적 개선이지만, 최상위 레이어 승격, 가벼운 닫기, popovertarget 호출과 같은 정의 동작에는 CSS 전용에 상응하는 기능이 없습니다. 이전 브라우저에는 폴리필이 필요하며, 폴리필을 제공하지 않으려면 수동 대체가 필요합니다.

폴리필: 이전 브라우저에서 popover 속성을 지원하려면 조건부로 @oddbird/popover-polyfill를 로드합니다. 필수: HTMLElement.prototype에서 popover 속성을 확인하여 기능을 감지하고 네이티브 지원이 누락된 경우에만 폴리필을 로드합니다. 무조건 로드하지 마세요.

번들러 또는 가져오기 맵 사용:

// MANDATORY: Feature detect 'popover' on HTMLElement.prototype.
if (!("popover" in HTMLElement.prototype)) {
  import("@oddbird/popover-polyfill");
}

번들러가 없는 경우 <script type="module"> 내의 CDN에서 가져옵니다.

<script type="module">
  if (!("popover" in HTMLElement.prototype)) {
    import("https://unpkg.com/@oddbird/popover-polyfill@latest/dist/popover.min.js");
  }
</script>

스타일 지정 주의사항: 폴리필은 실제 :popover-open 의사 클래스를 정의할 수 없으므로 대신 .\:popover-open 클래스를 적용합니다. 필수: :is() 또는 :where()를 사용하여 두 가지를 결합합니다. 그렇지 않으면 :popover-open가 없는 브라우저에서 전체 규칙을 삭제합니다.

[popover]:is(:popover-open, .\:popover-open) {
  display: block;
}

또는 폴리필이 없는 기존 대체 기능의 경우 position: fixed를 사용하고 getBoundingClientRect()를 통해 좌표를 수동으로 계산하거나, 사용 사례에 적합한 경우 inset: auto를 사용하여 기본 위치 지정에 의존합니다.

popover-polyfill는 popover를 지원하지만 popover="hint"를 지원하지 않는 브라우저에서 힌트 동작을 폴리필하지 않습니다. 이러한 브라우저의 경우 포커스를 통해 열린 도움말은 마우스 오버를 통해 두 번째 도움말이 열릴 때 열린 상태로 유지될 수 있습니다.

앵커 위치 지정을 지원하지 않는 브라우저를 지원하려면 @oddbird/css-anchor-positioning 폴리필을 사용하면 됩니다. 또는 @supports를 사용하여 대체 위치를 지정할 수 있습니다.

기존 브라우저 지원을 위해 @oddbird/css-anchor-positioning 폴리필을 사용하는 경우 폴리필은 팝오버에서 암시적 앵커 또는 position-area를 지원하지 않습니다. 트리거에 anchor-name를 명시적으로 설정하고, 팝오버에 position-anchor를 설정하고, position-area 대신 anchor() 인셋 함수를 사용하여 배치합니다.

<!-- MANDATORY: Conditionally install the anchor positioning polyfill -->
<script type="module">
  if (!("anchorName" in document.documentElement.style)) {
    await import("https://unpkg.com/@oddbird/css-anchor-positioning");
  }
</script>
button[interestfor="tooltip-attrs"] {
  /* MANDATORY: Each trigger and popover pair must have a unique anchor name, referenced by `anchor-name` on the trigger and `position-anchor` on the popover. */
  anchor-name: --tooltip-attrs;
}
#tooltip-attrs {
  position-anchor: --tooltip-attrs;
  /* If using the anchor positioning polyfill with a popover, DO use `anchor()` functions, and not `position-area. */
  top: anchor(bottom);
  left: anchor(right);
  margin: unset;
}