프론트엔드 개발자가 될거야./css 라이브러리

[react][typeScript][styled-component] hover시 svg 이미지 색깔 바꾸기

정니정은니 2023. 2. 8. 15:32

이미지는 png, jpg, svg 등 여러 확장자를 가진다. 

나는 그동안 png를 많이 썼는데

header의 icon 이미지를 hover 했을 때 hover 이벤트로 색상을 변경해 주어야 할 때

png를 쓰면 color를 변경할 수 없어서 이미지를 바꿔줘야하는데 이 방법은 매우 비효율적이라는 생각이 들었다.

 

예를들어 이런 상황이다. 

바이낸스의 헤더

그래서 header의 이미지 중 hover 이벤트로 색상을 변경해주어야 하는 이미지는 svg로 바꾸어 주었다.

 

SVG ?

  • svg 파일은 픽셀로 이루어진 png 파일과는 다르게 라인과 곡선들로 이루어져 있다.
    이런 점에서 파일을 확대하거나 줄였을때 이미지가 깨지지 않고 그대로 선명함을 유지한다.
  • svg 파일은 값을 조작 할 수 있기 때문에
    js를 이용해서 svg 아이콘의 색상을 변경하거나 애니메이션을 적용시킬 수도 있어서
    이미지 파일을 원하는 스타일에 맞게 변경이 가능하다.
  • svg 파일 사이즈는 기본적으로는 작은 편에 속한다.
    그렇지만 이미지가 복잡해질수록 크기가 커지거나 속도 저하를 일으킨다.

즉, 로고, 아이콘 또는 단순화된 이미지는 svg로 하는 것이 적절하다!

 

 

styled-component, typeScript에 svg 적용하기

 

svg의 색상은 path의 fill 속성에 의해 색상이 변경된다.

우리는 이 fill 속성의 색을 변경시켜주면 된다.

 

- styled-component

const SVG = styled.svg<{ isHover: boolean }>`
  fill: ${(props) =>
    props.isHover
      ? 'blue'
      : 'black' };

  &:hover {
    fill: 'blue' ;
  }
`;

- props 전달

    <li
      onMouseOver={() => setIsHover(true)}
      onFocus={() => setIsHover(true)}
      onMouseOut={() => setIsHover(false)}
      onBlur={() => setIsHover(false)}
    >
      <SVG
        isHover={isHover} // isHover값 전달해주기
        width="16"
        height="16"
        viewBox="0 0 16 16"
        fill="none"
        xmlns="http://www.w3.org/2000/svg"
      >
        <g clipPath="url(#clip0_369_6410)">
          <path d="M14.2609 9.3913V14.2609H1.73914V9.3913H0.347839V14.2609V15.6522H1.73914H14.2609H15.6522V14.2609V9.3913H14.2609Z" />
          <path d="M9.39137 0.347824H6.60876V1.73913H9.39137V0.347824Z" />
          <path d="M12.174 7.30434H9.39139V2.43478H6.60878V7.30434H3.82617L8.00008 12.8696L12.174 7.30434Z" />
        </g>
        <defs>
          <clipPath id="clip0_369_6410">
            <rect
              width="15.3043"
              height="15.3043"
              fill="white"
              transform="translate(0.347839 0.347824)"
            />
          </clipPath>
        </defs>
      </SVG>
    </li>

 

- 전체코드

import React, { useState } from "react";
import styled from "styled-components";

function DownloadLi() {
  const [isHover, setIsHover] = useState(false);

  return (
    <li
      onMouseOver={() => setIsHover(true)}
      onFocus={() => setIsHover(true)}
      onMouseOut={() => setIsHover(false)}
      onBlur={() => setIsHover(false)}
    >
      <SVG
        isHover={isHover}
        width="16"
        height="16"
        viewBox="0 0 16 16"
        fill="none"
        xmlns="http://www.w3.org/2000/svg"
      >
        <g clipPath="url(#clip0_369_6410)">
          <path d="M14.2609 9.3913V14.2609H1.73914V9.3913H0.347839V14.2609V15.6522H1.73914H14.2609H15.6522V14.2609V9.3913H14.2609Z" />
          <path d="M9.39137 0.347824H6.60876V1.73913H9.39137V0.347824Z" />
          <path d="M12.174 7.30434H9.39139V2.43478H6.60878V7.30434H3.82617L8.00008 12.8696L12.174 7.30434Z" />
        </g>
        <defs>
          <clipPath id="clip0_369_6410">
            <rect
              width="15.3043"
              height="15.3043"
              fill="white"
              transform="translate(0.347839 0.347824)"
            />
          </clipPath>
        </defs>
      </SVG>
    </li>
  );
}

export default DownloadLi;

const SVG = styled.svg<{ isHover: boolean }>`
  fill: ${(props) =>
    props.isHover
      ? 'blue'
      : 'black' };

  &:hover {
    fill: 'blue' ;
  }
`;