본문으로 건너뛰기

"layout" 태그로 연결된 2개 게시물개의 게시물이 있습니다.

모든 태그 보기

One true layout 만들기

· 약 4분

One true layout

Header, Navigation, Aside, Section, Footer 로 이루어진 레이아웃을 만들 시에 float 을 사용해서 구성할 경우 틀어짐을 잡는 방법에 대한 내용이다.

원문으로 보이는 링크에서는 진정한 하나의 레이아웃을 찾는 과정 중 하나이며 Eqaul Height Columns - revisited로 소개되고 있다.

이슈

아래와 같은 레이아웃에는 footer 영역이 섹션에 붙어 올라온다.

<style>
body {
width: 1000px;
margin: 0 auto;
}
#aside {
float: left;
width: 200px;
}
#section {
float: left;
width: 800px;
}
</style>
<body>
<div id="header">header</div>
<div id="nav">nav</div>
<div id="wrap">
<div id="aside">
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi sed
sollicitudin mauris. Aliquam faucibus facilisis vulputate. Curabitur
condimentum placerat mattis. Duis at metus at tellus volutpat ultrices.
Cras lorem eros, cursus et risus sit amet, gravida feugiat libero.
Nullam id faucibus ipsum. Nulla a leo sed eros mattis bibendum. Nullam
et sapien in orci tempus elementum eu sed augue. Pellentesque eu
vestibulum arcu. Pellentesque vel finibus libero. Nulla facilisi.
Quisque dolor enim, ornare eget elit ac, pharetra porta ex. Vivamus
eleifend eu arcu nec consequat.
</p>
</div>
<div id="section">
<p>
Nam pulvinar dictum nibh id ullamcorper. Suspendisse justo eros, tempor
vel faucibus in, pellentesque congue enim. Proin non eleifend turpis,
vel commodo purus. Fusce vitae nisl dapibus, tincidunt elit at, cursus
lacus. Maecenas varius imperdiet sollicitudin. Nunc pharetra fringilla
enim ut facilisis. Curabitur maximus nibh non rhoncus semper. Duis
porta, purus ut tincidunt convallis, sem purus pharetra erat, eu
vestibulum tellus mi id eros. Fusce congue, erat at blandit mollis,
tellus ex semper velit, dapibus commodo ante turpis a neque. Fusce vel
ex id sem auctor accumsan. Maecenas finibus nunc sem, ut gravida felis
efficitur at. Pellentesque lobortis dui non ligula condimentum, at
auctor dui blandit.
</p>
</div>
</div>
<div id="footer">footer</div>
</body>

해결방안

overflow: hidden

래퍼에 이 속성을 넣는 것으로 해결 된다.

body {
width: 1000px;
margin: 0 auto;
}
#aside {
float: left;
width: 200px;
}
#section {
float: left;
width: 800px;
}
#wrap {
overflow: hidden;
}

clear: both

또는 래퍼를 삭제하고 구획을 나누는 부분에 sibling 노드로 clear: both 속성을 주면 된다.

<style>
body {
width: 1000px;
margin: 0 auto;
}

.clear {
clear: both;
}

#aside {
float: left;
width: 200px;
}
#section {
float: left;
width: 800px;
}
</style>
<body>
<div id="header">header</div>
<div id="nav">nav</div>
<div id="aside">
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi sed
sollicitudin mauris. Aliquam faucibus facilisis vulputate. Curabitur
condimentum placerat mattis. Duis at metus at tellus volutpat ultrices.
Cras lorem eros, cursus et risus sit amet, gravida feugiat libero. Nullam
id faucibus ipsum. Nulla a leo sed eros mattis bibendum. Nullam et sapien
in orci tempus elementum eu sed augue. Pellentesque eu vestibulum arcu.
Pellentesque vel finibus libero. Nulla facilisi. Quisque dolor enim,
ornare eget elit ac, pharetra porta ex. Vivamus eleifend eu arcu nec
consequat.
</p>
</div>
<div id="section">
<p>
Nam pulvinar dictum nibh id ullamcorper. Suspendisse justo eros, tempor
vel faucibus in, pellentesque congue enim. Proin non eleifend turpis, vel
commodo purus. Fusce vitae nisl dapibus, tincidunt elit at, cursus lacus.
Maecenas varius imperdiet sollicitudin. Nunc pharetra fringilla enim ut
facilisis. Curabitur maximus nibh non rhoncus semper. Duis porta, purus ut
tincidunt convallis, sem purus pharetra erat, eu vestibulum tellus mi id
eros. Fusce congue, erat at blandit mollis, tellus ex semper velit,
dapibus commodo ante turpis a neque. Fusce vel ex id sem auctor accumsan.
Maecenas finibus nunc sem, ut gravida felis efficitur at. Pellentesque
lobortis dui non ligula condimentum, at auctor dui blandit.
</p>
</div>
<!-- clear:both 노드 추가 -->
<div class="clear"></div>

