코드스피츠 CSS Rendering 6회차 정리 (STEP 48)

Display Model, Flexbox

image

STEP 48

코드스피츠76 CSS Rendering - 6회차 강의를 보고 정리한 내용입니다.

💡 CSS 모듈은 어떤 개념을 배우고자 할 때 관련된 지식을 유기적으로 쭉~ 배워야 잘 이해할 수 있다.

✍️ Display Model

  • Display: ‘표시’가 아닌 ‘레이아웃’. CSS에서 Geometry를 결정할 때 쓰는 알고리즘을 구성하는 역할. (참고: CSS에서 Geometry를 계산하게 하는 것은 display와 position 밖에 없다.)

Display Group

  • Display에는 방대한 스펙이 들어있어 다음과 같은 그룹으로 나뉘어 속성이 관리되고 있다.
    • outside inside listitem internal box legacy
  • 사실 말이 속성이지 Geometry를 계산하는 함수와 같은 것들이다.

1️⃣ outside

Normal Flow를 관리하는 속성 그룹이다.

  • block (ex. display: block)
  • inline
  • run-in: 경우에 맞춰 block이 됐다가 inline이 됐다가 한다. (잘 쓰지 않음)

Normal Flow

  • BFC: 줄 단위로 위치를 지정하는 알고리즘
  • IFC: 글자단위로 옆으로 위치를 지정해주는 알고리즘
  • RP(Relative Position): BFC, IFC로 계산이 끝난 후 그 상태에서 realative하게 위치를 옮겨주는 알고리즘. position: relative를 선언해주면 된다. 코드스피츠76 CSS Rendering - 1회차 정리 문서 참고

2️⃣ listitem

  • list-item: 태그를 li(st)처럼 그려달라는 스펙 (ex. display: list-item)

예전엔 html 태그가 디자인 속성까지 내포하고 있었다. 지금은 list-style이라는 CSS로 분리되었지만 1,2,3 / 동글뱅이 등의 li 스타일을 html 태그가 가지고 있었던 때가 있었다. 그래서 list-item과 같은 속성이 존재하는 것이다. 여전히 디자인까지 담겨있는 태그가 있긴 하다. 바로 table이다. 태그 자체에 표처럼 그려지는 그래픽 로직(디자인)이 담겨있다.

3️⃣ box

  • none: 안 보이게 하고 싶을 때(box를 무시하라)
  • contents: 자신의 box model을 무시한다. 부모의 자식처럼 튀어나오게 하는 효과가 있다. 박스를 그리는 html을 버리고 native(OS)의 요소로 대체해서 그리는 것을 말한다.
    • 예를 들어, grid 셀 안에 grid 요소가 있을 때, 내부의 grid 요소에 contents를 주면 부모 grid 셀 요소를 대체한다.
    • native(OS)로 대체된 것이 마치 부모를 무시하고 그려진 것처럼 보인다.

🏷️ 대상이 되는 태그들(기본값이 contents인 태그들)

br, wbr, meter, progress, canvas, embed, object, audio, iframe, img, video, frame, frameset, input, textarea, select, legend, button, details, fieldset

select 박스의 디자인은 OS마다 다르다. 이처럼 박스를 그리는 html을 버리고 native 요소로 그리는 것은 contents이다.(원래 html은 박스로 그림<?)

img도 박스 모델이 아니다. 로딩 이후에 크기가 변하기 때문에 박스 모델이 아니다.(html 태그 중엔 이런 요소가 없다.)

4️⃣ inside

contents layout

  • 바깥 부모 입장에서 나를 어떻게 정의하는가?
  • 이 안을 table로 그려라. 이 안을 grid로 그려라 라는 것.
  • 앞에 block이라는 말이 생략된 것이나 마찬가지이다.
  • 바깥쪽은 block, 안쪽은 grid

🏷️ 속성 종류

  • flow (상황에 따라 BFC를 만들지 말지 결정하게 하는 것. CSS에서 flow는 normal flow와 관련지어 생각하기!)
  • flow-root (이 시점부터 새로운 BFC를 시작한다는 것)
  • table
  • flex
  • grid
  • subgrid
  • ruby

지금까지는 바깥쪽 부모의 입장에서 스타일 준 요소(나)를 어떻게 봐야하는가 였다. 내가 block이라는 뜻은 부모가 날 보기에 block이라는 뜻이다. 그렇다면 안쪽에서의 관점은 어떻게 정의할까? 이제 공부할 것(-> legacy)

5️⃣ legacy

