SVG Symbol
폰트 기반 아이콘의 대안——SVG 심볼 스프라이트를 사용하여 확장 가능한 다색 아이콘을 HTML에 직접 삽입합니다.
SVG 심볼 스프라이트란?
SVG 심볼 스프라이트는 여러 SVG 아이콘을 하나의 파일로 묶습니다. 각 아이콘은 고유한 id를 가진 <symbol> 요소 안에 정의됩니다. 아이콘을 사용하려면 <use href="#icon-id">로 참조합니다. 스프라이트는 한 번만 로드되고——인라인이나 외부 파일로——개별 아이콘은 페이지 어디서나 렌더링할 수 있습니다.
이것은 아이콘 폰트와 근본적으로 다른 접근법입니다. Unicode 코드 포인트를 폰트 글리프에 매핑하는 대신 네이티브 SVG 요소를 사용합니다. 각 아이콘은 완전한 SVG 기능을 유지합니다: 다색, 그라디언트, 필터, 세밀한 접근성 속성. 트레이드오프는 폰트 아이콘의 순수 CSS 접근법에 비해 마크업과 스타일링 규칙이 약간 더 복잡하다는 것입니다.
작동 원리
스프라이트 파일은 하나 이상의 <symbol> 요소를 포함하는 일반 SVG 문서입니다. 각 심볼은 자체 viewBox를 가진 독립적인 아이콘을 정의합니다:
<svg xmlns="http://www.w3.org/2000/svg" style="display:none">
<symbol id="icon-home" viewBox="0 0 24 24">
<path d="M3 12l9-9 9 9M5 10v10a1 1 0 001 1h3a1 1 0 001-1v-4..."/>
</symbol>
<symbol id="icon-search" viewBox="0 0 24 24">
<path d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"/>
</symbol>
</svg>
바깥 <svg>는 style="display:none"으로 숨겨져 페이지에서 공간을 차지하지 않습니다. 내부 심볼들은 참조되기 전까지 보이지 않습니다. 아이콘을 렌더링하려면 <use> 요소를 사용합니다:
<svg class="icon"><use href="#icon-home"></use></svg>
<svg class="icon"><use href="#icon-search"></use></svg>
폰트 기반의 color 속성 대신 fill과 stroke로 CSS에서 아이콘을 스타일링합니다:
.icon {
width: 24px;
height: 24px;
fill: currentColor;
stroke: none;
}
fill: currentColor를 사용하면 폰트 아이콘이 color 속성으로 작동하는 것과 유사하게, 아이콘이 부모 요소의 텍스트 색을 상속합니다.
심볼 vs 폰트 아이콘
- 다색 지원——각 경로가 자체 fill과 stroke를 가질 수 있음
- 각 아이콘이 실제 SVG 요소로 접근성이 더 우수
- Unicode 매핑 불필요——읽기 쉬운 이름으로 아이콘 참조
- 더 선명한 렌더링——폰트 힌팅 문제나 서브픽셀 아티팩트 없음
- 아이콘 각 부분을 독립적으로 애니메이션 가능
- 모든 SVG 기능 지원: 그라디언트, 필터, 클립 패스, 마스크
- 더 장황한 마크업 (
<svg><use>vs<i class="icon">) - CSS
color로 스타일링하기 어려움——fill/stroke필요 - 외부 스프라이트는 크로스 오리진 로딩 시 CORS 문제
- 압축 폰트 형식보다 총 파일 크기가 더 큼
- 아이콘 사용마다 HTML 용량이 더 큼
::before/::after가상 요소 지원 없음
로딩 전략
SVG 심볼 스프라이트를 페이지에 로드하는 세 가지 주요 방법이 있으며, 각각 다른 트레이드오프가 있습니다:
인라인 스프라이트
전체 스프라이트 SVG를 HTML <body>에 직접 붙여넣습니다. 가장 단순한 접근법입니다——CORS 문제 없음, 추가 HTTP 요청 없음. 심볼은 페이지의 모든 <use> 참조에 즉시 사용 가능합니다. 단일 페이지 애플리케이션이나 작은 아이콘 세트(50개 미만)에 가장 적합합니다.
외부 스프라이트
<use href="icons.svg#home">를 통해 스프라이트를 외부 파일로 로드합니다. HTML을 깔끔하게 유지하고 브라우저가 스프라이트를 페이지와 별도로 캐시할 수 있습니다. 그러나 CORS 문제가 있습니다: 스프라이트는 동일 오리진에서 제공되거나 서버가 적절한 Access-Control-Allow-Origin 헤더를 설정해야 합니다. Internet Explorer는 외부 <use> 참조를 지원하지 않으므로 IE 지원이 필요한 경우 svg4everybody 폴리필을 사용하세요.
JS 인젝션
fetch()로 스프라이트 파일을 로드하고 런타임에 DOM에 삽입합니다. 외부 스프라이트의 캐시 가능성과 인라인 스프라이트의 신뢰성을 결합합니다——삽입된 SVG가 문서의 일부가 되어 <use> 참조가 CORS 제한 없이 작동합니다. Bobcorn이 이 접근법을 생성합니다: 로드 시 모든 심볼을 가져와 등록하는 JS 파일입니다.
<!-- 생성된 JS 스프라이트 로드 -->
<script src="icons-symbol.js"></script>
<!-- 그 다음 일반적으로 사용: -->
<svg class="icon"><use href="#icon-home"></use></svg>
<svg class="icon"><use href="#icon-search"></use></svg>
JS 파일은 모든 <symbol> 정의를 포함하는 숨겨진 <svg> 요소를 만들어 문서 body에 추가합니다. 로드 후 아이콘 참조 방식은 인라인 방식과 동일합니다.
SVG 심볼을 사용하는 경우
프로젝트가 폰트 아이콘으로는 제공할 수 없는 기능을 필요로 할 때 SVG 심볼 스프라이트가 적합합니다:
- 다색 아이콘——아이콘이 두 가지 이상의 색, 그라디언트, 또는 단일 글리프 폰트로 표현할 수 없는 복잡한 채우기를 사용할 때
- 접근성이 최우선 과제——각 아이콘에
<title>요소와aria-label속성을 포함시켜 스크린 리더에 의미 있는 설명을 제공할 수 있음 - 아이콘 부분 애니메이션——아이콘 내의 개별 경로나 그룹을 애니메이션해야 할 때 (예: 설정 아이콘 안의 회전하는 톱니바퀴)
- SVG를 많이 사용하는 프로젝트——애플리케이션이 이미 인라인 SVG를 광범위하게 사용하여 심볼이 기존 아키텍처에 자연스럽게 맞는 경우
- 최고의 렌더링 선명도——폰트 힌팅이 작은 크기에서 정렬 문제를 일으킬 수 있습니다. SVG 심볼은 어떤 크기에서도 픽셀 완벽하게 렌더링합니다
폰트 아이콘을 유지하는 경우
폰트 아이콘이 더 나은 선택인 몇 가지 일반적인 시나리오가 있습니다:
- 대형 아이콘 세트 (200개 이상)——압축된 WOFF2 폰트 파일이 같은 수의 아이콘을 가진 SVG 스프라이트보다 훨씬 작음
- 모두 단색 아이콘——모든 아이콘이 단색이라면 폰트 아이콘이 트레이드오프 없이 가장 단순한 통합을 제공
- CSS 전용 통합——폰트 아이콘은 스타일시트 링크와 CSS 클래스만 필요하고 JavaScript나 추가 마크업이 없음
- 레거시 시스템——이미 아이콘 폰트를 사용하는 프로젝트는 전환을 정당화할 만큼 충분한 이익을 얻지 못함
- 가상 요소 지원——폰트 글리프로만 작동하는
::before또는::after가상 요소에 아이콘이 필요한 경우