<div id="footer">footer</div>
</body>

CSS3 레이아웃

· 약 10분

CSS3

사용할 수 없는 브라우저에서 신규 문법은 무시된다.

BFC

Block Formatting Context이며 아래 조건에서 생성된다.

  • 루트 요소
  • float: right, left
  • position: absolute
  • display: inline-block
  • overflow 값이 visable 외에 다른 값일 때
  • flex item
  • grid item
  • table cell

layout

float

<style>
.box {
float: left;
}
/* 다음 세 가지 방법으로 container 안에 box 를 넣어줄 수 있다. */
.container {
overflow: hidden;
}
.container {
float: left;
}
.container {
display: flow-root;
}
</style>
<div class="container">
<div class="box">
<p>플로팅</p>
</div>
</div>
  • overflow: hidden 으로 플로팅 요소를 잡는 것은 box-shadow가 잘리는 등의 문제가 있다.
  • display: flow-root는 모던 브라우저에서만 지원한다.

position

  • static: 기본 값이다. 코드상 노출된 순서대로 표시된다.
  • relative: 오프셋(top, left...)와 함께 사용된다.
    • 새로운 컨테이너 블록이 되며 하위 absolute 를 가둘 수 있다 .
  • absolute: 흐름에서 벗어나며 자신이 포함된 컨테이너 블록의 가장자리를 기준으로 오프셋만큼 이동한다.
    • 별도의 컨테이너 블록이 선언되지 않았을 경우, viewport가 된다.
  • fixed: viewport를 기준으로 고정된다. 스크롤해도 변하지 않는다.
  • sticky: static + fixed 로 문서와 함께 스크롤 되다가 설정한 위치가 되면 고정된다.
    • 모던 브라우저에서만 지원한다.
<style>
.container {
width: 400px;
height: 400px;
}
/* 이 박스는 맨 위(viewport)에서 10 10 씩 떨어져있다. */
.box {
position: absolute;
top: 10px;
right: 100px;
width: 200px;
}

/* 컨테이너 블록으로 만들면 박스가 들어온다. */
/* .container { position: relative; width: 400px; height: 400px; } */
</style>
<div class="container">
<div class="box">
<p>absolute</p>
</div>
</div>

multi-column

column-count, column-width로 단 효과를 낼 수 있다.

<style>
.columes {
column-width: 200px;
column-count: 2;
}
</style>
<div class="columns">
<p>첫 번째 단</p>
<p>두 번째 단</p>
</div>

axis

  • 주축교차축이 있다.
    • 기본은 flex-direction: row이며 교차축은 수직이다.
    • flex-direction: column이면 교차축은 수평이다.
  • 아이템의 배치는 항상 교차축(cross axis)에서 이뤄진다.
  • 교차축 === 블럭축(block axis) 이다.
  • 그리드에서는 컬럼 축(column axis)이라고도 한다.

flexbox

1차원 레이아웃

  • display: flex 설정시 자식은 flex item이 된다.
  • flex item은 min-content로 설정한 너비보다 작아질 수 없으므로 컨테이너를 벗어난다.
    • min-content는 아이템 내부 단어 중 가장 긴 것을 기준으로 설정된다.
  • flex-wrap: wrap; 속성 설정 시 여러 줄에 걸쳐 표현된다.
  • 줄이 넘어가면 넘어간 줄이 flex container 가 된다.

플렉스 아이템 배치

  • align-items
    • stretch: 기본값으로 늘어난다.
    • flex-start: 요소가 컨테이너 상단에 붙는다.
    • flex-end: 바닥에 붙는다.
    • center: 중앙에 배치된다.
  • align-self: flex item 에서 위 속성을 덮는다.

플렉스 아이템 정렬

  • justify-content
    • flex-direction: row면 가로줄, column이면 세로줄에서 동작한다.
    • flex-start: 기본값
    • flex-end: 플렉스 컨테이너 끝에서부터 추가된다.
    • space-between: 아이템 사이의 공간을 똑같은 간격으로 설정한다.
    • space-around 모든 아이템 양쪽에 똑같은 간격의 마진을 설정한다.
    • space-evenly 모든 공백을 똑같이 설정한다.
      • 아이템-아이템 간 컨테이너-아이템 간의 간격이 똑같다.
    • center: 가운데 설정한다.
  • align-content
    • 교차축 위에서 동작한다.
    • flex-wrap: wrap이고 아이템 배치 공간보다 컨테이너가 길 때 사용할 수 있다.
    • 초기값은 start이다.
    • 나머지 동작은 justify-content와 같다.
  • margin-left: auto; 를 사용하면 원하는 아이템을 반대방향에 배치할 수 있다.

