오늘은 어제 Card Flip Effect관련하여 구현에 대해서 어려움을 겪던 김**님과 같이 코드를 보던 중에 한번 공부해보면 좋겠다라는 생각이 들어서 card flip effect에 대해서 구현을 해봤다.
html 파일은 아래와 같이 우선 작성을 하였다.
<body>
<div class="card">
<div class="card-front">
<h1>카드 앞면</h1>
</div>
<div class="card-back">
<h1>카드 뒷면</h1>
</div>
</div>
</body>
구현을 위해 아래와 같이 생각했다.
card에 position: relative;
를 설정하고 card-front와 card-back은 position:absolute;
를 설정하였다.
.card {
width: 200px;
height: 400px;
position: relative;
}
.card-front,
.card-back {
position: absolute;
width: 100%;
height: 100%;
}
card가 호버되면 카드를 뒤집는 이펙트가 나와야하는데 이는 rotateY를 이용해서 180deg로 돌려버리면 된다고 생각했다. 그런데 카드가 어차피 뒤집어 진다면 card-front는 0deg, card-back은 180deg로 미리 설정을 해놓으면 card가 뒤집어지는 순간 card-back은 제대로 보일 것이라고 생각했다.
.card:hover {
transform: rotateY(180deg);
}
.card-back {
transform: rotateY(180deg);
3번의 경우에는 z-index를 처음에는 card-front에게 더 우선순위를 주고 background-color를 설정해서 뒷면이 보이지 않게 하고, card가 hover 시 card-back에게 z-index를 높여 뒤가 보이게끔 설정하면 된다고 생각했다. 물론 뒷면도 background-color를 front와는 다른 색을 부여하였다.
.card-front {
background-color: red;
z-index: 1;
}
.card-back, .card:hover card-front {
z-index: 0;
}
.card:hover .card-back {
z-index: 1;
}
3가지의 내용들을 전부 구현한 결과 아래와 같았다.
호버를 하면 원하는대로 나오기는 했다. 다만 아쉬운 점이 조금 있었는데 card자체가 rotateY를 하면서 제대로 된 공간을 차지하지 않아서 그런지 자꾸 버벅거린다는 현상이 있었다.
전체 코드
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Card Flip Effect</title>
<style>
/* 어떻게 구현할 것인가?
1. 카드 뒷면과 카드 앞면은 카드를 기준으로 position이 일치해야 한다. -> position
2. hover를 하는 순간 카드를 뒤집는 이펙트가 나와야 한다. -> transform 을 이용하여 ?
3. 앞 뒷면 구현은 어떻게 할 것인가? 뒷면에 있는 내용은 보여서는 안된다. -> z-index
*/
body {
display: grid;
grid-template-columns: repeat(3, 1fr);
row-gap: 1rem;
}
.card {
width: 200px;
height: 400px;
position: relative;
}
.card,
.card-front,
.card-back {
transition: transform 0.5s;
}
.card-front,
.card-back {
position: absolute;
width: 100%;
height: 100%;
}
.card-front {
background-color: red;
z-index: 1;
}
.card-back {
transform: rotateY(180deg);
background-color: blue;
}
.card:hover {
transform: rotateY(180deg);
}
.card-back, .card:hover .card-front {
z-index: 0;
}
.card:hover .card-back {
z-index: 1;
}
</style>
</head>
<body>
<div class="card">
<div class="card-front">
<h1>카드 앞면</h1>
</div>
<div class="card-back">
<h1>카드 뒷면</h1>
</div>
</div>
<div class="card">
<div class="card-front">
<h1>카드 앞면</h1>
</div>
<div class="card-back">
<h1>카드 뒷면</h1>
</div>
</div>
<div class="card">
<div class="card-front">
<h1>카드 앞면</h1>
</div>
<div class="card-back">
<h1>카드 뒷면</h1>
</div>
</div>
<div class="card">
<div class="card-front">
<h1>카드 앞면</h1>
</div>
<div class="card-back">
<h1>카드 뒷면</h1>
</div>
</div>
<div class="card">
<div class="card-front">
<h1>카드 앞면</h1>
</div>
<div class="card-back">
<h1>카드 뒷면</h1>
</div>
</div>
</body>
</html>
그래서 card flip effect에 대해서 다시 한번 구글링을 해본 결과 다음과 같이 작성하면 flip 효과를 구현할 수 있었다.
/* The flip card container - set the width and height to whatever you want. We have added the border property to demonstrate that the flip itself goes out of the box on hover (remove perspective if you don't want the 3D effect */
.flip-card {
background-color: transparent;
width: 300px;
height: 200px;
border: 1px solid #f1f1f1;
perspective: 1000px; /* Remove this if you don't want the 3D effect */
}
/* This container is needed to position the front and back side */
.flip-card-inner {
position: relative;
width: 100%;
height: 100%;
text-align: center;
transition: transform 0.8s;
transform-style: preserve-3d;
}
/* Do an horizontal flip when you move the mouse over the flip box container */
.flip-card:hover .flip-card-inner {
transform: rotateY(180deg);
}
/* Position the front and back side */
.flip-card-front,
.flip-card-back {
position: absolute;
width: 100%;
height: 100%;
-webkit-backface-visibility: hidden; /* Safari */
backface-visibility: hidden;
}
/* Style the front side (fallback if image is missing) */
.flip-card-front {
background-color: #bbb;
color: black;
}
/* Style the back side */
.flip-card-back {
background-color: dodgerblue;
color: white;
transform: rotateY(180deg);
}
<div class='flip-card'>
<div class='flip-card-inner'>
<div class='flip-card-front'>
<img src='img_avatar.png' alt='Avatar' style='width: 300px; height: 300px' />
</div>
<div class='flip-card-back'>
<h1>John Doe</h1>
<p>Architect & Engineer</p>
<p>We love that guy</p>
</div>
</div>
</div>
실행을 해보면서 이전에 언급했던 버벅거리는 현상이 줄어들었고, 코드를 보내 flip-card라는 것을 기준으로 두고 flip-card는 돌아가지 않고 내부에 있는 inner만 돌아가게끔 설정하였다.
그리고 그 외에 css로는
위 3가지가 추가가 돼있다.
perspective는 원근감을 주는 속성으로 현재 바라보는 위치에서 얼마나 멀리 있게끔 설정할 것인가를 설정할 수 있다. z축으로 움직이는 것은 반드시 원근감이 세팅되어야 하는데 그렇지 않다면 굳이 필요가 있는 속성은 아니다.
backface-visibility 속성은 요소의 뒷면의 요소들을 보여줄 것인지 보여주지 않을 것인지를 설정하는 속성으로 이전에 혼자 구현할 때 겹치는 것은 잘했지만 뒷면도 같이 보이는 문제를 background-color를 이용해서 색을 채워 안보이게 설정했는데 이 속성을 통해서 안보이게도 할 수 있었다.
transform-style 속성은 요소의 자식들이 3d 환경인지 평면의 환경인지를 세팅하는 속성으로 preserved-3d 값을 넣으면 요소의 자식들이 3d처럼 보이게 할 수 있다. mdn에서 설명 중 childs of element라고 하는 것을 보아 부모 요소에 해당 속성을 작성해야 하는 것 같다.
이 속성을 이용해서 3d처럼 보일 수 있는데 이렇게 해놓으니까 기존에 생각했었던 z-index를 설정해놓는 것 보다 조금 더 부드럽게 수행이 가능했다.
원래 알고 있는 지식을 이용해서 구현하는 것도 재미있었고 이렇게 새롭게 다른 방식으로 구현하는 방법을 보면서 css는 정말 다양한 방식으로 표현할 수 있는 것을 알았고, 이전보다 더 다양한 css 속성에 대해서 공부해본 시간이었다.