본문 바로가기

FrontEnd

[번역] css z-index 잘 사용하기

반응형

중첩 오버레이가 있는 컴포넌트들이 많은 화면을 개발하다보면, 금방 z-index를 유지보수하기 어려워 집니다.

z-index를 잘 유지보수하는 방법을 알아봅시다.

원문 링크 : 

https://www.smashingmagazine.com/2021/02/css-z-index-large-projects/

 

Managing CSS Z-Index In Large Projects — Smashing Magazine

Wrangling z-index values is a difficult task for many developers. Here is an easy-to-implement mini-framework based on existing conventions that brings clarity and confidence to working with z-index.

www.smashingmagazine.com

우리는 추상화와 규칙을 사용하여 까다롭고 오류가 발생하기 쉬운 부분을 숨겨
동일한 작업을 수행해야 하는 모든 사람이 더 쉽게 수행할 수 있도록 할 수 있습니다.
  • 특정 z-index값의 용도
  • 새로운 z-index값 선언에 사용할 숫자
  • 원하지 않게 스택 간 요소가 침범하는 현상 방지

일반적인 솔루션

 특정 값의 용도를 정해놓고 활용하는 것입니다 (ex Bootstrap)

$zindex-dropdown:       1000;
$zindex-sticky:         1020;
$zindex-fixed:          1030;
$zindex-modal-backdrop: 1040;
$zindex-modal:          1050;
$zindex-popover:        1060;
$zindex-tooltip:        1070;
  • 이 sass 변수명은 간단해 보이나, 지금 작업하는 컴포넌트가 무엇인지 혼란스러운 시점이 옵니다.
  • 값이 1000부터 시작하여 10씩 증가하는 규칙에 대한 의문이 듭니다
    • 1020은 어디갔죠? 버그인가요?
    • 1000보다 작은 값은 왜 안쓰죠?
    • 왜 1000부터 시작하나요?
    • 왜 10을 증분으로 사용하나요?

좀 더 좋은 방법을 찾아봅시다.


새로운 솔루션

마법같은 숫자를 피하고, 모든 팀원들이 자신있게 z-index를 새로 만들 수 있도록 하는 것이 목표입니다.

"사용하기 쉽게"라는 것은 애매하기에 후순위로 둡니다.

이를 위해 아래 문제들을 해결합니다.

  • 사람들은 종종 임의로 큰 z-index 값을 선택합니다.
  • z-index 버그 수정으로 인한 z-index 버그가 발생합니다.
  • z-index간 관계는 추적이 어렵습니다.

z-index를 위한 의미있는 문법

사람들이 종종 임의로 큰 z-index 값을 선택하는 한 가지 이유는,
사람들이 아래에 깔고자 하는 요소의 z-index 값을 모르기 때문입니다.
동적하는 임의의 높은 값을 찾으면 최적의 값을 찾는 대신 그대로 둡니다.
 
z-index: 9999;
 

이러한 매직 넘버를 피하는 방법은 명명된 상수를 사용하는 것입니다.
우리는 CSS-IN-JS를 사용하기에 JS를 사용하지만, css 변수나 전처리기 변수를 사용해도 됩니다.

export const backdrop = 0;
export const openButton = 1;
export const dropdown = 2;

 이제 css에는 의미만 남아있으며 실제 값은 숨겨집니다.

css`
  z-index: ${backdrop};
`;
  • 원래 값을 쉽게 찾을 수 있고
  • 상수 간 관계를 쉽게 찾을 수 있습니다.
더 개선할 수 있는 부분이 있습니다.
우리는 z-index가 작동하는 방식을 통해 이러한 값이 서로 관련되어 있음을 알고 있으므로
상수를 변경하여 더 명확하게 만들 수 있습니다.
export const backdrop = 0;
export const openButton = backdrop + 1;
export const dropdown = openButton + 1;

간단한 산수로 이전 상수를 이용해 다음 상수를 만듭니다.
좀 더 문장처럼 읽히도록 유틸리티 상수를 추가합니다.

const base = 0;
const above = 1;

export const backdrop = base;
export const openButton = above + backdrop;
export const dropdown = above + openButton;
이제  z-index: ${dropdown};는 z-index : ${above + openButton}; 이렇게도 잃을 수 있습니다.
(“The dropdown is above the open button.”)
이 방법은 상수를 추가하는것도 더 쉽게 해줍니다.
export const backdrop = base;
export const openButton = above + backdrop;
export const dropdown = above + openButton;
export const closeButton = above + dropdown; // new