반응형 플렉스박스

  • flex-grow: flex-basis에 설정한 값보다 커질 수 있는지 설정한다.
  • flex-shrink: flex-basis에 설정한 값보다 작아질 수 있는지 설정한다.
    • 500px 컨테이너에 200px 플렉스 아이템이 3개 있다면 활성화시 영역 안에 들어올 것이다.
  • flex-basis: flex-direction 에 따라 너비나 높이의 기본값을 지정한다.
    • flex-basis: content: 주축의 컨텐츠 크기로 설정된다.
    • flex-basis: auto: 플렉스 아이템에 width 속성이 있다면 그 값을 flex-basis 로 사용한다. 특별한 경우가 아니라면 auto가 권장된다.
  • 보통 세 속성을 합쳐서 flex: 0 0 200px; 처럼 적는다.

플렉스박스 방향

플렉스박스와 그리드는 dir=ltr dir=rtl 속성에 좌,우 영향을 받는다.

  • flex-direction: row-reverse
  • flex-direction: column-reverse

grid

2차원 레이아웃

<style>
.container {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
/* grid-column-gap, grid-row-gap 축약 */
grid-gap: 20px;
/* 가장 최근 명세에서는 `grid-` prefix 가 빠졌다 */
gap: 20px;
}
</style>
<div class="container">
<div class="item">
<h2>grid 1</h2>
</div>
<div class="item">
<h2>grid 2</h2>
</div>
<div class="item">
<h2>grid 3</h2>
</div>
<div class="item">
<h2>grid 4</h2>
</div>
<div class="item">
<h2>grid 5</h2>
</div>
<div class="item">
<h2>grid 6</h2>
</div>
</div>

fr

  • fraction
  • 유연한 너비를 나타내는 단위이다.

그리드 트랙

  • 그리드의 열과 행을 나타낸다.

그리드 배치

프로그래머의 수는 0부터 시작이지만 그리드 배치에서는 1부터여야한다.

  • LTR 의 경우는 왼쪽 끝이 1 이다.
  • RTL 의 경우는 오른쪽 끝이 1 이다.
  • 반대편 끝은 -1 이다.
.container {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-gap: 20px;
}

.item1 {
grid-column: 1 / 3;
grid-row: 1;
}
.item2 {
grid-column: 3;
grid-row: 1;
}
.item3 {
grid-column: 1;
grid-row: 2 / 4;
}
.item4 {
grid-column: 2 / 4;
grid-row: 2;
}
.item5 {
grid-column: 2 / 4;
grid-row: 3;
}

grid-column: auto / span 2; 처럼 시작 위치를 auto로 잡고 끝 위치를 span 2로 잡으면 자동 배치 기능에 의해 그리드 아이템 위치는 자동으로 정해지고 너비는 항상 컬럼 두 개만큼 확장한다.

그리드 정렬

  • justify-items로 설정하며 각 영역 안에서 정렬된다.
  • 초기값은 stretch이다.

named area

  • 그리드에 이름을 직접 지정할 수도 있다.
  • .은 공백을 나타낸다.
  • 영역은 반드시 사각형이여야한다.
  • align-items, justify-items 속성 변경시 반복이 무시된다. (stretch가 아니므로)
.container {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-gap: 20px;
grid-template-areas:
"a a b"
". d d"
"c e e";
}

.item1 {
grid-area: a;
}
.item2 {
grid-area: b;
}
.item3 {
grid-area: c;
}
.item4 {
grid-area: d;
}
.item5 {
grid-area: e;
}

반응형 그리드

  • auto-fill: 너비가 허용하는만큼 최대한 많이, 다만 아이템 갯수가 부족하면 빈 공간을 남긴다.
  • auto-fit: 아이템 갯수가 부족하면 남은 공간은 균등하게 분배된다.
  • minmax: 너비의 최소, 최대크기를 지정할 수 있다.
    • 아래 예시라면 200px 의 컬럼이 몇 개 들어가는지 계산한 뒤, 남은 공간을 컬럼에 균등하게 분배된다.
.container {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
/* 컨텐츠에 따라 그리드가 길어진다. */
grid-auto-rows: minmax(150px, auto);
}

그리드 흐름

  • grid-auto-flow 속성으로 조절한다.
    • row: 기본값이며 왼쪽 위부터 오른쪽으로 칸을 채워나간다.
    • column: 줄을 채우고 다음 컬럼을 채운다.
    • dense: 빈 공간에 채워넣는다.
    • sparse: 기본값이며 빈 공간을 내버려둔다.

이 외에 order 속성으로 직접 순서 제어가 가능하다. 다만 denseorder는 탭 순서까지 변경해주지 않아 접근성을 벗어난다.

supports

구 브라우져와의 호환을 위해 @supports (display: grid) 처럼 서포트 피쳐쿼리를 사용할 수 있다.