inline contents layout

  • display에 2개의 속성을 한꺼번에 부여하고 싶어 만들어진 스펙
  • -로 이어 2개의 속성을 한번에 준다.
  • 옛날 스펙의 잔재이다.
  • inline-table: 바깥쪽은 inline 안쪽으론 table

table은 기본적으로 block이라 table 옆에 글자가 붙어 그려지지 않는다. 하지만 inline-table을 주면 table 옆에 글자가 붙을 수 있다.(인라인인 table을 만들고 싶다면 inline-table 사용할 것)

6️⃣ internal

table & ruby

  • outside, inside는 요소 자신의 입장에서 얘기했다. internal은 좀 다르다. 예를 들어 grid로 지정된 요소 안은 grid 아이템들이 된다. 이 아이템들 입장에서 속성을 지정하는 것이 internal이다.

image

  • table-cell, table 자체 외에는 대부분 대체 가능하다.

float 배웠던 내용 복기

  • float left, right를 쓰면 float가 inline 가드 역할은 수행하지만, block 요소를 잘라먹지 않는다. (float는 위에 둥둥 떠있기 때문이다.)
<div
  style="width:200px;height:200px;background:red;opacity:.5;float:left"
></div>
<div style="background:blue;"></div>

image

  • 새로운 BFC로 block 요소를 자르고 싶다면? overflow: hidden을 주면 된다. overflow는 auto가 아닌 값을 가지면 무조건 새로운 BFC를 만들어내기 때문이다. flow-root도 이와 비슷한 기능을 한다.(이를 사용하면 언제든지 새로운 bfc 영역을 만들 수 있다.)
<div
  style="width:200px;height:200px;background:red;opacity:.5;float:left"
></div>
<div style="background:blue;overflow:hidden"></div>
<div
  style="width:200px;height:200px;background:red;opacity:.5;float:left"
></div>
<div style="background:blue;display:flow-root"></div>

image

정리

  • Display 모델은 6개의 그룹이 있다. 이번 문서에서 각각 그룹의 의미, 역사적 쓰임에 대해 배웠다.
  • 특정 엘리먼트가 부모에서 어떻게 배치되는지(outside), 엘리먼트 내부 아이템들은 어떻게 배치할건지(inside), outside와 inside를 한번에 정의할 수 없다면(legacy), 태그와 연결된 것들(list-item, contents), 옛날 방식의 자식들을 태그가 갖고 있어서 어쩔 수 없이 쓰는 것(internal)

✍️ Flexbox

CSS Flexible Box Layout Module

https://drafts.csswg.org/css-flexbox-1/

  • display: flex 또는 display: inline-flex를 주면 그 안쪽이 flex 영역으로 선언된다.
  • 그 안에 있는 모든 아이템은 flex-item이다. (부모가 flex이기 때문) (단, 자식의 자식은 flex-item이 아니다. 직계의 자식까지만 flex가 상속된다.)
  • flex box는 기본적으로 한 줄만 그린다.
  • flex-line: flex-item을 배치하는 가상의 선
  • main-axis: flex-line이 진행하는 방향의 축. 기본축
  • cross-axis: main-axis와 직교하는 축

image


flex-direction

flex-direction을 이용해 축을 바꾸거나 flex-item이 배치되는 방향을 바꿀 수 있다.

  • default(기본): 왼쪽->오른쪽, 위->아래
  • row-reverse: 오른쪽->왼쪽, 아래->위 (그림을 보면 여러줄인 것 같지만 flex-item은 한줄만 커버한다.)

🏷️ 축을 바꾸는 방법

  • column: 위->아래, 왼쪽->오른쪽 배치 / main 축이 y축이 되고 cross-axis 축이 x축이 된다.
  • column-reverse: 위->아래, 오른쪽->왼쪽

image


정렬

따로 언급하는 경우를 제외하고 flex-direction이 default인 상태를 기반으로 설명할 것이다.

justify-content

justify-content: 메인축을 기준으로 정렬

🏷️ justify-content에 올 수 있는 값들

  • flex start: (flex-direction에 따라 설정된 것을 기준으로) start에 정렬
  • flex end: (flex-direction에 따라 설정된 것을 기준으로) end에 정렬
    • 예를 들어, flex-direction이 column-reverse라면 flex start는 아래, flex end는 위일 것이다. (메인축이 기준임을 기억!)
  • center: 메인축의 가운데로 모는 것
  • space-between: flex-box 사이사이에 여백을 지정하는 것
  • space-around: 양쪽 끝에도 여백을 둘 수 있게 지정하는 것