값을 삭제하는 것도 쉽지만 여기에 종속된 다른 값을 업데이트해야 한다는 점을 기억해야 합니다.
JavaScript linter는 이를 쉽게 찾아줍니다.

 

이제 스택 버그도 찾기 쉬워집니다. 관계 측면에서 파악할 수 있기 때문입니다.

export const backdrop = base;
export const dropdown = above + backdrop;
export const openButton = above + dropdown;
export const closeButton = above + dropdown; // ???

이제 뭔가 문제가 생겼음을 쉽게 알 수 있습니다. openButton과 closeButton이 충돌하게 생겼군요

이럴때 도움이 되는 것은 다른 항목 아래에 항목을 배치하는 유틸리티 상수 입니다.
위와 아래가 섞이는 것을 피하기 위해 아래는 음수 값에만 사용해야 한다는 규칙을 만들었습니다.

const base = 0;
const above = 1;
const below = -1;

export const backdrop = below + dropdown;
export const dropdown = below + button;
export const button = base;

지금까지 만든 시스템의 핵심은,
모든 z-index 값은 필요한 만큼만 크며 동적으로 선택되기 때문에 값이 실제로 무엇인지는 신경 쓰지 않아도 됩니다.
다른 쌓인 요소에 어떤 영향을 미칠지 확신을 가지고 값을 삭제하고 추가할 수도 있습니다.

하지만 12개 정도의 z-인덱스 상수로 생기자 좀 혼란스러워지기 시작합니다.


쌓임 맥락으로 구조화하기

이는 개념적으로 scoping과 유사합니다.

JS 모듈, 컴포넌트, atomic design, BEM 은 모두 해당 문제를 풀기 위한 도구입니다.

각 소프트웨어 컴포넌트가 독립적으로 진화할 수 있도록 해줍니다.

 

BEM에서 영감을 받아 만든 포맷은 z<Context><Element>와 같은 템플릿입니다.
  • z 부분은 z-인덱스 선언에 사용된다는 사실을 나타내는 접두사입니다.
  • <Context>는 쌓임 맥락 명을 위한 부분입니다.
    • BEM의 블록과 유사합니다
    • Styled Component의 컴포넌트명과 동일합니다
      • 예외는 HTML 스택 컨텍스트 입니다.
  • <Element>는 쌓임 맥락에 배치할 특정 요소를 위한 부분입니다.
    •  BEM의 요소와 유사합니다.

아래 링크를 확인하시면, 해당 규칙을 이용해 페이지를 구성한 모습을 볼 수 있습니다.

https://codepen.io/smashingmag/pen/xxEvepz

 

Managing CSS Z-Index in Large Projects Demo

...

codepen.io

styled-components가 아닌 다른 방법들은 아래 레포지토리에서 확인하세요

check out this repository

 

GitHub - sfrieson/managing-css-z-index-in-large-projects: Code to accompany the Managing CSS Z-Index in Large Projects article i

Code to accompany the Managing CSS Z-Index in Large Projects article in Smashing Magazine - GitHub - sfrieson/managing-css-z-index-in-large-projects: Code to accompany the Managing CSS Z-Index in L...

github.com

// Utils
const base = 0;
const above = 1; // use this for all values above the base
const below = -1; // and this for all values below the base

// Page Layout
export const zLayoutNavigation = above + base;
export const zLayoutFooter = above + base;
export const zLayoutModal = above + zLayoutNavigation;
export const zLayoutPopUpAd = above + zLayoutModal;

// NavMenu
export const zNavMenuBackdrop = below + base;
export const zNavMenuPopover = above + base;
export const zNavMenuToggle = above + zNavMenuPopover;

이제 상수가 쌓임 맥락(컴포넌트) 별로 구성되어 있으므로,

  • 값 간의 관련을 쉽게 알 수 있습니다
  • 새 값을 쉽게 만들 수 있습니다.
    • 수정, 삭제도 쉽게 할 수 있습니다.
    • 쌓임 맥락 외부에서는 의미없는 값이라는 것을 쉽게 알 수 있기 때문입니다.

해당 방법이 해결해주지 않는 것

쌓임 맥락이 정확하게 어떻게 형성되고 있는지는 직접 파악해야 합니다.

  • 새로운 쌓임 맥락이 어디에서 형성되고 있나요?
  • 중간에 새로운 쌓임 맥락이 끼어들어 있지 않나요?
  • z-index가 어떤 쌓임 맥락에서 설정되고 있나요?

따라서 해당 방법을 적용하기 전에, 쌓임 맥락을 명확하게 파악하세요!


 

반응형