본문 바로가기

프론트엔드

backdrop-filter, box-shadow 크로스 브라우징하기

  • 키워드: backdrop-filter, box-shadow, pseudo-element, nested-element, cross browsing
  • 상황
    1. 아무런 효과가 없던 기존의 Header 배경을 backdrop-filter와 box-shadow를 이용하여 꾸미고자 한다.
      기존 Header(흰색), Sub Menus(회색)
      원하는 결과(blur 처리와 아래쪽 box-shadow)
    2. 윗 줄의 흰색 배경(Header)과 아랫줄의 회색 배경(Sub Menus)에 각각 backdrop-filter와 box-shadow를 적용해야했는데, 그 과정에서 Chrome/Safari css 오류가 생겼다.
      오류 발생 과정과 해결법을 설명하고자 한다.
  • 해결 과정
    1. 먼저 Header와 SubMenu에 각각 새로운 background-color, backdrop-filter, box-shadow를 적용해본다.
        // header.module.scss
      .header {
        background-color: rgba(#ffffff, 0.8);
        backdrop-filter: saturate(180%) blur(10px);
        box-shadow: rgb(2 1 1 / 10%) 0 5px 20px -5px;
      }
      
      .subMenus {
        background-color: rgba(250, 251, 252, 0.9);
        backdrop-filter: blur(10px);
        box-shadow: rgb(2 1 1 / 10%) 0 5px 20px -5px;
      }


    2. 여기서 발생하는 첫번째 버그는 크롬에서 SubMenu에 backdrop-filter blur가 제대로 작동하지 않는 것이다.
      아래 줄 SubMenu에 backdrop-filter가 적용되지 않은 모습

      DOM에서 .header element 아래에 .subMenus element가 위치해있다. 즉 subMenus는 header의 nested element(child element) 이다.
      Chrome 브라우저에서는 nested element의 backdrop-filter CSS가 제대로 동작하지 않는 버그가 있다고 한다.
      (https://stackoverflow.com/questions/60997948/backdrop-filter-not-working-for-nested-elements-in-chrome)

      이 버그를 해결하기 위해서는 부모의 backdrop-filter CSS를 해제해야하며, 이는 부모 element에서 pseudo-element를 사용함으로써 해결할 수 있다.
        .header {
        &::before {
          content: '';
          z-index: -1;
          position: absolute;
          left: 0;
          top: 0;
          width: 100%;
          height: 100%;
          background-color: rgba(#ffffff, 0.8);
          backdrop-filter: saturate(180%) blur(10px);
        }
        box-shadow: rgb(2 1 1 / 10%) 0 5px 20px -5px;
        ...
      }

      &::before { content: ''; }를 이용하여 의사 요소를 만들고, 기존 background-color와 backdrop-filter css를 의사 요소에 적용시킨다. 그리고 position, left, top, width, height 속성을 이용하여 원래의 header와 똑같은 영역을 차지하도록 만든다.

      의사 요소를 사용하면 backdrop-filter가 부모-자식간에 중첩된 것이 아니므로 버그를 비껴갈 수 있다.
      Chrome Browser에서 정상적인 backdrop-filter

      이제 Chrome 브라우저에서 header와 subMenus의 배경이 모두 흐리게 적용된다!

    3. 하지만 header를 사파리 브라우저에서 확인하면 또 다른 버그가 나타난다.
      header와 subMenus 사이에 글자가 보이는 현상

      header와 subMenus 사이 공간에만 blur가 적용되지 않는 이상한 현상이었다. 원인을 알 수 없어 CSS를 이리저리 삭제해보았는데, subMenus의 box-shadow를 삭제했을 때만 버그가 해결되었다(blur가 제대로 동작함).

      디자이너분이 주신 css를 따로 그려보니, box-shadow가 위 아래로 모두 spread 되고 있었다.
      기존 box-shadow

      nested element에서 box-shadow와 backdrop-filter 영역이 겹치면 버그가 일어나는 것으로 추론하고, box-shadow가 아래로만 퍼지도록 값을 수정한다.
      y-offset과 spread-radius를 변경하여 아래로만 퍼지도록 함

      이제 Safari 브라우저에서도 정상 동작한다!
       
      Safari Broswer에서 정상적인 backdrop-flter, box-shadow


    4. modern broswers에도 CSS 버그가 많이 남아있다는 것을 알게 되었으니, 더 꼼꼼하게 크로스 브라우징을 해야겠다.