참고사항- 태극기 양은 (#d13642) 을 사용해야 하며, 음은 (#080884) 을 사용해야 합니다. 과정에는 음의 색상만 정확히 사용하고, 양의 색상은 임시 색상인 red 를 사용하고 있는데, 결과물에서는 정상적인 색상으로 설정되어 있습니다. |
들어가는 말
오늘 만들어볼 작품은 태극기 입니다. 1945년 8월 15 일 일본 제국의 패망으로 식민지로 벗어나 현재 대한민국은 눈부신 성장을 거쳐 지금과 같은 강국이 되었습니다. 오늘은 이 날을 맞이하여 나름의 광복절을 기념하며, 애국하는 마음으로 CSS 를 사용해 태극기를 만들어 보았습니다.
아래는 시연 영상입니다. 참고로 자바스크립트 부분은 설명하지 않았습니다. 만들고 정리하다보니 시간이 많이 지체되어서 생략하였습니다. 어려운 코드는 아니니 최하단 공유된 코드를 통해 살펴보시길 추천합니다.
이미지로 보면 아래와 같은 결과물을 만들 수 있습니다.
[번외] AI 야, 태극기 그려줘
참고로 AI 는 태극기 이미지를 던져 주면 잘 만들 수 있을까 궁금하여 몇 곳을 방문해서 맡겨 보았습니다. gpt와 그 외 친구들은 .. 말하지 않아도 아실거라 생각합니다.
이 친구는 텍스트는 엄청 잘 아는 듯이 설명은 해주는데, 뜬금없는 데칼코마니를 만들어주었습니다.
다음 친구는 시작도 전에 포기해 버렸습니다.
AI 도 태극기는 많이 어렵나 봅니다.
[번외] 태극기란 무엇인가
태극기를 만들기 전 대한민국의 태극기는 무엇을 의미하는 걸까요? 태극기는 건괘(乾卦)-하늘, 곤괘(坤卦)-땅, 감괘(坎卦)-물, 이괘(離卦)-불 을 의미하는 4개의 괘가 중앙의 태극 문양(태양과 바다를 의미하는 음양)을 감싸고, 바탕으로 흰색인 대한민국의 국기 입니다.
흰색 바탕은 밝음과 순수, 그리고 전통적으로 평화를 사랑하는 우리의 민족성을 나타내며,
태극 문양은 음(파랑)과 양(빨강)의 조화를 상징하는 것으로 우주 만물이 음양의 조화로 인해 생명을 얻고 발전한다는 대자연의 진리를 표현해낸 것입니다.
구현에 적극 참고된 태극기 만드는 방법
아래는 태극기 만드는 방법으로 소개된 이미지로 해당 이미지에 표시된 각 비율을 기반으로 제작하였습니다.
바로 들어가봅시다.
HTML
우선 HTML 은 건,곤,감,이 를 의미하는 각 컨테이너 형태의 태그를 만들고, 중앙에 태극이 올 수 있도록 괘 사이에 배치하였습니다. 이들은 CSS 에서 display:grid 를 적용하여 적절한 위치에 배치할 예정입니다.
<p>
흰색 바탕은 밝음과 순수, 그리고 전통적으로 평화를 사랑하는 우리의 민족성을 나타냅니다.
태극 문양은 음(파랑)과 양(빨강)의 조화를 상징하는 것으로 우주 만물이 음양의 조화로 인해 생명을 얻고 발전한다는 대자연의 진리를 표현해낸 것입니다
</p>
<div class="container">
<!-- 건괘 (乾卦) - Heaven -->
<div class="heaven hexagram">
<div class="bar_group">
<div class="bar"></div>
<div class="bar"></div>
<div class="bar"></div>
</div>
</div>
<!-- 곤괘 (坤卦) - Earth -->
<div class="earth hexagram">
<div class="bar_group">
<div class="bar half"></div>
<div class="bar half"></div>
<div class="bar half"></div>
</div>
</div>
<!-- 태극 (Taegeuk) -->
<div class="taeguk">
<div class=" yang"></div>
<div class=" yin"></div>
</div>
<!-- 감괘 (坎卦) - Water -->
<div class="water hexagram">
<div class="bar_group">
<div class="bar half"></div>
<div class="bar"></div>
<div class="bar half"></div>
</div>
</div>
<!-- 이괘 (離卦) - Fire -->
<div class="fire hexagram">
<div class="bar_group">
<div class="bar"></div>
<div class="bar half"></div>
<div class="bar"></div>
</div>
</div>
</div>
CSS
기본 CSS 초기화 및 CSS 변수
기본 CSS 초기화
우선 브라우저에 기본적으로 적용된 여백을 제거하고, body 태그가 뷰포트 전체를 감싸도록 설정 후 배경 전체를 #333 으로 설정하여 어둡게 표현해줍니다.
* {
margin: 0;
padding: 0;
box-sizing: border-box;
--base-diameter: 250px;
}
body {
width: 100%;
height: 100%;
background: #333;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
대략 아래와 같은 화면이 보이게 됩니다.
CSS 변수 설정
아래와 같이 --base-diameter 로 250px 를 지정해둔 것을 볼 수 있습니다. 이는 태극헤 해당하는 원의 기본 지름을 설정한 것으로 해당 지름을 기준으로 레이아웃을 동적으로 지정해나갈 것 입니다. 참고로 해당 변수는 var(뱐수명) 형태로 사용할 수 있고 해당 자리에 지정한 값이 남게 됩니다.
* {
--base-diameter: 250px;
}
Container 초기 설정
.container {
aspect-ratio: 3 / 2; /*넓이: 3, 높이: 2*/
background: white;
display: grid;
place-items: center; /* 그리드의 각 셀 마다 수직/수평 정렬*/
grid-template-columns: 1fr 1fr 1fr; /* 셀 비율 맞춤*/
grid-template-rows: 1fr 1fr;
grid-template-areas:
"heaven circle water"
"fire circle earth";
}
종횡비 설정(3/2)
container 부분은 태극기의 전체 틀이 되는 부분으로 넓이 3, 높이 2의 비율로 직사각형을 만들어주기 위해 종횡비를 설정해주는 속성인 aspect-ratio 를 3/2 로 설정해줍니다.
그리드 설정
해당 태극기의 구역은 절대적인 비율을 맞추는 것이 중요하므로 flex 레이아웃 보다 grid 가 적합하다고 판단해서 이를 적용 했습니다. place-items 는 그리드의 각 셀 마다 수직/중앙 정렬을 해주는 친구입니다.
display: grid;
place-items: center; /* 그리드의 각 셀 마다 수직/수평 정렬*/
grid-template-columns: 1fr 1fr 1fr; /* 셀 비율 맞춤*/
grid-template-rows: 1fr 1fr;
grid-template-areas:
"heaven circle water"
"fire circle earth";
grid-template-columns 와 rows 는 각각 그리드의 각 셀이 차지하는 비율은 세로, 가로 기준으로 프레임을 지정해줄 수 있는 속성입니다. columns 는 1fr 1fr 1fr 을 설정하여 가로 방향으로 3개의 셀이 균등하게 배치되도록 하였고,
rows 또한 1fr 1fr 을 적용하여 세로 방향으로 2개의 셀이 균등하게 배치되도록 설정하였습니다.
grid-template-areas 는 현재 container 요소의 자식 요소로 배치되고 있는 각 건,곤,감,이를 나타내는 각 요소에 grid-area: circle 등과 같이 이름이 지정된 경우 해당 별칭이 지정된 요소를 그리드 영역 내에서 배치시키는 역할을 하는 친구입니다.
여기까지 지정했다면, 눈에 보이지는 않더라도 대략 아래와 같은 형태로 배치 됩니다.
기본 건곤감이 형태 생성
건,곤,감,이 를 배치하기 전에 기본적으로 베이스가 되는 형태를 만들겠습니다.
.hexagram {
aspect-ratio: 3 / 2;
position: relative;
width: 100%;
.bar_group {
position: absolute;
}
.bar {
position: relative;
background: black;
margin-top: calc(var(--base-diameter) / 24); /* 태극(써클) 지름의 1/24 */
width: calc(var(--base-diameter) / 2); /* 태극(써클) 지름의 1/2 */
height: calc(var(--base-diameter) / 12); /* 태극(써클) 지름의 1/12 */
}
}
hexagram
.hexagram (괘를 의미) 에도 aspect-ratio 를 3/2 비율로 지정해줍니다. 이는 태극기 전체 틀인 container 와 비율적으로 자연스럽게 만들어 주기 위해서 입니다.
bar_group
.bar_group 은 아래 이미지와 같이 각 괘를 감싸는 테두리 입니다. 해당 요소에 absolute 를 지정하여 향후 적정 위치에 각 괘를 배치할 떄 사용할 것입니다.
.bar
.bar {
position: relative;
background: black;
margin-top: calc(var(--base-diameter) / 24); /* 태극(써클) 지름의 1/24 */
width: calc(var(--base-diameter) / 2); /* 태극(써클) 지름의 1/2 */
height: calc(var(--base-diameter) / 12); /* 태극(써클) 지름의 1/12 */
}
여기서 margin-top, width, height 을 calc 함수와 var 변수를 사용해서 계산된 값을 설정해주고 있습니다. 해당 공식은 아래 태극기 만드는 법 이미지에 설명 되어 있는 수치를 참고 했습니다. 여기서 1/12, 1/24 의 기준이 되는 크기를 저의 경우에는 태극 문양의 지름을 의미한다고 판단해서 --base-diameter 에 각 수치를 나눠서 계산된 값을 적용하였습니다.
여기 까지 적용한다면, 아래와 같이 반듯한 괘들이 만들어진 것을 볼 수 있습니다.
괘 모양 만들기
이 부분은 모두 동일한 방식으로 레이아웃을 지정하기 때문에, 건괘 부분만 설명하고 나머지는 코드만 반영하고 넘어가겠습니다.
건괘 - 하늘
여기서 grid-area 이 나옵니다. 그 값으로 heaven 을 지정한 것을 볼 수 있습니다.
/* 건쾌- 하늘 */
.hexagram.heaven {
grid-area: heaven;
.bar_group {
transform: rotate(-50deg);
top: 15%;
left: 45%;
}
}
해당 별칭으로 지정한 값을 앞서 container 요소에 지정했던 grid-template-areas 에서 각 요소가 위치하는 셀의 위치를 임의적으로 배치할 때 사용 합니다.
display: grid;
place-items: center; /* 그리드의 각 셀 마다 수직/수평 정렬*/
grid-template-columns: 1fr 1fr 1fr; /* 셀 비율 맞춤*/
grid-template-rows: 1fr 1fr;
grid-template-areas:
"heaven circle water"
"fire circle earth";
즉, 현재 건괘는 아래 주황색 위치에 배치됩니다.
나머지도 동일하게 배치해 보도록 하겠습니다.
감괘 - 물
/* 감쾌- 물 */
.hexagram.water {
grid-area: water;
.bar_group {
transform: rotate(50deg);
top: 15%;
right: 45%;
}
}
이괘 - 불
/* 이쾌 - 블 */
.hexagram.fire {
grid-area: fire;
.bar_group {
transform: rotate(50deg);
bottom: 15%;
left: 45%;
}
}
곤괘 - 땅
/* 곤쾌 - 땅 */
.hexagram.earth {
grid-area: earth;
.bar_group {
transform: rotate(-50deg);
bottom: 15%;
right: 45%;
}
}
태극 문양 만들기
만들기 어려워 보이는 태극 문양을 하나씩 만들어봅니다.
/* yang/yin */
.taeguk {
aspect-ratio: 1 / 1;
position: relative;
grid-area: circle;
width: var(--base-diameter);
min-height: var(--base-diameter);
transform: rotate(30deg);
border-radius: 50%;
/* 양= 태양 */
.yang {
position: absolute;
width: 100%;
height: 100%;
background: red;
border-radius: 50% 50% 0 0;
clip-path: circle(50%);
}
/* 음 = 바다 */
.yin {
position: absolute;
width: 100%;
height: 100%;
background: #134a9d;
border-radius: 0 0 50% 50%;
/* 원을 절반으로 자름 */
clip-path: inset(50% 0 0 0);
}
}
taeguk
.taeguk {
aspect-ratio: 1 / 1;
position: relative;
grid-area: circle;
width: var(--base-diameter);
min-height: var(--base-diameter);
transform: rotate(30deg);
border-radius: 50%;
}
여기서 taguk 는 문양의 컨테이너(감싸는) 역할을 하기 때문에 완전한 원형을 만들어주기 위해서 aspect-ratio 를 1/1 로 지정하여 높이와 넓이의 비율을 고정시켜 줍니다.
grid-area 에 circle 을 지정하게 되면, 앞서 언급했듯이 container 에 지정한 circle 의 위치로 taeguk 이 위치하게 됩니다.
앞서 예시 이미지에서는 circle 로 지정한 셀의 위치를 구분해두었지만,
실제로는 아래와 같이 두 셀의 영역이 합쳐지고 해당 circle 은 중앙에 위치하게 됩니다. 참고로, 중앙에 위치 되는 이유는 container 에 지정한 place-items:center 를 통해 수직 수평으로 셀이 정렬되기 때문입니다.
yang - 태양 - 빨강
다음은 태극의 양에 해당하는 부분입니다. position을 absolute 로 지정하는 이유는 음에 해당하는 요소와 겹치기 위해서 입니다.
/* 양= 태양 */
.yang {
position: absolute;
width: 100%;
height: 100%;
background: red;
border-radius: 50% 50% 0 0;
clip-path: circle(50%);
}
여기서 주요 속성은 clip-path:circle(50%) 입니다. 여기서 circle 함수는 클립핑 영역을 원형 형태로 생성하는 함수로 적용되는 수치는 어느 정도 크기 까지 클립핑하여 숨길 것인지 나타냅니다.
아래 예시를 보면 40% 일 떄와 20% 일 떄 클립핑 되어 숨겨지는 정도가 달라지는 것을 볼 수 있습니다.
yin - 음 - 바다
/* 음 = 바다 */
.yin {
position: absolute;
width: 100%;
height: 100%;
background: #134a9d;
border-radius: 0 0 50% 50%;
/* 원을 절반으로 자름 */
clip-path: inset(50% 0 0 0);
}
여기서 주요 속성도 clip-path 입니다. inset 함수가 적용되어 있는데 해당 함수는 top, right, bottom, left 순으로 클립핑 영역을 지정하는 값을 전달받으며, 전달받은 값의 길이 만큼 클립핑하여 요소가 보이지 않도록 설정합니다.
아래 예시를 보면 inset(0 0 0 0) 경우에는 이미지에 아무런 변화가 없습니다.
여기서 top 에 해당하는 부분의 수치를 변경해주면, 그 비율만큼 클립핑 영역으로 지정되어 보이지 않는 것을 볼 수 있습니다.
여기 까지 적용하면
여기 까지 적용한다면, 아래와 같은 모양이 만들어졌을 겁니다. 이제 조금만 더 하면 됩니다.
물결치는 문양 만들기(앙 - 태양)
.taeguk::before {
content: "";
position: absolute;
left: 0;
top: 50%;
transform: translate(0, -50%);
width: 50%;
height: 50%;
background: red;
border-radius: 50%;
z-index: 1;
}
특별한 부분은 없습니다. before 가상선택자를 통해 태극의 지름에 반에 해당하는 크기의 원을 만들어주는 코드입니다. 배치를 좌측 끝에 붙여주어, 아래와 같은 형태가 만들어집니다.
물결치는 문양 만들기(음- 바다)
이 부분도 동일하게 설정해주는데, 위치를 우측 끝으로 이동시켜줍니다.
.taeguk::after {
content: "";
position: absolute;
right: 0;
top: 50%;
transform: translate(0, -50%);
width: 50%;
height: 50%;
background: #134a9d;
border-radius: 50%;
}
완벽한 태극 문양이 만들어졌습니다!.
레이아웃 배치
이제 각 괘를 필요로 하는 위치로 한 번에 옮깁니다. .hexagram 의 속성으로 position:relative 를 추가해줍니다. 이렇게 되먄, 각 bar 에 적용된 absolute 의 기준점이 hexagram 이 되어 각 셀을 기준으로 요소들이 배치됩니다.
.hexagram {
position: relative;
}
결과적으로 아래 모양이 만들어집니다.
괘 모양 마무리
현재 까지 따라오셨다면, 각 건곤감이가 모두 동일한 모양을 가지고 있을 겁니다. 이제 이들의 모양을 만들어주겠습니다.
앞서 HTML 의 건곤감이 부분을 보시면, .bar 말고도 half 라는 클래스 값이 적용된 것을 볼 수 있습니다. CSS 에서 이를 꾸며주는 코드만 추가해주면 됩니다.
<!-- 건괘 (乾卦) - Heaven -->
<div class="heaven hexagram">
<div class="bar_group">
<div class="bar"></div>
<div class="bar"></div>
<div class="bar"></div>
</div>
</div>
<!-- 곤괘 (坤卦) - Earth -->
<div class="earth hexagram">
<div class="bar_group">
<div class="bar half"></div>
<div class="bar half"></div>
<div class="bar half"></div>
</div>
</div>
<!-- 태극 (Taegeuk) -->
<div class="taeguk">
<div class=" yang"></div>
<div class=" yin"></div>
</div>
<!-- 감괘 (坎卦) - Water -->
<div class="water hexagram">
<div class="bar_group">
<div class="bar half"></div>
<div class="bar"></div>
<div class="bar half"></div>
</div>
</div>
<!-- 이괘 (離卦) - Fire -->
<div class="fire hexagram">
<div class="bar_group">
<div class="bar"></div>
<div class="bar half"></div>
<div class="bar"></div>
</div>
</div>
.hexagram 의 중첩 요소로 .bar.half::before 을 추가해줍니다.
.hexagram {
.bar.half::before {
content: "";
position: absolute;
width: calc(var(--base-diameter) / 24); /* 태극(써클) 지름의 1/24 */
height: 100%;
background: white;
left: 50%;
transform: translate(-50%);
}
}
이 부분에서 간격을 만들어 주는 부분은 width 입니다. 이 는 앞서 태극기 만드는 법에서 나와있는 1/24 를 태극의 지름에서 나눠준 값을 할당하여 만들어줍니다. 위 코드는 결국 작은 직사각형을 만든 후 해당 사각형을 필요로 하는 위치로 이동시켜서 마치 bar 가 나뉘어 있는 것처럼 보이게 만들어주는 것이 다입니다.
여기까지만 해도 완성된 것
여기 까지만 해도 아래와 같이 깔끔한 태극기가 만들어집니다. 이후 부터 적용하는 코드는 선택이라 보면 됩니다.
표면에 반사되는 빛나는 태극기
왠지 이대로 마무리 하기 아쉬웠습니다. 그래서 몇 가지 기능을 더 추가했습니다. 최근에 알게된 속성 중에 reflect 라는 css 속성이 있습니다. 해당 속성은 요소의 데칼코마니를 만들어주는 속성으로 이 속성을 활용하면 잔잔한 표면에 은은하게 비추는 효과를 만들어 줄 수 있습니다.
앞서 container 요소에 아래와 같이 추가해줍니다.
.container {
-webkit-box-reflect: below 0 linear-gradient(transparent, rgba(0, 0, 0, 0.09));
}
하단에 보시면 태극기가 반사되어 반투명하게 보이는 것을 볼 수 있습니다. 참고한 정보는 (https://developer.mozilla.org/en-US/docs/Web/CSS/-webkit-box-reflect#syntax) 입니다. 다만 참고하셔야 하는 점은 해당 속성은 비표준이기 때문에, 브라우저 전반적으로 지원하기는 하지만 언제 변경되거나 레거시될지 알 수 없습니다.
이대로 마무리 하기에도 뭔가 아쉽습니다. 그래서 이번에는 은은하게 빛이 나도록 그림자 효과를 추가해주었습니다. 해당 속성도 container 에 적용해주면 됩니다.
box-shadow: 0 0 100px white;
이제 뭔가 만족스러운 결과물이 보이는 것 같습니다.
막상 마무리 하려니 또 뭔가가 아쉽습니다. 음.. 위아래로 움직이면 더 극적이지 않을까 싶어서 업다운 되는 애니메이션을 하나 추가해줬습니다.
.container {
-webkit-box-reflect: below 0 linear-gradient(transparent, rgba(0, 0, 0, 0.09));
box-shadow: 0 0 100px white;
animation: 1s alternate infinite updown linear;
scale: 0.8;
}
@keyframes updown {
0% {
transform: translateY(15px);
}
}
결과물
아래는 전체 코드 입니다. 사실 위 애니메이션 까지 추가하고 아쉬워서 자바스크립트 한 스푼과 태극기를 소개하는 텍스트 부분도 같이 추가해주었습니다.
See the Pen 태극기 by youngwan2 (@youngwan2) on CodePen.
나가는 말 - 후기
오늘은 광복절을 맞이하여 태극기를 CSS를 사용하여 만들어 보았습니다. 보다 태극기가 강조되도록 여러 효과를 추가해보기도 하였습니다. 비록 완벽한 형태의 태극기라고 볼 수는 없으나, 이렇게 하나하나 만들어보는 시간을 가져봄으로써 평소에 사용하지 않던 다양한 CSS 그리드 속성을 적용해보는 시간이 된 것 같습니다.
이 포스트가 도움이 되었길 바라며 이만 글을 줄여봅니다.
'UI 디자인 애니메이션 연구소' 카테고리의 다른 글
HTML,CSS,JS + GSAP 로 만드는 버블 어택 애니메이션 (0) | 2024.08.18 |
---|---|
JS와 GSAP stagger API 로 만드는 스트리밍 써클 애니메이션! (1) | 2024.08.06 |
바닐라 자바스크립트를 이용한 스크롤 트리거 애니메이션의 원리와 구현 (0) | 2024.07.25 |
캐러셀 라이브러리에서 보던 드래그 가능한 슬라이드, 원리 부터 구현까지!! (0) | 2024.07.18 |
HTML과 CSS 만으로 이런 것도 가능해?? 액자 모양 로고 애니메이션 (0) | 2024.07.02 |