HTML과 CSS만을 이용하여, 원형 그라데이션 테두리(Circle Gradation Border)을 표현하고 애니메이션(Animation)을 추가한 효과를 만들어 보자.
결과물 미리 보기
HTML 구성
HTML 요소들을 아래와 같이 구성한다.
<div class="container">
<h1>Circle Gradient Border Rotation</h1>
<div class="circle"></div>
</div>
Flexbox 레이아웃을 이용한 중앙정렬
스타일시트(CSS)의 플렉스박스(Flexbox) 레이아웃(Layout)을 아래와 같이 지정하여 컨테이너 요소(.container
)가 중앙정렬(수직 방향과 수평 방향 모두 중앙정렬) 되도록 한다.
body {
margin: 0;
padding: 0;
color: #efefef;
background-color: #333333;
}
.container {
display: flex;
flex-direction: column;
flex-wrap: wrap;
justify-content: center;
align-content: center;
height: 100vh;
}
타이틀 중앙정렬 및 테두리 추가
타이틀 수직 방향 중앙정렬을 위해 h1
요소에 플렉스박스(Flexbox) 레이아웃(Layout)을 적용하고 타이틀과 도형이 겹쳐 보이도록 위치(position
)를 절대좌표(absolute
)로 지정한다. left
속성과 transform
속성을 이용하여 타이틀을 수평 방향으로 중앙정렬한다. .circle
요소의 사이즈(width
, height
) 및 테두리(border
)를 적용한다.
/* ... 생략 ... */
.container h1 {
display: flex;
position: absolute;
left: 50%;
flex-direction: column;
justify-content: center;
width: 24rem;
height: 24rem;
margin: 0;
font: 100 3rem/1.2 "Helvetica Neue", Helvetica, Arial, sans-serif;
text-align: center;
transform: translateX(-50%);
}
.circle {
box-sizing: border-box;
width: 24rem;
height: 24rem;
border: 1px solid;
}
테두리 그라데이션 효과
스타일시트(CSS) image-image
속성의 linear-gradient
를 사용할 경우 테두리(border
)만 그라데이션(Gradation) 효과가 적용되는 것이 아니라 배경 전체에 그라데이션(Gradation)이 적용된다. 물론, image-image
속성의 linear-gradient
중첩 사용과 background-clip
속성 및 background-origin
속성들을 이용하여 테두리(border
)만 그라데이션(Gradation)이 적용된 것처럼 효과를 낼 수 있지만 내부가 색이나 그라데이션(Gradation)으로 채워지게 된다.
위에서 스타일시트(CSS) .circle
선택자에 적용한 테두리 속성 border
대신, box-shadow
속성의 X offset 및 Y offset을 사용하여 테두리를 표현한다.
/* ... 생략 ... */
.circle {
box-sizing: border-box;
width: 24rem;
height: 24rem;
box-shadow:
0 -1px 0 0 rgba(255, 64, 0, 1), /* Top Border */
1px 0 0 0 rgba(255, 192, 0, 1), /* Right Border */
0 1px 0 0 rgba(255, 192, 0, 1), /* Bottom Border */
-1px 0 0 0 rgba(255, 64, 0, 1); /* Left Border */
}
/* ... 생략 ... */
위와 같이 box-shadow
속성의 X offset 및 Y offset을 사용하여 각각의 테두리(Top, Right, Bottom, Left)를 표현할 수도 있으며, 동시(Top+Left, Right+Bottom 또는 Top+Right, Bottom+Left)에 적용할 수도 있다.
box-shadow: [<Type>] <X offset> <Y offset> [<Blur Radius>] [<Spread Radius>] [<Color>];
box-shadow
속성의 X offset 및 Y offset를 이용하여 한 테두리 표현은 아래와 같은 방식으로 지정할 수 있다.
box-shadow: 0 -1px 0 0 rgba(255, 0, 0, 0);
→ Top Borderbox-shadow: 1px 0 0 0 rgba(255, 0, 0, 0);`
→ Right Borderbox-shadow: 0 1px 0 0 rgba(255, 0, 0, 0);`
→ Bottom Borderbox-shadow: -1px 0 0 0 rgba(255, 0, 0, 0);`
→ Left Borderbox-shadow: 1px -1px 0 0 rgba(255, 0, 0, 0);`
→ Top Border, Right Borderbox-shadow: -1px 1px 0 0 rgba(255, 0, 0, 0);`
→ Bottom Border, Left Borderbox-shadow: 1px 1px 0 0 rgba(255, 0, 0, 0);`
→ Right Border, Bottom Borderbox-shadow: -1px -1px 0 0 rgba(255, 0, 0, 0);`
→ Top Border, Left Border
Type
의 기본값은 outset
이며, inset
으로 지정할 경우 위 방향과 반대 방향으로 테두리가 그려지게 된다.
아래의 스타일시트(CSS)는 box-shadow
의 색상에 투명도(rgba
의 Alpha 값)를 적용하고 모든 경우의 테두리를 사용한 경우이다.
/* ... 생략 ... */
.circle {
box-sizing: border-box;
width: 24rem;
height: 24rem;
box-shadow:
0 -1px 0 0 rgba(255, 64, 0, 0.25), /* Top Border */
1px 0 0 0 rgba(255, 192, 0, 0.25), /* Right Border */
0 1px 0 0 rgba(255, 192, 0, 0.25), /* Bottom Border */
-1px 0 0 0 rgba(255, 64, 0, 0.25), /* Left Border */
1px -1px 0 0 rgba(255, 128, 0, 0.5), /* Top Right Border */
-1px 1px 0 0 rgba(255, 128, 0, 0.5), /* Bottom Left Border */
-1px -1px 0 0 rgba(255, 0, 0, 0.75), /* Top Left Border */
1px 1px 0 0 rgba(255, 255, 0, 0.75); /* Right Bottom Border */
}
/* ... 생략 ... */
원형 테두리로 변경
스타일시트(CSS)의 border-radius
속성을 이용하여 원형으로 변경한다.
/* ... 생략 ... */
.circle {
box-sizing: border-box;
width: 24rem;
height: 24rem;
border-radius: 50%;
box-shadow:
0 -1px 0 0 rgba(255, 64, 0, 0.25),
1px 0 0 0 rgba(255, 192, 0, 0.25),
0 1px 0 0 rgba(255, 192, 0, 0.25),
-1px 0 0 0 rgba(255, 64, 0, 0.25),
1px -1px 0 0 rgba(255, 128, 0, 0.5),
-1px 1px 0 0 rgba(255, 128, 0, 0.5),
-1px -1px 0 0 rgba(255, 0, 0, 0.75),
1px 1px 0 0 rgba(255, 255, 0, 0.75);
}
/* ... 생략 ... */
회전 애니메이션 적용
스타일시트(CSS)의 @keyframes
키워드를 이용하여 회전 키프레임들을 생성하고, animation
속성을 이용하여 1초(1s
)에 한 바퀴 회전(transform: rotate(360deg)
)하는 애니메이션을 무한반복(infinite
)시킨다.
원형 테두리 추가 및 각각 다른 색상의 그라데이션 적용
3개의 원형(Circle) 테두리(Border)가 교차되면서 애니메이션(Animation) 되도록 하기 위해 HTML에 원형 요소(.circle
)들을 추가한다.
<div class="container">
<h1>Circle Gradient Border Rotation</h1>
<div class="circles">
<div class="circle"></div>
<div class="circle"></div>
<div class="circle"></div>
</div>
</div>
3개의 원형(Circle) 테두리(Border)에 각각 다른 색상의 그라데이션(Gradation)을 적용한다.
/* ... 생략 ... */
.circles {
position: relative;
width: 24rem;
height: 24rem;
}
.circle {
position: absolute;
box-sizing: border-box;
width: 24rem;
height: 24rem;
border-radius: 50%;
animation: rotation 1s linear infinite;
}
.circle:nth-of-type(1) {
left: -1rem;
box-shadow:
0 -1px 0 0 rgba(255, 64, 0, 0.25),
1px 0 0 0 rgba(255, 192, 0, 0.25),
0 1px 0 0 rgba(255, 192, 0, 0.25),
-1px 0 0 0 rgba(255, 64, 0, 0.25),
1px -1px 0 0 rgba(255, 128, 0, 0.5),
-1px 1px 0 0 rgba(255, 128, 0, 0.5),
-1px -1px 0 0 rgba(255, 0, 0, 0.75),
1px 1px 0 0 rgba(255, 255, 0, 0.75);
}
.circle:nth-of-type(2) {
left: 0;
box-shadow:
0 -1px 0 0 rgba(165, 181, 222, 0.25),
1px 0 0 0 rgba(225, 131, 194, 0.25),
0 1px 0 0 rgba(225, 131, 194, 0.25),
-1px 0 0 0 rgba(165, 181, 222, 0.25),
1px -1px 0 0 rgba(195, 156, 208, 0.5),
-1px 1px 0 0 rgba(195, 156, 208, 0.5),
-1px -1px 0 0 rgba(135, 206, 235, 0.75),
1px 1px 0 0 rgba(255, 105, 180, 0.75);
}
.circle:nth-of-type(3) {
left: 1rem;
box-shadow:
0 -1px 0 0 rgba(214, 69, 99, 0.25),
1px 0 0 0 rgba(192, 63, 153, 0.25),
0 1px 0 0 rgba(192, 63, 153, 0.25),
-1px 0 0 0 rgba(214, 69, 99, 0.25),
1px -1px 0 0 rgba(203, 66, 126, 0.5),
-1px 1px 0 0 rgba(203, 66, 126, 0.5),
-1px -1px 0 0 rgba(225, 72, 71, 0.75),
1px 1px 0 0 rgba(181, 59, 180, 0.75);
}
/* ... 생략 ... */
교차 애니메이션 적용
각각의 원형(Circle) 테두리(Border) 애니메이션(Animation)이 교차되도록 애니메이션 지연 시간(animation-delay
)을 다르게 지정하고, 애니메이션 프레임에서 위치(translate
)를 변경한다.
/* ... 생략 ... */
.circle:nth-of-type(1) {
box-shadow:
/* ... 생략 ... */;
animation: rotation 2s linear infinite;
}
.circle:nth-of-type(2) {
box-shadow:
/* ... 생략 ... */;
animation: rotation 2s linear 0.1s infinite;
}
.circle:nth-of-type(3) {
box-shadow:
/* ... 생략 ... */;
animation: rotation 2s linear 0.25s infinite;
}
@keyframes rotation {
0% {
transform: rotate(0deg) translate(0, 0);
}
33% {
transform: rotate(360deg) translate(0.375rem, 0.375rem);
}
66% {
transform: rotate(720deg) translate(-0.375rem, -0.375rem);
}
100% {
transform: rotate(1080deg) translate(0, 0);
}
}
/* ... 생략 ... */