개발 기술/개발 이야기

팝오버를 라이브러리 없이 웹 API로 구현하는 법, Popover API

by GicoMomg (Lux) 2023. 9. 17.

1. popover를 아시나요?

  • 팝오버는 도움말과 같이 요소에 대한 부연 설명을 창으로 표시할 때 주로 쓰이는데,
  • 아래 이미지는 Bootstrap의 popover 예시이다.


  • 이제까지 popover를 구현하기 위해 개발자가 처음부터 코드를 짜거나 라이브러리를 써야했다.
  • 하지만 2023년에 Popover API가 출시되면서, 별도의 라이브러리 없이 웹 API로 팝오버를 구현할 수 있게 됐는데 Popover API는 어떤 특징을 가지며 어떻게 사용하는 지 한 번 알아보자!



2. Popover API 알아보기

1) 특징

💡 2023년에 출시된 Popover API의 경우 아래와 같은 특징을 가진다.

  • 상위 레이어로 인식
    • 팝오버는 웹 페이지에서 별도의 레이어에 위치한다.
    • 그러므로 z-index를 설정하지 않아도 상위 영역에 표시된다.
  • ClickOutside 제공
    • 기본적으로 팝오버 영역 바깥을 클릭시 팝오버 창이 닫힌다.
  • 키보드 컨트롤 가능
    • 기본적으로 ESC키를 누르면 팝오버 창이 닫힌다.
  • 이벤트 제공
    • beforetoggle, toggle 이벤트를 제공하므로, 팝오버 동작시 특정 로직을 처리할 수 있다.
    • 단 이벤트는 실험단계(23.09.17 기준)이므로 해당 글에서는 자세히 설명치 않겠다.
    • 만약 이벤트에 대해 자세히 알고 싶다면, 공식문서를 확인해보자(링크)

2) 사용법

💡 팝오버를 사용하기 위해선 popover, id, popovertarget을 지정해야하는데,
HTML 속성으로 팝오버 띄우는 법, JS로 팝오버를 띄우는 법 2가지를 알아보자.

(1) HTML 속성으로 팝오버 띄우기

  • 우선, 팝오버 창으로 지정할 요소에 popover 속성와 id를 지정해준다.
<div id="my-popover" popover> <!-- this -->
  <p>팝오버 내용이 여기에 있겠죠?<p>
</div>

  • 그리고 팝오버 버튼의 popovertarget속성을 팝오버 창의 id 값으로 지정한다.
  • 이렇게 3가지 속성을 설정해주면 기본적인 팝오버 기능을 사용할 수 있다.
<button class="btn-popover" popovertarget="my-popover"> <!-- this -->
    팝오버창 열기
</button>

<div id="my-popover" popover>
  <p>팝오버 내용이 여기에 있겠죠?<p>
</div>

  • 아래 예시는 기본적인 팝오버이다.
  • 팝오버창 열기 버튼을 클릭할 때마다 팝오버창이 열렸다가 닫히는 걸 알 수 있다.

See the Pen Simple default popover(html) by KumJungMin (@kumjungmin) on CodePen.



(2) JS로 팝오버 띄우기

  • 팝오버는 HTML 속성으로 만들 수 있지만, JS로도 만들 수 있다.
  • 먼저 팝오버창 요소에 id값으로 접근하여 popover값을 지정한다.
const popover = document.getElementById("my-popover");

popover.popover = "auto"; // 기본값인 auto로 지정

  • 그 다음 팝오버 버튼(toggleBtn)의 popoverTargetElement을 팝오버창 요소(popover)로 설정하고,
  • popoverTargetAction은 기본값으로 설정하면 팝오버 기능을 쓸 수 있게 된다.
const btnPopover = document.querySelector(".btn-popover");

btnPopover.popoverTargetElement = popover;
btnPopover.popoverTargetAction = "toggle";  // 기본값인 toggle로 지정

  • 앞선 JS 코드를 사용하면 아래와 같이 팝오버 기능을 쓸 수 있게 된다.

See the Pen Simple default popover(js) by KumJungMin (@kumjungmin) on CodePen.



3) Popover API 활용해보기

(1) 팝오버창 닫기/열기 버튼을 만들고 싶을 때, popovertargetaction 조작하기

  • 버튼에 popovertarget을 지정하면, 팝오버창을 토글할 수 있는 요소가 된다.
  • 하지만 만약 버튼에 토글 기능이 아닌 팝업 닫기 혹은 열기 기능만 지정하고 싶다면, popovertargetaction를 조작해보자
popovertargetaction 값 기능
show 팝오버창을 표시한다.
hide 팝오버창을 숨긴다.
<button popovertarget="my-popover" popovertargetaction="hide">
  팝오버창 닫기
</button>

<button popovertarget="my-popover" popovertargetaction="show">
  팝오버창 열기
</button>

See the Pen popovertargetaction by KumJungMin (@kumjungmin) on CodePen.



(2) 키 동작시 팝오버창을 닫거나 열고 싶다면?

  • 만약 ESC키가 아닌 다른 키를 클릭했을 때 팝오버창을 열거나 닫고 싶다면, Popover API에서 제공하는 함수를 사용해보자!
  • hidePopover()로 팝오버창을 닫을 수 있고 showPopover()를 사용하면 팝오버창을 열 수 있다.
