Zeno ZENO
회사 개발일지 / 레거시 생존기 · 조회 3 · 좋아요 0

CSS로 커스텀 테두리(Border) 만드는 3가지 방법 (SVG, border-image)

border 속성의 한계를 극복하고 원하는 디자인의 커스텀 테두리를 만드는 방법을 소개합니다. MDN 기준 기본 border-style의 종류와 한계, 그라데이션 및 이미지로 테두리를 만드는 border-image, 그리고 가장 유연하지만 오류가 잦은 인라인 SVG background-image 활용법과 실무 해결책까지 완벽하게 가이드합니다.

SVG background-image로 점선 테두리 만드는 방법

파일 업로드 영역이나 드롭존 UI를 만들 때 단순히 border: dashed;를 사용하면 점선의 길이, 간격, 색상, 모서리 둥글기 등을 세밀하게 맞추기 어렵다.

이럴 때는 CSS의 background-image 안에 SVG를 직접 넣어서 점선 테두리를 그리는 방식을 사용할 수 있다.

1. 기본 예제 코드

.file-dropbox {
  flex: 1;
  gap: 1.3rem;
  border-radius: 0.4rem;
  overflow: hidden;
  background-color: #fff;

  background-repeat: no-repeat;
  background-position: center;
  background-size: 100% 100%;

  background-image: url("data:image/svg+xml,%3csvg width='100%25' height='100%25' viewBox='0 0 100 100' preserveAspectRatio='none' xmlns='http://www.w3.org/2000/svg'%3e%3crect x='2' y='2' width='96' height='96' fill='white' rx='4' ry='4' stroke='%23CDCDCD' stroke-width='4' stroke-dasharray='6 14' stroke-dashoffset='0' stroke-linecap='square' vector-effect='non-scaling-stroke'/%3e%3c/svg%3e");
}

위 코드는 흰색 배경에 #CDCDCD 색상의 점선 테두리를 그리는 예제다. border-radius와 SVG 내부의 rx, ry를 같이 맞춰서 모서리도 둥글게 처리했다.
(한 줄로 쓰셔야 합니다 url이 끊겨서.. 아니면 개행을 하셔야 합니다)

2. 왜 SVG를 background-image에 넣는가?

CSS의 기본 border-style: dashed;는 간단하지만 점선 간격을 원하는 만큼 정밀하게 조절하기 어렵다.

border: 4px dashed #CDCDCD;

위 방식은 간단하지만 점선 하나의 길이와 점선 사이의 공백을 직접 지정하기 어렵다. 반면 SVG를 사용하면 stroke-dasharray 속성으로 점선 패턴을 직접 정할 수 있다.

3. SVG 코드 안의 주요 속성

fill

fill은 사각형 안쪽 면의 색상을 의미한다.

fill='white'

이렇게 쓰면 박스 안쪽이 흰색으로 채워진다.

fill='none'

이렇게 쓰면 안쪽을 투명하게 비운다.

stroke

stroke는 테두리 선의 색상이다.

stroke='%23CDCDCD'

여기서 %23# 기호를 URL 안에서 사용할 수 있게 바꾼 값이다. 즉, %23CDCDCD는 실제로 #CDCDCD라는 뜻이다.

stroke-width

stroke-width는 테두리 선의 두께다.

stroke-width='4'

숫자가 커질수록 점선 테두리가 두꺼워진다.

stroke-dasharray

stroke-dasharray는 점선의 패턴을 정하는 속성이다.

stroke-dasharray='6 14'

이 코드는 6만큼 선을 그리고, 14만큼 비우는 패턴을 반복한다는 뜻이다.

  • 6 14 : 짧은 선, 넓은 공백

  • 8 12 : 조금 더 긴 선, 적당한 공백

  • 10 10 : 선과 공백이 같은 점선

stroke-linecap

stroke-linecap은 점선 조각의 끝 모양을 정한다.

stroke-linecap='square'

square는 점선 끝을 각지게 마감한다.

stroke-linecap='round'

round는 점선 끝을 둥글게 마감한다.

rx, ry

rxry는 SVG 사각형의 모서리 둥글기 값이다.

rx='4' ry='4'

CSS에서 border-radius: 4px;를 사용했다면, SVG 내부의 사각형에도 rx='4', ry='4'를 같이 넣는 것이 좋다.

4. # 기호를 왜 %23으로 바꾸는가?

SVG를 CSS의 url() 안에 직접 넣으면 해당 SVG 코드는 이미지 주소처럼 처리된다. 이때 # 기호를 그대로 쓰면 브라우저가 색상 코드가 아니라 주소의 특수 기호로 해석할 수 있다.

그래서 #%23으로 바꿔서 써야 한다.

#CDCDCD  →  %23CDCDCD
#FFFFFF  →  %23FFFFFF
#333333  →  %23333333

예를 들어 일반 CSS에서는 아래처럼 쓰지만,

color: #CDCDCD;

