본문 바로가기

프론트엔드

svg mask fill 속성은 white로 지정하기

  • 프로젝트: loplat UI
  • 키워드: svg, mask, fill
  • 상황
    1. 팀원분께서 IconButton이라는 컴포넌트를 개발하셨는데, 이상한 점이 있다고 하셨다.
      "svg에 border와 동일한 색상을 설정했는데 svg의 색상이 border색상보다 좀더 밝게 나타납니다."

    2.  실제로 확인해보니 border color와 svg fill 에 동일한 색상을 전달하지만, storybook 상에는 색상이 다르게 보이는 것을 확인했다.
        border-color: ${({ border }) => border.default};
      svg path {
        fill: ${({ text }) => text.default};
      }

      색상이 다르다
  • 해결 과정 
    1. 개발자도구로 확인한 결과, svg path에는 정상적으로 fill 속성이 채워져있었다.

      fill의 색상이 border와 동일했지만, svg path가 좀 더 연하게 보였다.

    2. element 탭을 눈여겨보던 와중에, 바로위에 <defs> tag가 있는 것을 발견했다.
      id="campaign_svg__a"
      defs 아래에도 path가 있었는데, css 선택자가 'svg path'였기 때문에 defs에 있는 path에도 fill 속성이 들어가있었다.

    3. 다시 svg 구조를 살펴보니 mask를 이용하여 svg icon을 그리고 있었다.
        <g transform="translate(2 2)" fill="none" fill-rule="evenodd">
        <mask id="campaign_svg__b__0mpvmuvoi" fill="#fff">
          <use xlink:href="#campaign_svg__a__0mpvmuvoi"></use> // defs 아래에 있던 path
        </mask>
        <g mask="url(#campaign_svg__b__0mpvmuvoi)">
          <path d="M-2-2h32v32H-2z"></path>
        </g>
      </g>
      Icon에 해당하는 path는 mask 아래 use를 통해 들어가있었고, '<path d="M-2-2h32v32H-2z"></path>' 라는 정사각형 path와 mask 를 조합해서 Icon을 그리고 있는 것이었다.
    4. svg mask(https://developer.mozilla.org/en-US/docs/Web/SVG/Element/mask)는 fill="white"일 때 mask가 덮고 있는 영역이 모두 보이고, fill="black" 일때는 mask가 덮고 있는 영역이 보이지 않게 된다.
      즉, 정사각형(d="M-2-2h32v32H-2z") 영역 중에서, Icon에 해당하는 path만 보이고 나머지는 보이지 않도록 mask가 작동해야한다.
      정사각형의 색상이 원래 원하던 색상이므로, Icon에 해당하는 path(즉, mask안에 있는 campaign_svg__a path) 의 fill 값은 'white'여야한다.
      하지만 현재는 모든 path의 색상이 빨간색(white와 black의 중간)이므로 원하던 색상보다 조금 연하게 보였던 것이다.(완전히 보이지도(white) 숨겨지지도(black) 않은 중간 상태)

    5. defs 아래에 있는 (mask용) path는 제외하고 g 태그 아래에 있는 path에만 원하는 색상을 적용하도록 수정했다.
      svg g > path {
        fill: ${({ text }) => text.default};
      }
    6. 이제 원하는대로 마스킹이 일어난다!