토이 프로젝트로 센추리: 향신료의 길을 웹으로 클론(?)하고 있다. 보드게임인데, 자세한 사항은 구글 선생님께 물어보자.
오늘 구현할 내용은 API로부터 받아온 큐브 정보를 카드에다 그려내는 것인데, 내가 생각했던 것과 결과가 다르게 나왔다.
저 큐브를 둘러싸고 있는 하얀 프레임이 큐브 개수에 맞게 크기가 조절되었으면 하는데, 큐브 개수에 상관없이 카드에 꼭 맞게 나와서 CSS의 여러 속성을 조절해봤고, 문제는 align-items에 있는 것을 발견했다.
우선 카드를 표현하는 HTML 태그와 CSS를 간단히 표현하면...
<div class="card">
<div class="cube-frame">
<div class="cube-item">
</div>
</div>
</div>
.card {
display: flex;
flex-direction: row;
...
}
.cube-frame {
display: flex;
flex-direction: column;
align-items: center;
}
.cube-item {
width: 8px;
height: 8px;
margin-bottom: 4px;
...
}
처음에는 cube-frame
에 높이를 설정해줄까 생각했는데, 높이가 가변이어야 하는데 높이를 고정시키면 Flex를 쓸 이유가 없다는 생각이 들었다. 여러가지를 실험해 보다가 도저히 답이 안나와서 프로젝트 팀원에게 도움을 요청했는데,
어? 이거 왜 자동으로 align-items: stretch 돼있어요?
라는 말을 하셔서 이게 문제구나! 라는 것을 알게 되었다. 여기서 알게 된 사실이, align-items
는 따로 설정해주지 않으면 기본적으로 stretch
가 적용되어 자식요소에 따로 높이를 설정하지 않으면 부모 요소에 맞게 쭉~ 늘어나는 것이다. 그래서 card
태그에 align-items: flex-start
속성을 추가해주니 내가 원하는 그림이 나왔다!
센추리 프로젝트는 Vue로 개발되고 있다. 그래서 큐브는 v-for
를 사용하여 반복하고 있는데, 큐브를 싸고 있는 프레임에 padding이 적용되어 있는데 마지막 요소의 margin-bottom이 더해지니까 보기에 영 좋지 않았다. 그래서 마지막 요소를 CSS로 어떻게 제외하는지 찾아보았다.
그래서 not 키워드를 사용해서 마진값을 제외하거나, last-of-type을 사용해서 마진을 0으로 만드는 방법이 있다. 나는 그냥 후자를 선택하여 처리했다.
.cube-item {
width: 8px;
height: 8px;
margin-bottom: 4px;
...
}
/* 첫 번째 방법 - cube-item에서 margin 태그를 지우고 not으로 처리 */
.cube-item {
width: 8px;
height: 8px;
/* margin-bottom: 4px; */
...
}
.cube-item:not(last-of-type) {
margin-bottom: 4px;
}
/* 두 번째 방법 - last-of-type의 마진값을 0으로 설정 */
.cube-item {
width: 8px;
height: 8px;
margin-bottom: 4px;
...
}
.cube-item:last-of-type {
margin-bottom: 0;
}
두 방법 사이의 성능 차이가 있는지 탐구해보고 싶다. 개인적인 생각으로는, 첫 번째 방법은 N-1개의 요소에 추가적인 margin을 적용해주는 거라 1개의 요소에 추가적인 것을 적용하는 두 번째 방법이 성능이 조금 더 좋지 않을까? 생각해본다. 이건 근데 적용해야하는 요소의 개수에 따라 적절한 방법이 다를 것 같다.
align-center의 기본값은 stretch이다.
css로 첫번째, 마지막 요소를 선택할 때는 뒤에 :first-of-type, :last-of-type을 붙이면 된다.