• 스크롤 앵커링: 더보기 버튼이 이상했'었'던 이유 (overflow-anchor)

    2020. 11. 22.

    by. 나나 (nykim)

    320x100

     

    프롤로그

    왜 제목이 저러냐면요... 얼마 전까지 ‘더보기’ 버튼이 생각과는 다르게 동작한 적이 있‘었’습니다.

     

     

     

    위와 같이 더보기 버튼을 클릭하면 그 위로 아이템을 추가하는 형식의 UI였는데,
    이상하게 버튼이 고정된 채로 버튼 위에서 새로운 아이템이 추가됐었거든요.

     

    기획: "더보기 버튼을 누르면 추가 영역이 아래에 펼쳐지는 게 아니라 위로 올라가는 느낌이 들어요."
    디자인: "그러게요. 버튼은 고정이고 내용이 위에서 열리는 형식 같은데... 밑으로 열리게 가능한가요?"
    UI개발: ????

     

    확인해보니까 다른 브라우저에선 해당 현상이 없고,

    Chrome 브라우저에서만 버튼 또는 a 태그와 같은 포커스가능 요소를 클릭한 경우 해당 현상이 발생했습니다.

    또, 돔 추가뿐만 아니라 display나 max-height 변경으로 숨김 처리 해제하는 경우에도 발생했고요.

     

    '난 이런 설정 넣은 적 없는데?!' 싶어서 당황했었는데요,
    다행히도 overflow-anchor: none 이라는 속성을 넣어 해결해 줄 수 있었습니다.

    알고보니 '스크롤 앵커링'이란 기능 때문이었습니다.

     

    버튼에 스크롤이 앵커링⚓️됐기 때문에, 버튼이 화면 밖으로 움직이자 스크롤이 그에 맞춰 움직인 것입니다.

    그래서 마치 아이템이 버튼 위에서 생기는 것처럼 보였던 거죠.

     

    구글에 검색해보면 Chrome 84부터 이런 현상이 발생한 것으로 보입니다. (Chrome 84는 2020년 7월 14일에 릴리즈)

     

    어... 정말로 저런 현상이 있었는데... 진짜인데... ㅠ.ㅠ
    좀 더 찾아보고 글 쓰면 좋겠다는 생각에 초안만 저장하고 포스팅을 미루다가,
    얼마 전 크롬이 업데이트 해서 더 이상 안 써줘도 되는 속성이 됐더라고요.

     

    ㅎㅎㅎㅎㅎㅎㅎ?

     

     

    아래 예제에서 맨 아래의 더보기(もっと見る) 버튼을 눌러도 딱히 큰 이상은 발견할 수 없을 거에요. (2020/11/22 기준)

     

    See the Pen もっと見るボタン by ryo_hisano (@ryo_hisano) on CodePen.

     

    출처: https://zenn.dev/nontan/articles/0cd8ea48bdf05faf1c26

     

     

    그래서 결국 없는 내용에 대한 글을 쓰고 있던 게 되어버렸습니다..... 😭
    아쉽긴 하지만 배운 게 있으니까 과거형으로라도 포스팅 해봅니다.

     

    할 일은... 미루지 말자... 

     

     

     


     

     

     

    스크롤 앵커링

    overflow-anchor: none라는 다소 생소한 이 속성은 스크롤 앵커링 기능을 비활성화 시키는 데 사용합니다.
    스크롤 앵커링? 그게 뭐죠?

     

    등장 배경

    웹의 강점 중 하나는 점진적 로딩입니다. 로딩이 다 끝날 때까지 기다리지 않더라도 그동안 콘텐츠를 사용할 수가 있죠.
    하지만 로딩이 완료되면서 보고 있던 콘텐츠가 아래로 밀린다는 문제가 있었습니다.

     

    아래의 비디오 예시를 살펴보세요.

    기사 위쪽에 있던 이미지가 뒤늦게 로드되면서 읽고 있던 기사가 아래로 밀려나버린 상황입니다.

     

     

     

     

    보고 있던 콘텐츠를 밀어내고 다른 요소가 비집고 들어온다면 사용자 경험이 영 좋지 않겠죠.
    이렇게 뷰포트 밖에서 일어난 변화에 방해를 받아 사용자의 주의가 분산되는 경우가 종종 있었습니다.


    광고를 포함한 iframe을 스크립트로 삽입하거나 느린 네트워크 환경에서 크기가 정해져 있지 않은 이미지를 불러오는 경우가 그 예입니다.

    게다가 모바일 환경에서는 디스플레이가 작아서 더욱 거슬리는 문제였는데요,

    이러한 문제를 해결하고자 나타난 것이 바로 스크롤 앵커링 기능입니다.

     

     

     

     

    앵커링이 하는 일

    스크롤 앵커링은 레이아웃이 변경되더라도 문서를 보고 있는 사용자의 시야를 안정적으로 유지될 수 있도록 해줍니다.
    아래 예시를 통해 스크롤 앵커링이 UX를 얼마나 향상시키는지 볼 수 있습니다.

    각 영역을 스크롤 하면 1초 후 상단에 초록색 박스가 생기는데, overflow-anchor 속성이 있으면 방해되지 않도록 스크롤이 조절됩니다.

     

    See the Pen overflow-anchor by Chris Coyier (@chriscoyier) on CodePen.

     

    출처: https://css-tricks.com/almanac/properties/o/overflow-anchor/

     

     

    이 기능은 돔 노드를 선택해 ‘앵커 노드(Anchor Node)’라고 하고, 앵커 노드의 위치를 추적하며 그에 따른 스크롤 옵셋을 조정합니다.
    앵커 노드를 주시하고 있다가 새로운 요소의 등장(돔 추가, display 처리 등)으로 위치가 바뀌면 알아서 스크롤을 앵커 노드에 맞춰 줍니다.

     

    그렇다면 이 멋진 기능을 어떻게 쓰면 되나요?

     

    사실... 아무 것도 안 해도 됩니다!

    이 기능을 지원하는 브라우저라면 기본적으로 스크롤 앵커링이 활성화 상태입니다.
    기본적으로 활성화 상태지만 필요 없을 때 해제 처리할 수 있는, 이른바 옵트 아웃 속성입니다.

     

    이 속성은 한 번 해제하면 하위 요소에서 다시 설정하는 것은 불가합니다.
    즉, document에서 overflow-anchor: none으로 옵트 아웃하면 문서 내 어떤 요소에서도 overflow-anchor: auto로 옵트 인 할 수 없습니다. (참고: MDN)

     

     

    그래서 저 버튼 위로 아이템이 보여지는(정확히는 버튼에 스크롤이 앵커링 되는) 현상을 overflow-anchor:none으로 막았던 거죠.

     

     

    히스토리

    그렇다면 이 스크롤 앵커링은 언제부터 우리 곁에 스리슬쩍 있었던 걸까요?

     

    이 스펙은 WICG(Web Incubator Community Group)에서 제안된 내용입니다.

    WICG는 W3C의 커뮤니티 그룹으로, 복작복작 토론하면서 아이디어를 제안하고 발전시켜나가는 곳입니다.

    이렇게 제안된 내용이 W3C 워킹 그룹을 거쳐 권고 표준안이 되는 걸 목표로 합니다. (참고: WICG 소개페이지)

     

    2016년 Chrome 51부터 flag로 활성 가능한 기능으로 추가되었고,
    2017년 Chrome 56부터 기본 활성화 상태가 되었습니다.
    생각보다 오래 전에 나온 스펙이었네요!

     

    참고로 Firefox는 66부터, Opera는 43, Edge는 79부터 지원합니다.
    IE는 (당연히) 지원되지 않고, Safari도 아직 지원 전입니다.
    상세한 브라우저 지원 여부는 Can I use...에서 볼 수 있습니다.

     

    이후 W3C TAG의 검토를 받아 CSSWG 스펙으로 마이그레이션되었습니다.
    앞으로는 W3C의 워킹그룹이 공식적인 문서를 게시하는 스펙이 됐다는 거죠.

     

    2020년 2월에 스크롤 앵커링에 대한 첫번째 공식 초안(First Public Working Draft)이 게시되었고,

    현재 CSS Scroll Anchoring Module Level 1의 초안 문서(Working Draft)에서 관련 내용을 찾아볼 수 있습니다.

     

    정리하면...

     

      ▪︎  WICG에서 스크롤 앵커링 논의

      ▪︎  Chrome 51에서 실험적 기능(chrome://flags)으로 추가됨

      ▪︎  Chrome 56에서 기본 기능으로 추가됨

      ▪︎  CSSWG 스펙이 됨

      ▪︎  FPWD 게시

      ▪︎  WD 업데이트 중

     

    이렇게 볼 수 있겠습니다. 꽤 오래 전에 나온 거였는데도 몰랐네요 🤔

     

     

     

     

    크롬 업데이트

    그래서 스크롤 앵커링 기능이 더보기 버튼이 잠깐 이상했었던’ 것과 무슨 상관이 있을까요? 옛날엔 안 그랬던 것 같은데...
    왜냐면 저 속성은 WD 단계라서 언제든 바뀔 수 있기 때문입니다. 브라우저는 저걸 받아들일 수도 있고 아니다 싶으면 뺄 수도 있죠.

     

    처음 언급했던 것처럼 Chrome 84부터 저런 현상이 있었기에 업데이트 내용을 찾아봤는데 스크롤 앵커링과 관련된 커밋이 있었습니다.

     

    This patch updates the scroll anchoring selection to consider
    - focused element
    - find-in-page active match results

    This is updated due to changes in the spec:
    https://github.com/w3c/csswg-drafts/commit/396d0cf9dc9585bd77a611f18124770ac8ce704b

     

    ‘포커스된 요소’와 ‘페이지 내 일치하는 검색 결과’가 앵커 선택에 있어 우선 순위가 되도록 했다는 내용입니다.
    그리고 이는 아래 링크의 스펙 문서가 업데이트됐기 때문이라고 써놓았네요.

     

    문서 업데이트 내용을 살펴보면 최초안(First Public Working Draft, FPWD)과 비교해 추가된 내용이 있음을 알 수 있습니다.
    바로 앵커 노드를 선택하는 알고리즘에 ‘viable candidate(고려할 만한 후보)’와 ‘priority candidate(우선 후보)’ 개념을 추가한 것입니다.

     

     

    css-scroll-anchoring-1/Overview.bs

     

    새롭게 들어간 내용은 아래와 같습니다.

     

    아래 조건을 모두 만족하는 경우, 요소 C는 스크롤링 박스 S를 위한 앵커가 될 수 있다.
    이를 고려할 만한 후보(viable candidate)라고 부른다.

    - C가 non-atomic inline*이 아닐 것. (is not a non-atmoic inline)
    - C가 S 내에서 부분적 또는 완전히 보여질 것
    - C가 S의 하위요소일 것
    - S 내에서 C 또는 C의 상위요소가 서브트리에서 제외되지 않을 것 (display:none, position:fixed, overflow-anchor:none 등이 아닐 것)
    일부 요소는 앵커 선택의 우선 후보(priority candidates)로 고려된다.

    1. 문서 내 포커스된 영역의 돔 앵커(DOM anchor)
    2. user-agent 알고리즘의 현재 활성화된 페이지 내 일치하는 검색 결과를 포함하는 요소** (일치하는 항목이 여러 요소에 걸쳐있는 경우, 첫번째 요소만 고려함)

     

    따라서 크롬은 스펙 업데이트에 맞춰, 포커스된 요소가 앵커 선택의 우선순위에 오도록 설정하는 내용을 추가했다는 뜻이 됩니다.

     

    그래서 <button>이나 <a> 태그, 또는 tabindex 속성을 갖는 요소들이 스크롤 앵커링 기능에 따라 뷰포트에 고정되었던 거죠.

    이는 사용자가 상호작용한 요소를 계속 볼 수 있다는 장점이 있지만, 위와 같이 '더보기' 버튼 위로 새로운 요소를 불러와야 하는 경우 동작이 어색해 진다는 문제점도 있었습니다.

     

    크롬이 해당 내용을 넣었다 뺀 것도 그런 이유가 아닐까 추측해 봅니다.

     

     

    *아토믹 인라인(atmoic inline)은 <image>처럼 replaced된 인라인 요소(인라인이지만 인라인 블럭처럼 보여짐),
    또는 inline-block / inline-table의 서식 맥락을 갖는 인라인 레벨을 가리킵니다. (참고: stack overflow)
    원문에서 not a non-atomic inline으로 꼬아서 설명했는데, 이게 정확히 어떤 대상을 가리키는지 다소 애매해 그대로 옮겼습니다.
    정확한 내용 아시는 분은 도움! 부탁드립니다 🙏

    **원문: An element containing the current active selected match of the find-in-page user-agent algorithm.

     

     

     

     


     

     

     

     

    에필로그

    사실 이전까지는 W3C의 Working Draft를 보면서 '초안? 저런 것까지 봐둬야 할까?'라는 생각이었는데요,
    이번에 문서를 보면서 표준안이 어떻게 나타나 발전하는지 흐름을 살펴볼 수 있어서 좋았습니다.
    브라우저가 표준 이전 단계의 내용을 어떻게 받아들이는지 엿볼 수도 있었고요. 나중에 웹 표준을 좀 더 자세히 알아봐도 좋을 것 같네요.
    크롬 개발의 커밋 기록을 살펴보는 것도 재미있고 신선한 충격이었어요.

     

    이게 좀 불편했던 기능이라 언젠가 수정되지 않을까 내심 생각은 했지만...
    설마 글을 쓰는 도중에 업데이트가 될 줄이야.....

     

    © kakao Corp.

     

    그래도 이런 과정들을 통해 더 나은 웹을 만드는 거구나, 라는 전보다 넓은 시야를 가질 수 있었던 좋은 기회였습니다.
    (영어의 중요성도 깨달음 🤮)

     

     

     

    참고

    overflow-anchor (MDN)

    Scroll Anchoring (W3C Editor's Draft)

     

    728x90

    댓글