AI 기술을 서비스에 적용하면서 이 같은 스타일의 UI 요소를 자주 접한다. 단색이 아닌 그라데이션으로 테두리을 그리는 방식인데, 마치 AI가 끊임없이 변화하고 있다는 인상을 받았다.
처음엔 '그냥 이미지를 배경에 깔고 그 안에 흰 배경을 가진 요소를 두었겠거니' 싶었다. 최근 회사 코드리뷰 중에 운좋게 구현체를 발견했는데, 궁금증이 풀려 반가웠다.
어떻게 구현했는지 단계적으로 살펴보자.
1단계: 간단한 상자
간단한 상자를 하나 만든다.
.gradient-border {
border: 2px solid #ddd;
border-radius: 4px;
padding: 8px 16px;
}
- border → 테두리 두께, 스타일, 색
- border-radius → 모서리를 둥글게
- padding → 콘텐츠와 테두리 사이의 간격 (내부 여백)
결과: 회색 테두리와 내부 여백이 생김.
2단계: 그라데이션 배경을 넣고 테두리를 투명으로
linear-gradient() 는 두 개 이상의 색이 점진적으로 변화하는 선형 그라데이션을 만드는 함수다. 예를 들어 linear-gradient(red, green) 은 빨간색에서 시작해 초록색으로 변하는 그라데이션을 만들 것이다.
배경 이미지에 linear-gradient() 함수를 이용하면 그라데이션 배경을 연출할 수 있다.
.gradient-border {
border: 2px solid transparent; border-radius: 4px;
padding: 8px 16px;
/* 그라데이션으로 배경이미지 지정 */ background-image: linear-gradient(to right, pink, cyan);}
- background-image: linear-gradient() → 요소 전체에 그라데이션을 배경으로 채움
- border: transparent → 테두리를 투명으로 만들어, 컨텐츠와 패딩 영역의 그라데이션 그림을 테두리 영역까지 확장
결과: 테두리를 포함한 요소 전체가 그라데이션 배경으로 채워짐.
3단계: 내부를 흰색으로 덮는 레이어
테두리 영역만 그라데이션을 남기고, 컨텐츠와 패딩 영역은 흰색으로 바꿀 차례다.
background-image는 콤마를 이용해 여러 배경을 지정할 수 있는데, 먼저 지정한 값이 가장 위에서부터 쌓이는 구조다. 이를 이용해 흰 배경을 하나 더 쌓았다.
.gradient-border {
border: 2px solid #ddd;
border-radius: 4px;
padding: 8px 16px;
/* prettier-ignore */
background-image: /* 위 레이어: 내부를 흰색으로 덮음 */ linear-gradient(white, white), /* 아래 레이어: 실제 그라데이션(테두리로 보일 것) */ linear-gradient(to right, pink, cyan);}
- background-image: linear-gradient(), linear-gradient() → 첫번째 항목인 흰 색이 가장 위에 그려짐 (그라이데이션을 가림)
결과: 흰색과 그라데이션 배경 (그라데이션은 아래 가려진 상태)
4단계: 레이어 별로 자르기
두 레이어의 크기가 같아서 가장 위에 있는 흰색 레이어만 노출된 상태이다. 노출된 흰색 레이어의 테두리를 잘라낼 수 있다면, 뒤에 가려진 그라데이션이 그만큼 보일 것이다.
background-clip 은 배경을 잘라 크기를 조절하는 속성이다. 배경 이미지를 두 레이어로 지정했듯이, 배경을 자르는 속성도 순서대로 두 레이어에 적용할 수 있다.
.gradient-border {
border: 2px solid #ddd;
border-radius: 4px;
padding: 8px 16px;
background-image: linear-gradient(white, white), linear-gradient(to right, pink, cyan);
/* 각 배경 레이어에 대한 clip 지정 */ background-clip: padding-box, border-box;}
- background-clip: padding-box, border-box → 맨 위 흰색 레이어를 패딩 영역까지 자름. 뒤에 그라데이션 레이어는 테두리 영역까지 자름
결과: 그라데이션 경계선
5단계: 그라데이션 미세 조정
background-origin은 배경을 그릴 때 기준 위치를 정하는 속성이다. 기본 값은 padding-box로써, 패딩과 컨텐츠 영역을 기준으로 배경을 그린다.
그라데이션 배경도 이 패딩 박스를 기준으로 그리는데, 그러다보니 노출된 경계선 영역을 만나면 다시 그라데이션을 시작한다. 어색하게 보인다.
.gradient-border {
border: 2px solid #ddd;
border-radius: 4px;
padding: 8px 16px;
background-image: linear-gradient(white, white), linear-gradient(to right, pink, cyan);
/* 각 배경 레이어에 대한 clip 지정 */
background-clip: padding-box, border-box;
/* 배경의 기준을 보더 박스로 설정 */ background-origin: border-box;}
- background-origin: border-box → 테두리, 패딩, 컨텐츠 영역을 기준으로 배경을 그림
background-clip은 어디까지 잘라낼지를 정하고, background-origin은 어디를 기준으로 그릴지를 정하는 속성이다.
결과: 자연스러운 그라데이션 테두리 완성!
정리
- 기본 박스 만들기: 테두리와 패딩을 가진 상자를 만든다.
- 그라데이션 배경 입히기: border를 투명으로 두고, 요소 전체에 linear-gradient()로 배경을 채운다.
- 흰색 레이어 추가하기: 여러 배경을 겹쳐서, 흰색 배경을 가장 위에 올린다.
- background-clip으로 자르기: 흰색 레이어는 패딩 영역까지만, 그라데이션 레이어는 보더 영역까지 남기고 잘라낸다.
- background-origin으로 기준 맞추기: 테두리까지 배경을 그리도록 설정해, 자연스러운 그라데이션 경계선을 만든다.
즉, background-image, background-clip, background-origin 세 가지 속성을 조합해 테두리 영역만 남기고 내부는 흰색으로 덮는 기법이다. 덕분에 별도의 이미지 리소스 없이 CSS만으로 구현할 수 있다.
최종 코드는 이렇다.
.gradient-border {
border: 2px solid #ddd;
border-radius: 4px;
padding: 8px 16px;
/* 그라데이션으로 배경이미지 지정 */
/* prettier-ignore */
background-image:
/* 위 레이어: 내부를 흰색으로 덮음 */
linear-gradient(white, white),
/* 아래 레이어: 실제 그라데이션(테두리로 보일 것) */
linear-gradient(to right, pink, cyan);
/* 각 배경 레이어에 대한 clip 지정 */
background-clip: padding-box, border-box;
/* 배경의 기준을 보더 박스로 설정 */
background-origin: border-box;
}