Instagram 레이아웃 cloning #4 Feeds

leitmotif·2021년 12월 10일
0

클론 코딩

목록 보기
4/4
post-thumbnail

개요

Instagram cloning 중, Feeds 영역을 정리합니다.

CSS Idea

인스타그램 화면에서 유일하게 이동하는 화면입니다.

사이드바와 같은 부모를 공유하는데, 부모인 bodyContainer가

row로 정렬되며 시작점에 있으므로 부모 영역에서 표시될 영역만 잡았습니다.

앞선 영역들과 마찬가지로 반응형으로 width가 조절되도록 했습니다.

바로 다음 포스팅될 sidebar의 width는 즉,
935 - (605+28) = 302px가 됩니다.
여기에 내부 요소의 간격, 너비 등의 조절로 인해
소폭 감소된 298px로 결정된 것을 확인할 수 있었습니다.
물론 동일하게 max-width를 설정해도 되는 일이긴 하지만
인스타그램에서는 브라우저가 1001px width 아래로 resizing되면
아예 사이드바를 미표시하기에 따로 반응하도록 처리하지 않았습니다.

Feed Container

Section!

시맨틱 태그 중 section이라는 태그는 기본 block을 따라갑니다.

따라서 내부 각 영역의 최상위 태그를 section으로 정의하면

flex 속성을 굳이 정의하지 않아도 column 방향으로 흐를 것이라 생각했습니다.

Friends Header

인스타그램에서 피드영역 맨 위에는 팔로우한 친구 프로필 영역이 있습니다.

fixed만 걸리지 않는 navigation bar처럼 구성되어 있습니다.

흔한 Navigation bar에서 fixed만 해제한 것 같은 모습입니다.

justify-content를 쓰지 않은 것은 다음과 같은 이유에 있습니다.

친구 영역의 프로필들은 항상 시작점에서 출발하는 것을 확인했습니다.
즉, flex-start이고 기본값이기에 따로 선언할 필요가 없습니다.
여기에 더해 각 프로필은 li 태그 내부에서 구성되므로
li의 margin만 건드려주면 독립된 개체처럼 보이게 만들 수 있었습니다.

scroll Events

인스타그램은 friends 영역의 스크롤이 가능하므로 구현했습니다.

friendsFeeds 영역 다음에 새로 btnArea를 만들어주었습니다.

브라우저의 크기에 따라 위치의 너비 변동 가능성이 있으므로

relative 포지션과 top을 통해 위치를 잡아주었습니다.

1. list가 영역보다 작거나 같다면 버튼이 필요없다.
2. 영역보다 큰 경우?
  2-1. 시작점에서는 오른쪽 버튼만 보여야한다.
  2-2. 끝점에서는 왼쪽 버튼만 보여야한다.
  2-3. 시작점~끝점 사이의 범위에서는 둘 다 표시되어야한다.

위가 적용되어야할 조건이었습니다.

우선 list와 영역간의 width 비교가 필요합니다.

element.offsetWidth : border를 포함한 너비
 ::: 경계를 포함하므로 '포장지'의 너비입니다.
element.scrollWidth : scroll영역을 포함한 너비
 ::: scroll 영역을 잴 때 실제 scroll 영역의 너비입니다.
element.clientWidth : border, scroll을 포함하지 않는 너비
 ::: '포장지' 안쪽의 너비입니다.
 ::: 레이아웃에 적용하면 친구 프로필이 표시되는 창입니다.

따라서 overflow-x : scroll이 적용된 영역에 scroll 이벤트를 달고 내용을 정의했습니다.

ulWidth : 실제 스크롤될 영역
scrollEndPos : 스크롤 영역의 끝점
scrollLeft : 현재 스크롤 중인 위치

*** Round를 적용한 이유 ***

scrollLeft는 소수점이 적용된 값이 출력되었습니다.
반면, width들은 정수로 나오는데, 여러번 테스트해보니 반올림된 값으로 출력됩니다.
따라서 scrollLeft도 반올림으로 적용하여 단위를 맞추었습니다

스크롤의 시작점에서는 nextBtn만,
스크롤의 끝점이라면 prevBtn을,
범위 사이에 있다면 두 버튼을 모두 출력합니다.

scrollWidth는 만약 스크롤할 영역이 없다면 clientWidth와 동의어가 됩니다.

즉, 작거나 같은 경우는 항상 scrollWidth===clientWidth 이고,

이 때는 nextBtn을 감춥니다.