image

  • 위 그림에서 회색 공간은 빈 공간을 의미한다.
  • flex-start의 경우 메인축을 기준으로 왼쪽에 모여있는 것을 볼 수 있다.

align-items

align-items: cross-axis에서 정렬할 때는 align-items라는 속성을 쓴다.

  • 예를 들어 main-axis는 x축일 때, cross-axis인 y축 방향으로는 flex-item들을 어떻게 정렬할지 결정하는 것이 align-items이다.
  • (flex는 한 줄만 그린다는 것 기억하기)

🏷️ align-items에 올 수 있는 값들

  • flex-start
    • cross-axis를 기준으로 할 때, flex-start는 위이다.(위->아래니까) 만약 flex-direction이 row-reverse라면, flex-start는 아래로 몰릴 것이다.
  • flex-end
  • center
  • baseline: 글씨의 baseline을 맞춰서 정렬해준다.(문자 g가 오면 baseline이 또 달라지겠지)
  • stretch: 꽉 채우는 것

image

  • 만약 flex direction이 column이라면(main-axis가 y축으로 바뀜) 위 그림을 90도 꺾어서 바라봐야 이해가 쉬울 것이다.

grid-start, grid-end로 바꾸면 이 속성들은 grid에서도 쓸 수 있다. CSS Box alignment module level3 스펙을 따르기 때문이다.


flex-wrap

flex box는 기본적으로 한 줄로 그려지지만 여러 줄 그리고 싶다면?

  • nowrap(default): 옆으로만 계속 그린다.
  • wrap: 부모의 사이즈에 맞춰 사이즈가 모자르면 다음줄에 가서 flex line을 다시 그린다. flex line을 어떻게 그리냐면, 현재 flex line에서 가장 하단이 큰 요소 밑에 line을 그리게 된다.
  • wrap-reverse

align-content

  • flex-wrap에 적용되는 속성
  • wrapping시 flex line을 어떻게 정렬할 것인지

image


flex-item

지금까지는 flex box를 공부한 것이다. 그 내부에 flex-item에 대해 알아보자.

order 속성

order를 이용하면 flex-item의 순서를 바꿀 수 있다.

<div style="display:flex">
  <div style="order:2">a</div>
  <div style="order:1">b</div>
</div>
  • a라고 적힌 div가 먼저 나왔음에도 b라고 적힌 div가 먼저 배치된다. (order 때문!)
  • flex box는 이렇게 html을 바꾸지 않아도 order를 이용해 순서를 자유롭게 바꿀 수 있다.

flex box는 GPU가 그린다. 그래서 빠르다. dom 렌더링이 아닌 post process 방식으로 그림을 그리기 때문이다. 그림을 모두 그린후 gpu로 올려서 그리는 것이다. dom의 구조를 바꾸지 않으니 reflow가 일어나지 않고 repaint만 일어나 빠르다.

align-self 속성

image

align-self를 사용하면 예를 들어 flex-start로 정렬된 요소들에서 특정 요소만 flex-end로 바꾸는 것이 가능하다. (대신 align-self는 align-items에만 유효. justify-content에서는 적용될 수가 없음)

etc

flex box 영역에서 flex-item이 얼만큼의 크기를 가질 수 있는지

  • flex-grow: 땡겨서 늘릴 때 어디까지 늘릴 수 있는지
    • 0(기본값): 100%를 차지
    • 1: flex box의 flex item을 균등배분한 값
  • flex-shrink: 축소해 찌그러트릴 때 얼만큼 작아질 수 있는지
    • 1(기본값): 밀리지 않고 자신의 크기 유지
  • flex-basis(기본값)
    • auto: content (flex box 안에 있는 컨텐츠의 크기가 나의 크기)
    • flex-basis를 주지 않고 width, height를 주면 이게 기본값이 된다.

flex-grow, flex-shrink보다 max, min이 우선적으로 적용된다.

  • flex-grow, flex-shrink, flex-basis 속성을 한꺼번에 주는 방법
    • flex: initial: 기본적으로 flex하지 않음. 축소는 안되고 확장만 된다.
    • flex: auto: flex-grow만큼 커지거나 flex-shrink만큼 축소될 수 있게 동작한다.
    • flex: none: flex에 반응하지 않고 고정크기를 유지한다.
    • flex: 1~: 1 1 1 1 이렇게 주게 되면 자식이 1개만 있더라도 그 자식의 크기는 1/4로 표현된다.

Comment

팀원들 결과물

References