CSS Part

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
.panels {
min-height: 100vh;
overflow: hidden;
display: flex;
}

.panel {
background: #6b0f9c;
box-shadow: inset 0 0 0 5px rgba(255, 255, 255, 0.1);
color: white;
text-align: center;
align-items: center;
/* Safari transitionend event.propertyName === flex */
/* Chrome + FF transitionend event.propertyName === flex-grow */
transition: font-size 0.7s cubic-bezier(0.61, -0.19, 0.7, -0.11),
flex 0.7s cubic-bezier(0.61, -0.19, 0.7, -0.11), background 0.2s;
font-size: 20px;
background-size: cover;
background-position: center;
flex: 1;
justify-content: center;
display: flex;
flex-direction: column;
}

/* Flex Children */
.panel > * {
margin: 0;
width: 100%;
transition: transform 0.5s;
flex: 1 0 auto;
display: flex;
justify-content: center;
align-items: center;
}

Flex Display에 대한 이해가 필요한 예제였다. FlexGrid에 완전히 익숙하지가 않아 차근차근 이해하려 노력했다.

Flex

Flex와 관련된 CSS 속성들이 정말 많다. 간단하게 이번 에제에서 사용된 것만 정리해보면,

flex: 1 : flex 적용을 받는 요소들의 너비를 1로 통일 (1이든 100이든 상관없음)
justify-content: center, align-items: center : 요소 중앙 정렬
flex-direction: column : flex 적용을 받는 요소 안에 내용물의 방향(기본: row)

Flex Layout은 이 곳에 정리가 잘 되어 있다

cubic-bezier

1
2
transition: font-size 0.7s cubic-bezier(0.61, -0.19, 0.7, -0.11),
flex 0.7s cubic-bezier(0.61, -0.19, 0.7, -0.11), background 0.2s;

.panel에 선언된 css 속성이다. cubic-bezier() function은 transition 속성 또는 transition-timing-function 속성에서 전환 시작과 끝까지의 효과를 제어한다.

베지어곡선

베지어 곡선을 정의하는 것이라고 이해하면 된다.

위의 예에서 transition이 일어날 때 font-size, flex에 대해 cubic-bezier를 정의했는데, ()에 들어가는 4개의 숫자가 곡선의 curve를 나타낸다.

event 처리를 위한 css class 설정

이제 Javascript에서 각 panel에 이벤트를 걸어 css 속성을 바꿔주는데, 이 때 classList.toggle을 통해 css를 제어할 것이다.

우선 .panel의 첫 번째와 마지막 글자를 위한 transform 속성을 정의한다.

1
2
3
4
5
6
7
8
9
10
11
12
.panel > *:first-child {
transform: translateY(-100%);
}
.panel.open-active > *:first-child {
transform: translateY(0);
}
.panel > *:last-child {
transform: translateY(100%);
}
.panel.open-active > *:last-child {
transform: translateY(0);
}

이제 .panel의 flex layout을 변경하기 위해 flex 속성을 정의한다.

1
2
3
.panel.open {
flex: 5;
}

모든 요소가 flex: 1인 상태에서 .open class를 부여받은 panel만 5배의 비율로 늘어난다.

Javascript Part

이제 .panel에 event를 걸어준다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const panels = document.querySelectorAll(".panel");

function toggleOpen() {
console.log("Hello");
this.classList.toggle("open");
}

function toggleActive(e) {
if (e.propertyName.includes("flex")) {
this.classList.toggle("open-active");
}
}
panels.forEach((panel) => panel.addEventListener("click", toggleOpen));
panels.forEach((panel) =>
panel.addEventListener("transitionend", toggleActive)
);

toggle 속성이 꽤 자주 사용된다. class를 부여하는데, 있으면 놔두고 없으면 추가한다.

응용

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const panels = document.querySelectorAll(".panel");
function toggleOpen() {
panels.forEach((panel) => panel.classList.remove("open"));
this.classList.toggle("open");
}

function toggleActive(e) {
if (e.propertyName.includes("flex")) {
this.classList.toggle("open-active");
}
}
panels.forEach((panel) => panel.addEventListener("click", toggleOpen));
panels.forEach((panel) =>
panel.addEventListener("transitionend", toggleActive)
);

한 이미지를 선택할 때 나머지 이미지의 layout을 원래대로 돌려놓게 응용했다.

1
panels.forEach((panel) => panel.classList.remove("open"));

toggleOpen() 함수가 실행될 때 모든 panelopen class를 삭제한 후 이벤트가 발생한 panel에만 open class를 부여했다.