Please enable JavaScript to view the comments powered by Disqus.

linear-gradient 속성에 transition 적용하기

블로그를 호스팅하고 있는 Vercel 서비스의 웹사이트를 방문했다가 멋진 CSS 기술을 보게 되었다. 텍스트에 linear gradient를 사용해서 컬러를 입히고, 거기에 일정한 간격을 두고 차례대로 transition 효과를 주고 있었다.

vercel_linear_gradient_text.gif 3개의 단어와, 컬러, 애니메이션 효과만으로 서비스의 핵심을 아주 효과적으로 설명해주고 있지 않은가?

개발 도구로 확인해 보니 GIF 이미지나 canvas를 사용한 효과는 아니었고 HTML span 태그로 추가한 텍스트와 CSS로 구성되어 있었다. 단순히 linear gradient를 사용한 텍스트라면 모르겠는데, 애니메이션까지 적용되어 있으니 한번 카피해 보면 좋겠다는 생각이 들었다.

Linear gradient를 사용한 텍스트

CSS linear-gradient 속성은 기본적으로 백그라운드 컬러를 지정하기 위한 속성이다. 시작점, 종료점에 지정할 2개의 색상이 기본적으로 필요하며 중간 지점에 들어갈 컬러는 더 많이 추가할 수도 있다. 색이 변화하는 각도도 지정할 수 있는데, 예를 들어 to left 값은 좌에서 우로 컬러가 변화한다.

background-image: linear-gradient(to right, red, blue); /* 왼쪽 끝은 빨강, 오른쪽 끝은 파랑 */
background-image: linear-gradient(red, blue); /* 각도가 생략되면 to bottom */
background-image: linear-gradient(to right, red, yellow, blue); /* 중간 컬러를 넣을 수 있다. */
background-image: linear-gradient(45deg, red, yellow 40%, blue) /* 각도, 컬러의 위치도 지정 가능하다. */

그리고 linear-gradient는 기본적으로 background-image 속성에 지정하는 값이다. background 속성에도 할당될 수 있지만 background 는 여러가지 백그라운드 관련 속성(background-color, background-repeat, background-position 등)을 조합해서 사용하는 값이므로 별도로 지정하는 편이 CSS 버그를 방지하는데 도움이 된다.

백그라운드 컬러, 이미지를 텍스트에 적용하기

background-clip CSS 속성을 사용하면 배경이 컨텐츠 박스 중에서 어디까지 차지할지 결정할 수 있다. box-sizing 속성에 사용하는 border-box, content-box가 아닌 text 속성을 사용하면, 백그라운드 컬러, 이미지가 텍스트 위에만 입혀진다. 그리고 텍스트 컬러는 투명으로 지정해야 한다.

background-color: linear-gradient(to right, red, blue);
-webkit-background-clip: text;
color: transparent;

이렇게 하면 텍스트에 그래디언트 컬러가 적용된 멋진 텍스트를 표현할 수 있게 된다.

linear gradient에 transition 효과 설정

CSS transition 속성으로 엘레멘트의 위치, 크기, 컬러 등이 변경될 때 부드러운 전환 효과를 넣을 수 있다. 하지만 일반적인 백그라운드 컬러와 달리, linear-gradient 를 사용한 백그라운드 컬러에는 transition 속성의 timing function(ex. linear) 값이 적용되지 않는다. 다시 말해 중간 단계 없이 색깔이 빨강에서 파랑으로 바로 바뀌어버리는 것이었다.

그래서 여기서는 트릭을 사용해야 한다.

  • 부모 요소(ex. div, span)에 텍스트를 추가한다.
  • 부모 요소의 의사 요소(pseudo-element, ex. ::before)에 CSS 속성들을 추가한다.

    • content 속성에 부모 요소에 입력한 것과 동일한 텍스트를 입력한다.
    • linear-gradient를 사용해 컬러를 입힌다.
    • absolute 포지션을 사용해 부모 요소의 텍스트와 크기, 포지션이 완전히 겹치도록 만든다.
    • opacity 값을 0으로 둔다.
    • transition 속성에 opacity 값이 변할 때 전환 효과가 발생하도록 설정한다.
    • z-index 값은 부모 요소의 값보다 커야 한다. 그래야 의사 요소의 opacity 값을 1로 변경했을 때 의사 요소가 먼저 보이게 된다.
<span class="gradientText">HTML</span>
.gradientText {
  position: relative;
  z-index: 1;
  background-image: linear-gradient(to right, #000, #000); 
  -webkit-background-clip: text;
  color: transparent;
}

.gradientText::before {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  z-index: -1;
  content: "HTML"; 
  background-image: linear-gradient(to right, #007cf0, #00dfd8); 
  transition: opacity 0.5s linear;
  opacity: 0;
  -webkit-background-clip: text;
}

/* 이 클래스를 추가하면 텍스트에 컬러가 추가된 의사 요소의 텍스트가 보이게 된다. */
.transitionOn::before {
  opacity: 1;
}

정리하면 의사 요소에 부모와 똑같은 텍스트를 지정하고 컬러를 입힌 후, opacity 값으로 전환 효과를 주는 것이다. 의사 요소의 opacity 값이 0에서 1로 바뀌는 과정에서 마치 부모 요소의 텍스트 컬러가 전환되는 것처럼 보이는 효과를 준다.

자바스크립트로 transition 실행

이제 스타일은 준비가 되었으니 마크업을 추가하고 자바스크립트로 setTimeoutsetInterval을 조합해 클래스를 일정한 주기에 맞춰 붙였다 떼었다 하는 작업만 해주면 된다.

결과물

References