CSS를 그저 basic styling을 위해서 사용할 때, 즉 타이포그래피를 목적으로한다면 썩 어려운 언어는 아닐지 모른다. 하지만 CSS의 또 다른 용도인 레이아웃 디자인의 영역에 들어서면 tree의 상속적인 복잡성때문에 혀를 내두를지도 모른다.
CSS가 레이아웃 디자인 영역까지 활발히 사용되기 이전인 1990년대, 페이지를 구성하는 레이아웃에는 선택지가 몇 없었다. 레이아웃을 만들 수 있는 방법은 HTML에서 table tag를 통해 행과 열을 만드는 것 뿐이었다. 문서의 구조를 보여주는 마크업언어인 HTML로 두마리 토끼(content과 presentation)를 잡으려다보니 내용과 디자인은 구분되지 못하고 항상 얽혀있었다. 디자인을 조금 수정하려면 내용의 중요한 부분들까지 건들여야하는 문제가 생겨 효율성이 떨어지는 것이다.
Float-based layout
사실 float도 layout에 쓰라고 만들어진건 아니었다. 그래서 항상 문제가 발생했다.
float은 본디 아래와 같이, 신문처럼 글자들과 어울려 이미지를 한쪽에 배치하기 위한 속성이었다.
그런데 2000년대에 접어들어 사람들은 float을 이미지 뿐 아니라 오만 element에 적용하지 시작했다. 마찬가지로 원래 목적과 다른 쓰임새였기 때문에 통일된 방식은 정해지지 못하다가 2006년, float을 이용한 레이아웃을 정형화한 그 이름도 대단한 'The holy grail' 예수의 성배 가 발표되었다.
이 레이아웃을 구성하기 위해선 몇가지 꼼수가 필요했다. margin을 음수값으로 둔다든지, clear: both
속성을 사용한다든지, 비율을 맞추기 위해 좀 번거로운 계산까지 해야했다.
단점은 위 사진에서 볼 수 있듯이 명백하다. main, nav, aside의 height가 모두 들쭉날쭉이다. 스크린 높이를 100% 채우지 못하는데, float이라는 속성 자체가 콘텐츠를 왼쪽 끝 또는 오른쪽 끝에 닿도록 하기 위한 것일 뿐이라는 것을 생각하면 어쩔 수 없는 노릇이었다.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Modern CSS</title> <link rel="stylesheet" href="index.css"> </head> <body> <header>This is the header.</header> <main> <h1>This is the main content.</h1> <p>...</p> </main> <nav> <h4>This is the navigation section.</h4> <p>...</p> </nav> <aside> <h4>This is an aside section.</h4> <p>...</p> </aside> <footer>This is the footer.</footer> </body> </html>
/* FLOAT-BASED LAYOUT */ body { padding-left: 200px; padding-right: 190px; min-width: 240px; } header, footer { margin-left: -200px; margin-right: -190px; } main, nav, aside { position: relative; float: left; } main { padding: 0 20px; width: 100%; } nav { width: 180px; padding: 0 10px; right: 240px; margin-left: -100%; } aside { width: 130px; padding: 0 10px; margin-right: -100%; } footer { clear: both; } * html nav { left: 150px; }
Flexbox-based layout
flex 속성은 2009년도에 처음 발표되었지만 제대로 사용되기 시작된건 2015년부터이다. flex는 처음부터 각 행과 열의 얼마를 차지할지 정의하기 위해 만들어진 속성이었고, 따라서 더이상 float를 이용해 꼼수를 부리지 않아도 되게 되었다.
flexbox를 기반으로 하는 레이아웃은, 구성하고자 하는 내용 전체를 포함하는 **<div>
tag가 하나 더 필요하다.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Modern CSS</title> <link rel="stylesheet" href="index.css"> </head> <body> <header>This is the header.</header> <div class="container"> <!--main, nav, aside를 한데 묶어주는 div--> <main> <h1>This is the main content.</h1> <p>...</p> </main> <nav> <h4>This is the navigation section.</h4> <p>...</p> </nav> <aside> <h4>This is an aside section.</h4> <p>...</p> </aside> </div> <footer>This is the footer.</footer> </body> </html>
/* FLEXBOX-BASED LAYOUT */ body { min-height: 100vh; display: flex; flex-direction: column; } .container { display: flex; flex: 1; } main { flex: 1; padding: 0 20px; } nav { flex: 0 0 180px; padding: 0 10px; order: -1; } aside { flex: 0 0 130px; padding: 0 10px; }
레이아웃을 위한 속성이 추가되니 이보다 좋을 수 없었지만 단점도 분명 있었다. 첫째는 브라우저가 지원하지 않는 다는 점(지금은 거의 다 해결되었다), 둘째는 CSS 코드를 위해 HTML을 변경해야한다는 점이다. 가장 큰 단점은 직관적이지 못하다는 점이다. 코드를 보았을 때 각 element가 얼마를 차지할지 확인할 수 있어야하는데 flex를 이용한 레이아웃을 그려내려면 거듭 추측하고 확인해야한다.
또한 flexbox는 한 줄의 행 또는 열을 구성하기 위해 설계되었기 때문에 페이지 전체를 구성하기에는 분명히 무리가 있었다.
Grid-based layout
grid 속성은 2011년에 나왔지만 브라우저 호환성은 2018년 초가 되어야 안정화되었다. 결과물은 flex와 크게 다를바 없지만, 코드 자체만으로 명확하게 레이아웃을 표현할 수 있게 되었다. 처음으로 완벽하게 레이아웃 디자인을 위한 CSS 속성이 나온 것이다!
/* GRID-BASED LAYOUT */ body { display: grid; min-height: 100vh; grid-template-columns: 200px 1fr 150px; grid-template-rows: min-content 1fr min-content; } header { grid-row: 1; grid-column: 1 / 4; } nav { grid-row: 2; grid-column: 1 / 2; padding: 0 10px; } main { grid-row: 2; grid-column: 2 / 3; padding: 0 20px; } aside { grid-row: 2; grid-column: 3 / 4; padding: 0 10px; } footer { grid-row: 3; grid-column: 1 / 4; }
grid 발표 이후, 이전 개발자들이 float와 flex를 쓰며 이래도 되는건가.. 싶어 차마 구현하지 못했던 것을 마음껏 만들어낼 수 있게 되고, layout이 더 다양화되었다고 한다.