SVG를 background-image: url(...) 안에 넣을 때는 아래처럼 쓴다.

stroke='%23CDCDCD'

5. %25는 무엇인가?

SVG 코드 안에서 width='100%'처럼 퍼센트 기호를 써야 하는 경우가 있다. 그런데 이 코드가 url() 안에 들어가면 % 기호도 인코딩되어야 한다.

그래서 %%25로 바뀐다.

100%  →  100%25

즉, 아래 코드는 실제로 SVG에서 너비를 100%로 잡는다는 뜻이다.

width='100%25'

6. 테두리가 안 보이거나 안쪽에 생기는 이유

AD

제휴 광고 · 일부 링크는 수수료를 받을 수 있습니다

데이톡 - 매일 100만 회원과 새로운 인연

SVG의 stroke는 사각형 선의 중앙을 기준으로 그려진다.

예를 들어 stroke-width='4'라면 선이 안쪽으로 2px, 바깥쪽으로 2px 퍼진다.

그런데 사각형을 아래처럼 꽉 차게 그리면 문제가 생긴다.

<rect width='100%25' height='100%25' stroke-width='4' />

사각형이 SVG 영역을 이미 꽉 채우고 있기 때문에, 바깥쪽으로 퍼지는 2px 부분이 잘려서 안 보일 수 있다.

그래서 선 두께가 4라면 사각형을 안쪽으로 2만큼 넣어주는 방식이 안전하다.

<rect x='2' y='2' width='96' height='96' stroke-width='4' />

이렇게 하면 사각형이 SVG 영역 안쪽에 들어오므로 테두리가 잘리지 않는다.

7. viewBox와 preserveAspectRatio

아래 코드는 SVG의 기준 좌표계를 100 x 100으로 잡는다는 뜻이다.

viewBox='0 0 100 100'

그리고 아래 속성은 SVG가 박스 크기에 맞춰 가로세로로 늘어나도록 만든다.

preserveAspectRatio='none'

이 속성을 사용하면 박스가 가로로 길거나 세로로 길어도 SVG가 영역 전체를 채운다.

다만 SVG가 늘어나면서 선 두께까지 같이 늘어나는 문제가 생길 수 있다. 이때는 아래 속성을 추가하면 된다.

vector-effect='non-scaling-stroke'

이 속성은 SVG 크기가 변해도 선 두께가 같이 늘어나지 않게 막아준다.

8. url() 안에 주석을 넣으면 안 되는 이유

아래처럼 url() 내부에 CSS 주석을 넣으면 안 된다.

background-image: url("data:image/svg+xml,
  /* 여기 주석 넣으면 안 됨 */
  <svg>...</svg>
");

url() 안쪽은 CSS 코드가 아니라 이미지 주소 문자열로 처리된다. 그래서 CSS 주석을 넣으면 SVG 코드가 깨질 수 있다.

주석은 반드시 url() 바깥쪽에 작성해야 한다.

/*
  SVG 점선 테두리 코드
  stroke: 테두리 색상
  stroke-width: 선 두께
  stroke-dasharray: 점선 간격
*/
background-image: url("data:image/svg+xml,%3csvg ... %3e");

9. 최종 정리

SVG를 이용해 점선 테두리를 만들 때는 아래 내용을 기억하면 된다.

  • #%23으로 바꾼다.

  • %%25로 바뀐다.

  • stroke는 테두리 색상이다.

  • fill은 안쪽 배경색이다.

  • stroke-width는 선 두께다.

  • stroke-dasharray는 점선 간격이다.

  • rx, ry는 SVG 사각형의 모서리 둥글기다.

  • border-radiusrx, ry는 같이 맞추는 것이 좋다.

  • url() 안에는 CSS 주석을 넣으면 안 된다.

  • 선이 잘리면 x, y 값을 넣고 크기를 줄여야 한다.

10. 최종 코드

.file-dropbox {
  flex: 1;
  gap: 1.3rem;
  border-radius: 0.4rem;
  overflow: hidden;
  background-color: #fff;

  /*
  SVG 점선 테두리 설정

  fill: 안쪽 배경색
  stroke: 테두리 색상
  stroke-width: 테두리 두께
  stroke-dasharray: 점선 간격
  stroke-linecap: 점선 끝 모양
  rx, ry: SVG 사각형 모서리 둥글기
  */

  background-repeat: no-repeat;
  background-position: center;
  background-size: 100% 100%;

  background-image: url("data:image/svg+xml,%3csvg width='100%25' height='100%25' viewBox='0 0 100 100' preserveAspectRatio='none' xmlns='http://www.w3.org/2000/svg'%3e%3crect x='2' y='2' width='96' height='96' fill='white' rx='4' ry='4' stroke='%23CDCDCD' stroke-width='4' stroke-dasharray='6 14' stroke-dashoffset='0' stroke-linecap='square' vector-effect='non-scaling-stroke'/%3e%3c/svg%3e");
}

AD

'레거시 생존기' 카테고리의 다른 글

전체보기