popover.hidePopover();
popover.showPopover()

  • 아래 예시에서 w키 클릭시 팝업창을 열고, q키 클릭시 팝업창을 닫도록 처리해보았다.
document.addEventListener('keypress', (e) => {
  if (e.key === 'q') popover.hidePopover();
  else if (e.key === 'w') popover.showPopover()
})

See the Pen popup api keypress by KumJungMin (@kumjungmin) on CodePen.



  • 만약 키 클릭시 팝오버창을 토글하고 싶다면, togglePopover(force)을 사용할 수도 있다.
  • 인자(force)에는 boolean값을 지정하는데, 값에 따라 초기 동작이 달라진다.
togglePopover(force);
force값 동작
true 팝오버가 초기에 숨겨져 있었다면 보여지게 된다.
만약 초기에 보여져 있었다면 아무 일도 발생하지 않는다.
false 팝오버가 초기에 보여져 있었다면 숨겨지게 된다.
만약 초기에 숨겨져 있었다면 아무 일도 발생하지 않는다.



(3) 팝업 바깥 클릭시, 팝업 닫기를 막고 싶을 때, popover속성 조작하기

  • Popover API에서는 팝오버창 바깥 영역을 클릭하면 팝오버창이 닫힌다.
  • 하지만, 팝오버창 바깥을 클릭했을 때 팝오버창을 계속 유지하고 싶다면, popovermanual로 바꿔보자.
popover 값 동작
auto(기본값) 팝오버창 바깥 클릭시 팝오버창이 닫힌다.
manual 팝오버창 바깥 클릭시 팝오버창이 닫히지 않는다.

See the Pen Basic manual popover with close button by KumJungMin (@kumjungmin) on CodePen.



(4) 팝오버창 바깥 영역을 스타일링하고 싶다면, ::backdrop 쓰기!

  • ::backdrop를 팝오버창 바깥 영역을 스타일링할 수 있는 CSS 선택자이다.
  • 아래 코드는 ::backdrop에 반투명한 색상이 지정한 모습이다.
#my-popover::backdrop {
  background: rgba(170, 170, 170, 0.6);
}

See the Pen popver styling backdrop by KumJungMin (@kumjungmin) on CodePen.



(5) 팝오버창의 위치를 조정하고 싶다면, anchor() 사용하기

  • 팝오버는 최상위 레이어 바로 아래에 있는 레이어(#top-layer)에 존재한다.
  • 그렇기 때문에 팝오버의 positionabsolute로 지정해도 버튼 기준으로 배치할 수 없다.


  • 이 경우에 우리가 사용할 수 있는 건 바로 CSS의 anchor 속성이다. (W3C 문서)
  • CSS의 anchor를 사용하면 특정 요소를 앵커 요소 기준으로 상대 위치시킬 수 있다.
  • 우선, 앵커가 될 요소에 id를 지정한다.(앵커가 된다는 건 위치 기준이 된다는 말)
  • 우리는 팝오버창을 버튼 기준으로 상대 위치시키고 싶기에 버튼을 앵커 요소가 된다.
<button id="btn-popover" popovertarget="my-popover"> <!-- 앵커 요소에 id 지정 -->
    팝오버창 열기
</button>

  • 그리고 팝오버창이 어떤 앵커를 기준으로 위치될 것인지 설정해야한다.
  • 팝오버창이 버튼 앵커를 기준으로 상대 위치되어야하기에 anchor 속성에 버튼 id값을 넣어준다.
<div id="my-popover" popover anchor="btn-popover"> <!-- 위치 기준이 되는 앵커 id 설정-->
  <p>팝업 내용이 여기에 있겠죠?<p>
</div>

  • 마지막으로 팝오버창이 앵커(버튼) 기준, 상단 중앙에 위치하도록 CSS를 수정해주면 된다!
#my-popover {
  /* 팝오버창의 위치를 앵커를 기준으로 설정 */
  bottom: calc(anchor(top));  /* 앵커 기준 상단 */
  left: anchor(center);       /* 앵커 기준 수평 중앙 */
  translate: -50% -10px;
}

  • 아래 예시는 앵커 기준으로 팝오버가 배치된 모습이다.
  • 단 앵커 기능은 23.09.17기준, 일부 브라우저만 호환되기에 polyfill을 사용해야했..따…ㅜ

See the Pen anchor styling by KumJungMin (@kumjungmin) on CodePen.




3. 마치며…

이번 시간에는 2023년에 출시된 Popover API에 대해 알아보았다.
Popover API는 웹 API로, 라이브러리 없이 팝오버를 구현할 수 있는 기능으로 별도의 레이어에 존재하며 ESC키 기능 등을 기본적으로 제공한다.

다만 Popover API의 경우 팝오버 버튼 기준으로 배치할 때는 anchor()를 사용해야 하는데, anchor()가 브라우저 호환성이 낮다는 단점이 있었다.
또한, 팝오버를 열 때 애니메이션을 주고 싶다면 :popover-open 선택자(링크)를 사용해야 하는데, 23.09.17 기준 실험 단계이기 때문에 현재로서는 아쉬운 점이 있다.
만약 Popover API를 사용할 계획이 있다면, :popover-openanchor()의 지원을 우선 확인한 후 적용하는 것이 좋을 것 같다.

반응형

댓글