콘텐츠들의 방향성을 정의하는 속성입니다. 크게 인라인, 블록 흐름이 있죠. 인라인과 블록의 흐름을 각자 제어하는 것이 특징입니다.
하이픈 앞의 값은 inline flow direction이고, 하이픈 뒤의 값은 block flow direction입니다.
h1 {
writing-mode: vertical-rl;
}
기존에는 모든 흐름이 물리적인 측면에서 일반적으로 방향이 고정되었던 top-left에서 시작되었습니다.
그러나 이제는 좀 더 논리적이고 명확하게 속성을 명시할 수 있는 것입니다.
몇가지 예로 width, height은 각각의 요소가 따르는 흐름에 따라 사이즈를 맞춰주는 inline-size
, block-size
등으로 대체되고
horizontal-tb 모드에서 margin-left는 margin-block-start가 되고, left가 block-start가 되는 식입니다.
.box {
inline-size: 150px;
}
.logical {
margin-block-start: 20px;
padding-inline-start: 2em;
padding-block-start: 2px;
border-block-start: 5px solid pink;
border-inline-end: 10px dotted rebeccapurple;
border-block-end: 1em double orange;
border-inline-start: 1px solid black;
}
더 논리정연하지만 우리나라의 현실상 IE를 지원해야하므로 writing-mode에 부수적으로 따라와야하는 다른 속성들이 잘 지원되지 않는 IE까지 지원하기에는 무리가 있습니다.
우리가 아무 것도 설정하지 않았을 때 브라우저가 만드는 흐름입니다. 코드의 순서대로 쌓이기 때문에 html을 잘 구조화하는 것이 필요한 이유입니다.
각각의 html 엘리먼트가 가지고 있는 속성이므로 normal flow를 결정짓는 속성이라고 할 수 있습니다.
inline과 block에 관한 내용은 이전 포스트에 상세히 기술되어 있습니다.
1차원 레이아웃 기법으로 row 혹은 column방향으로 배치를 할 수 있습니다.
부모 컨테이너가 flex로 설정되면 직계 자식 요소들은 자동으로 flex-item이 됩니다.
.wrapper {
display: flex;
}
.wrapper > div {
flex: 1;
}
2차원 레이아웃 기법으로 동시에 row와 column을 제어합니다.
.wrapper {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-template-rows: 100px 100px;
grid-gap: 10px;
}
flex, grid가 나오기 전에 전통적으로 오랫동안 사용되어 온 속성입니다.
normal flow에서 벗어나 line box를 만들어냅니다. 즉, 원래 normal flow상태일 때만 동작합니다.
이는 새로운 bfc의 시작이며, line-box는 float 속성을 가진 요소들만 관리합니다.
즉, flow요소와 아닌 요소가 같이 있다면 서로 다른 bfc에 존재한다는 것입니다.
또한 돔구조에 관계없이 인라인 요소를 밀어내도록 작용하므로 block요소는 아래 이미지처럼 파란 영역은 float의 영향을 받고 밀려나지 않지만 그 안에 있는 텍스트 인라인 요소는 float에 밀려서 표현된 것을 알 수 있습니다.
line-box는 어느 방향이던, 그 방향의 마지막요소보다 더 그 방향쪽으로 나아갈 수 없으며 마지막 요소가 끝나는 지점부터 그려지기 시작합니다.
또 이미 그려진 영역은 새로운 요소가 그려질 영역에서 계산 제외되며, 수직방향의 기준은 가장 마지막 line-box 바로 아래에 그려집니다.
.wrapper {
float: left;
}
출처: mdn
레이아웃 전체에 float를 주고 싶은 것이 아니라 일부 영역에만 주려는 경우가 더 많겠죠. 처음부터 부모 컨테이너에 float의 영역을 주고 시작한 것이 아니었기 때문에 우리는 다음 요소에게 이제부터 너는 float의 영역이 아니야 라고 선언해 주어야 합니다.
또, 자식 요소들을 전부 float로 만들었을 때, 부모 요소가 높이값을 전혀 가지고 있지 않은 현상을 볼 수 있습니다. 이는 float 요소가 normal flow에서 빠져 나왔기 때문에 부모 컨테이너가 인식할 수 없습니다.
이들을 효과적으로 제어하는 3가지 방법이 있습니다.
float 부모요소에 clearfix 클래스를 부여합니다. 그러면 저 뜻대로 그 부모요소의 마지막 요소를 만들어서 그 요소가 clear를 합니다. after를 써야하는 상황이 아니라면 유용하게 잘 쓰입니다.
.clearfix::after {
content: "";
clear: both;
display: block;
}
overflow: auto
를 주어 block formatting context를 새로 설정하므로 다음 요소들과 분리시켜 줍니다. 보다 쉬운 방법 같지만 새로운 bfc를 만든다는 것은 브라우저에게 계산을 하나 더 시키는 꼴입니다. overflow는 line-box를 인식하므로 부모에게 overflow를 주면 (visible은 동작하지 않음) float를 자식으로 인식하는 효과가 있습니다. float 요소들 사이에 사용하면 line-box들에게 영역이 잘립니다.
.wrapper {
background-color: rgb(79,185,227);
padding: 10px;
color: #fff;
overflow: auto;
}
새롭게 나온 display 속성입니다. 그래서 원하는 기능이 깔끔하게 지원되지만 IE에서는 지원을 하지 않습니다. ㅠ
.wrapper {
background-color: rgb(79,185,227);
padding: 10px;
color: #fff;
display: flow-root;
}
포지셔닝은 normal flow에서 타겟 엘리먼트를 떼어 와서 다른 위치에 정밀하게 넣기 위함입니다. 이는 메인 레이아웃용이 아니라 특정한 요소의 위치를 세밀하게 조정할 때 필요합니다.
위치를 세밀하게 조절하기 위해 top, bottom, left, right의 기준점이 있으며 이 기준에서부터 정한 설정값에 위치합니다.
또한 이들은 기존 흐름에서 벗어나서 새로운 레이어를 형성하는 것과 같기에 요소들끼리 서로 겹칠 수 있고,
같은 position 속성을 가진 요소들의 레이어 순서를 바꿀 수 있는 것은 z-index 속성입니다. 값이 클수록 위로 올라옵니다.
.positioned {
z-index: 3;
}
normal flow에서 동작하는 것과 같은 일반적인 모습입니다. 다른 position들을 설정했다가 해제할 때 유용하게 쓰이겠네요.
.positioned {
position: static;
}
static과 동일한 영역을 차지하지만, 다른 요소와 겹쳐서 최종 위치에 놓을 수 있다는 점이 다릅니다. 기준점은 normal flow였을 때 본인의 위치입니다.
.positioned {
position: relative;
top: 20px;
right: 0;
}
원래 자신의 영역을 차지하지 않고 새로운 레이어로 분리되면서 position 속성(static이 아닌)을 가진 가장 가까운 부모 엘리먼트가 기준점입니다. 하지만 좌표를 설정하지 않으면 돔 구조상의 바로 위 부모를 기준점으로 0,0 에 위치합니다. position이 명시된 부모가 없다면 이 엘리먼트가 뷰포트 크기의 initial containing block을 만들어 위치를 잡습니다. 명세에서는 table, th, td 기준으로도 기준점이 된다고 되어 있지만 실제 브라우저에서는 올바르게 동작하지 않습니다.
.positioned {
position: absolute;
top: 20px;
right: 0;
}
absolute처럼 동작하지만 뷰포트를 기준점으로 잡습니다. 그래서 스크롤을 해도 요소가 움직이지 않습니다.
h1 {
position: fixed;
top: 0;
}
relative와 fixed를 왔다갔다하는 속성입니다. 최신 거라서 그런지 IE는 지원이 되지 않네요. 자신의 영역으로 올 때까지는 relative이다가 자신의 영역을 넘어서 아래로 스크롤이 되면 fixed로 성격이 바뀝니다.
.positioned {
position: sticky;
top: 30px;
left: 30px;
}
offset은 reflow를 하고 계산된 거리값을 의미합니다. 따라서 이 값은 조회 전용이지 수정할 수 있는 값이 아닙니다.
offsetLeft - 부모기준으로 얼마나 떨어졌는지
offsetTop - 부모기준으로 얼마나 떨어졌는지
offsetWidth - 뷰포트에서 보이는 컨텐츠의 크기
offsetHeight - 뷰포트에서 보이는 컨텐츠의 크기
offsetScrollTop - scroll이 위에서부터 얼마나 움직였는지
offsetScrollLeft - scroll이 왼쪽에서부터 얼마나 움직였는지
offsetScrollWidth - 진짜 컨텐츠의 크기
offsetScrollHeight - 진짜 컨텐츠의 크기
레거시 코드지만 여전히 css가 잘 지원되지 않는 이메일 코딩 등에서는 유효하게 사용되는 레이아웃 기법입니다. 굳이 예시를 들진 않지만 일반 table들을 겹쳐서 구조를 짠다고 생각하면 됩니다.