로딩시, 만약 scrollWidth가 영역보다 더 긴 경우
자동으로 nextBtn이 표시되어야합니다.
따라서 기본값에는 visibility를 설정하지 않은 상태에서
페이지 접근시 width를 검사하여 표시하거나, 표시하지 않게 만든 로직입니다.

Feeds

각 피드는 크게 보면 5개 영역, 잘게 쪼개면 6개 영역으로 나뉩니다.

이미지와 dots만 함께 묶이고 나머지는 각각 영역이 존재하며, 실제 인스타그램도 위와 같은 구조처럼 되어있습니다.

Feed Profile

프로필 영역에는 이미지, 아이디 및 이름, 더 보기 버튼이 있습니다.

특이사항이라면 이미지, 텍스트 영역이 시작점에 있고

버튼이 끝점에 위치해야하므로 내부가 2가지 영역으로 나뉩니다.

좌측 영역

display:flex;
flex-direction:row;
flex-basis:550px
.....~

우측 영역

align-self:center

좌측 영역에 대해 flex-basis를 썼지만, 이 영역들을 감싸는 flex에
space-between으로 정렬을 해도 됩니다.

영역의 height는 이미지와 텍스트 등으로 자연스럽게 정해지도록 딱히
건드리지 않았습니다.

Feed Img

여기서는 img를 담는 div 태그를 하나 만들고

해당 div태그의 background-image를 이용했습니다.

업로드되는 이미지들은 너비와 높이가 천차만별이므로

이미지 영역 Container

height:550px

이미지 영역

background-size:cover;
background-repeat:no-repeat
height:100%

심플하게 해당 영역에 꽉차게끔만 설정했습니다

다만 위의 경우는 사진이 한개만 있는 경우이기에

많은 사진이 업로드됐다고 생각하면,

<div>
  <img/>
  <img/>
  <img/>
</div>

예를 들어 위와 같은 구조라면

1. 최상위 태그가 보여줄 영역을 정의하고 (width, height)
2. img 태그의 너비, 높이를 최상위 태그에 맞춘다음
3. 최상위 태그에 overflow를 적용하고
4. JS에서 transform:translateX()를 이용한다

이 4가지 아이디어를 통해 구현할 것입니다.

또한 이와 관련된 부분이 dots입니다.

dots는 이미지와 붙어 함께 움직이며, 현재 보고있는 이미지가 파란색으로 보여야합니다.

1. 이미지가 DB로 부터 날아오면
2. 이미지와 dot에 순서대로 key나 name속성으로 고유값을 부여하고
3. transform이 발생할 때마다 고유값을 비교해
4. 파란색/회색으로 색 전환을, 크기 변화를 주는 등이 가능하다.

현재는 1개의 사진만 올라와있으므로

display:flex;
flex-direction:row;
justify-content:center

중앙 정렬만 해두었습니다.

하단은 그동안 했던 것들의 반복일 뿐입니다.

좌측 / 우측 영역으로 나눠 버튼을 배치한다던가..

위 아래 각각 영역을 구분하고 눈에 보기 좋게끔 간격을 넣어주기만 했습니다.

핵심 학습 포인트

display:flex 활용의 중요성이야 계속 언급하고 있는 것이고,

댓글의 갯수, 이미지의 너비와 크기 등이 있는 이런 동적인 구조는

static한 값을 거의 '무조건' 지양하는게 옳다라고 느꼈습니다.

'굳이 요소의 width나 height를 지레짐작할 필요가 전혀 없다.'

각각 영역을 하나의 페이지인 것 처럼 여기면서

내부의 독립적인 객체들을 건드려 부모의 영역은 알아서 따라가게 만드는 것이 훨씬 설계에 자유로웠습니다.

실제로 구현 초기, Feed 전체 영역의 height를 static하게 잡아두었다가

댓글 달기 테스트에서 텍스트가 외곽으로 벗어났던 실수가 있었습니다.

실제 인스타그램은 '더 보기' 버튼을 활용하거나 다른 페이지로의 라우팅, 
또는 모달 출력 방식이 적극적으로 채용되어 있습니다.

마무리

기능을 만드는 것만큼 CSS를 적절히 활용하는 것 또한

중요성이 뒤지지 않는다는 것을 몸소 체험하는 레이아웃 클로닝이었습니다.

자기 반성도 많이 했고, 레이아웃을 짜는 능력이 적어도 계단 한개 만큼은
늘지 않았을까? 싶은 시간이었습니다.

profile
제가 그린 것으로 하여금, 동기를 일으키는 개발자가 되고 싶습니다.

0개의 댓글