svg size 조절하기

너무 깊은 내용은 다루지 않는다. 사실 나도 모른다. 적어도 개발자가 svg를 다룰 때 알면 도움이 될만한 정도로 내용을 정리해 보려고 한다.

일반적으로 래스터 이미지의 크기를 변경하는 경우 어떻게 하면 될까?

img 태그의 속성으로 width와 height를 지정해도 되고, css selector를 통해 스타일 값을 부여해줘도 된다.

<div class="png">
  <h2>png</h2>
  <img src="./src/나비.png" width="200" height="auto" ></img>
  <img src="./src/나비.png" class="png__img-navi" ></img>
</div>

위 코드의 결과는 아래와 같다.

하지만 내가 다룰려는 요소가 svg라면 조금 다르게 결과가 나올 수도 있다. 왜냐하면 svg의 크기 조정은 단순 이미지의 크기 조정보다는 더 많은 크기 조절 옵션을 제공하기 때문에 조금 복잡하다.

위 이미지의 svg을 다운로드하여 width와 height값을 넣어줬다. 과연 제대로 동작할까?

<svg width="200" height="auto" viewBox="0 0 1981.355 1651.144" ...>
...
</svg>

거의 똑같이 나오는거 같다. 오 쉽네~

근데 실수로 height를 날려버렸다. 빠른 핫 로딩으로 인해 화면에 반영이 되었는데 똑같은 느낌이다.

실제 크기를 비교해 봐도 똑같은걸 알 수 있다. 달라졌다면 차라리 마음이 편했을 텐데 찜찜하다.

이것에 대한 비밀은 아래에서 다뤄 보겠다.

그전에 크기 조정을 하기 위해 svg의 두 가지 개념에 대해 먼저 살펴보자.

뷰포트(viewport)

뷰포트는 svg의 가시 영역으로 해당 요소의 너비와 높이를 의미한다. svg나 css를 통해 width와 height 특성을 설정할 경우 이 뷰포트 영역이 바뀐다고 생각하면 된다. 쉽게 말해 영화관의 스크린 영역(가시 영역)이라고 생각하자. 영화관 스크린보다 큰 영상을 비추면 화면에 안 보이게 된다. 똑같이 뷰포트 밖으로 엘리먼트가 삐져나간다면 볼 수 없다.

뷰박스(viewbox)

뷰박스는 좌표와 가로, 세로의 비율을 결정하는 svg의 특성이다(x, y, width, height). 뷰박스는 뷰포트를 비추고 있는 현미경이라고 생각하자. 뷰포트와 뷰박스가 동일하다면 원래 크기와 동일한 엘리먼트가 보일 것이다. 반면에 뷰포트가 뷰박스보다 작다면 축소되어 보이고, 뷰포트가 뷰박스보다 크다면 확대되어 보이게 된다.

예제를 좀 더 단순화해서 가져와봤다.

<svg width="50" height="50" viewBox="0 0 50 50" ...>
  <!-- 나는 코드로 기본 도형밖에 못그린다.. 실제 필요할때는 디자이너분들이 툴로 알아서 그려주시니 안심하시길 -->
  <rect x="0" y="0" rx="4" ry="4" width="50" height="50" style="fill:#dddddd;" />	
</svg>

위 svg는 뷰포트와 뷰박스를 정확하게 일치시켰다. 따라서 svg는 시각적으로 차지되는 부분에 정확하게 그려지게 된다.

축소하고 싶다면,

<svg width="50" height="50" viewBox="0 0 100 100" ...>

확대하고 싶다면,

<svg width="50" height="50" viewBox="0 0 25 25" ...>

viewBox에 앞에 두 인자가 x,y 라고 했는데 조금 더 자세히 표현하자면, 왼쪽 꼭짓점의 x 좌표와 y 좌표라고 생각하면 된다. (pinning을 제어한다)

확대하면서 꼭지점 이동,

<svg width="50" height="50" viewBox="25 25 25 25" ...>

여기서 중요한 점은 viewBox만 설정해서는 안된다는 점이다. viewBox를 설정하면서 viewBox의 가로(width), 세로(height) 비율(=뷰포트 비율)도 꼭 같이 설정해 주는 것이 좋다. 만약 뷰박스의 가로, 세로 비율을 설정하지 않는다면 100%를 기준으로 되기 때문에 엄청(?) 큰 svg 이미지가 렌더링 될 수도 있다.

만약 뷰포트와 뷰박스의 비율이 다르다면, 뷰포트의 길이가 긴 부분(높이건 넓이 건) 기준으로 svg는 가운데 위치하게 된다.

왜 svg는 뷰포트의 중심에 위치할까?

이 이유는 바로 preserveAspectRatio 속성의 기본값 때문에 그렇다.

<svg preserveAspectRatio="xMidYMid meet" ... >

값의 x와 Y부분에는 Min, Mid, Max가 접미사로 붙는다. 이 속성의 기본값은 위에 지정한 것과 같다. 해석해 보면 "x축에서 가운데(Mid), Y축에서 가운데(Mid)로 이동하고, 그 다음 잘림이 생기지 않을 정도로 크게 만들어라(meet)"이다.

meet의 경우 "잘림이 생기지 않을 정도로 크게 만들어라"라는 명령을 담당하고 있는데, 이것을 "꽉 채우고 잘림을 허용한다"라는 의미의 slice로 대체할 수도 있다. (developer.mozilla.org/en-US/docs/Web/SVG/Attribute/preserveAspectRatio)

그렇다면 래스터 이미지처럼 뷰포트에 맞추어 크기를 조정하려면 어떻게 해야할까?

일반적으로 래스터 이미지를 다룰 때 위 속성같이 무언가를 이용하여 가로세로 비율을 고려하진 않는다. svg 또한 해당 뷰포트에 맞춰 크기를 조정하고 싶다면 preserveAspectRatio 속성을 끄면 된다.

참고 자료

Last updated