본문 바로가기
www/CSS_tip

CSS 레이아웃을 배웁시다 #1

by 랭님 2014. 1. 1.

목차



이 사이트에서는 모든 웹 사이트의 레이아웃에 사용되는 CSS의 기초를 다룹니다.

이곳에서는 여러분이 선택자와 프로퍼티, 값이 무엇인지 알고 있다고 가정합니다. 그리고 레이아웃 작업이 여러분을 짜증 나게 만드는 작업일 수도 있겠지만 이미 한두 가지 레이아웃을 알고 있다고 가정합니다. HTML과 CSS를 처음부터 배우고 싶다면 이 튜토리얼을 참고하세요. 그렇지 않다면 이 튜토리얼이 여러분의 다음 프로젝트에 도움될 수 있을지 알아봅시다.

레이아웃 없음

페이지에 콘텐츠가 기다란 한 줄로만 나오게 하고 싶다면 아무런 레이아웃을 지정하지 않는 방법도 괜찮습니다. 하지만 사용자가 브라우저 창을 굉장히 넓게 키운다면 콘텐츠를 읽기가 굉장히 불편해질 것입니다. 각 줄이 끝날 때마다 다음 줄로 가려면 오른쪽에서 왼쪽으로 먼 거리를 움직여야 하니까요. 브라우저 크기를 조정해서 이게 무슨 의미인지 확인해 보세요!

이 문제를 해결하기에 앞서 굉장히 중요한 display 프로퍼티에 관해 확실히 알아봅시다.


"display" 프로퍼티

display는 CSS에서 레이아웃을 제어하기 위한 가장 중요한 프로퍼티입니다. 모든 엘리먼트에는 엘리먼트의 유형에 따라 기본 표시값이 있습니다. 대부분의 엘리먼트에 대한 기본값은 보통 block이나 inline입니다. 블록 엘리먼트는 블록 레벨 엘리먼트라고 부를 때도 있으며, 인라인 엘리먼트는 늘 인라인 엘리먼트라고 부릅니다.

block

<div>

div는 표준 블록 레벨 엘리먼트입니다. 블록 레벨 엘리먼트는 새 줄에서 시작해 좌우로 최대한 늘어납니다. 자주 볼 수 있는 다른 블록 레벨 엘리먼트로 p와 form이 있으며, HTML5에서 새로 추가된 엘리먼트로 header와 footersection 등이 있습니다.

</div>

inline

span은 표준 인라인 엘리먼트입니다. 인라인 엘리먼트는 단락 안에서 <span> 이처럼</span> 해당 단락의 흐름을 방해하지 않은 채로 텍스트를 감쌀 수 있습니다. 링크에 사용하는 a 엘리먼트는 가장 흔히 볼 수 있는 인라인 엘리먼트입니다.

none

흔히 볼 수 있는 또 한 가지 display 값은 none입니다. script와 같은 일부 특별한 엘리먼트에서는 none을 기본값으로 사용하기도 합니다. 이 값은 자바스크립트에서 엘리먼트를 실제로 삭제하고 재생성하지 않고도 엘리먼트를 보이고 감추는 데 흔히 사용됩니다.

이것은 visibility와 다릅니다. display를 none으로 설정하면 엘리먼트가 마치 존재하지 않는 것처럼 페이지가 렌더링됩니다. visibility: hidden;으로 설정하면 엘리먼트가 감춰질 테지만 해당 엘리먼트는 완전히 보이지 않게 되더라도 여전히 공간을 차지합니다.

다른 display 값

list-item과 table 같은 다른 좀 더 특이한 display 값도 있습니다. 전체 목록은 이곳을 참고하세요. inline-block과 flex에 대해서는 나중에 살펴보겠습니다.

보충 내용

앞에서 언급했듯이 모든 엘리먼트에는 기본 표시 타입이 지정돼 있습니다. 하지만 언제든지 이러한 기본값을 재정의할 수 있습니다! 인라인 div를 만드는 것은 적절하지 않겠지만 이를 이용해 특별한 시맨틱을 지닌 엘리먼트의 표시 방식을 조정할 수 있습니다. 흔히 볼 수 있는 예로 가로 메뉴를 만들기 위해 인라인 li 엘리먼트를 만드는 것이 있습니다.

margin: auto;

#main {
  width: 600px;
  margin: 0 auto; 
}
<div id="main">

블록 레벨 엘리먼트의 width를 설정하면 컨테이너의 좌우 가장자리로 늘어나지 않게 할 수 있습니다. 그런 다음 좌우 마진을 auto로 설정해 해당 엘리먼트를 컨테이너 안에서 가로 중앙에 오게 할 수 있습니다. 엘리먼트는 여러분이 지정한 너비를 차지할 테고, 나머지 공간은 두 마진에 균등하게 나눠질 것입니다.

브라우저 창이 엘리먼트 너비보다 좁을 때 유일하게 문제가 발생합니다. 브라우저에서는 페이지에 가로 스크롤바를 만들어 이 문제를 해결합니다. 그럼 이 같은 상황을 개선해 봅시다...

</div



max-width

#main {
  max-width: 600px;
  margin: 0 auto; 
}
<div id="main">

이러한 상황에서 width 대신 max-width를 사용하면 브라우저가 작은 창을 처리하는 방식을 개선할 수 있습니다. 이것은 사이트를 모바일 환경에서도 사용할 수 있게 만들 때 중요합니다. 이 페이지의 크기를 조절해서 어떻게 바뀌었는지 확인해 보세요!

그나저나 max-width는 IE7+를 비롯한 주요 브라우저에서 모두 지원되므로 안심하고 사용하셔도 됩니다.

</div


박스 모델

너비에 관해 이야기하는 김에 너비와 관련해서 반드시 알아둬야 할 박스 모델에 대해 이야기하겠습니다. 엘리먼트의 너비를 설정할 경우 해당 엘리먼트는 실제로 여러분이 설정한 것보다 크게 나타날 수 있습니다. 이것은 엘리먼트의 테두리와 패딩이 지정된 너비 이상으로 엘리먼트를 늘리기 때문입니다. 다음 예제를 보시면 너비값을 동일하게 설정했는데도 결과적으로 크기가 다릅니다.

.simple {
  width: 500px;
  margin: 20px auto;
}

.fancy {
  width: 500px;
  margin: 20px auto;
  padding: 50px;
  border-width: 10px;
}
<div class="simple">

저는 더 작습니다...

</div>
<div class="fancy">

그리고 전 더 커요!

</div>

오랫동안 이 문제의 해법은 너비값을 조절하는 것이었습니다. CSS 코드를 작성하는 사람들은 패딩과 테두리를 빼는 식으로 늘 원하는 것보다 작은 너비값을 지정해왔습니다. 다행히도 이제 더는 그렇게 하지 않아도 됩니다.


box-sizing

오랜 시간에 걸쳐 사람들은 너비값을 조절하는 해법이 그다지 만족스럽지 않다는 사실을 깨닫고 box-sizing이라고 하는 새로운 CSS 프로퍼티를 만들어냈습니다. 엘리먼트에 box-sizing을 지정하면 해당 엘리먼트의 패딩과 테두리가 더는 너비를 늘리지 않습니다. 다음은 이전 페이지와 동일한 예제이지만 두 엘리먼트에 모두 box-sizing: border-box;를 지정했습니다.

.simple {
  width: 500px;
  margin: 20px auto;
  -webkit-box-sizing: border-box;
     -moz-box-sizing: border-box;
          box-sizing: border-box;
}

.fancy {
  width: 500px;
  margin: 20px auto;
  padding: 50px;
  border: solid blue 10px;
  -webkit-box-sizing: border-box;
     -moz-box-sizing: border-box;
          box-sizing: border-box;
}
<div class="simple">

이제 크기가 같아졌어요!

</div>
<div class="fancy">

야호!

</div>

이 방법이 훨씬 더 낫기 때문에 페이지 상의 모든 엘리먼트가 항상 이런 식으로 동작하게 만들고 싶은 분들도 있습니다. 그런 분들은 페이지에 다음과 같은 CSS 코드를 집어넣습니다.

* {
  -webkit-box-sizing: border-box;
     -moz-box-sizing: border-box;
          box-sizing: border-box;
}

이렇게 하면 모든 엘리먼트가 항상 이처럼 더 직관적인 방식으로 크기가 지정됩니다.

box-sizing은 다소 근래에 생긴 프로퍼티라서 지금 당장은 예제에서 한 것처럼 -webkit-이나 -moz- 접두사를 붙여야 합니다. 이 기법은 특정 브라우저에서 실험적인 기능들을 활성화하는 데 사용됩니다. 아울러 이 기법은 IE8+에서만 사용할 수 있다는 점도 염두에 두세요


position

좀 더 복잡한 레이아웃을 만들기 위해서는 position 프로퍼티에 관해 살펴볼 필요가 있습니다. position 프로퍼티에는 다양한 값을 설정할 수 있으며, 각 값의 이름은 제대로 지어지지 않아서 기억하기가 불가능합니다. 그럼 지금부터 하나씩 살펴보기로 하고, 이 페이지를 즐겨찾기에 추가해 둬야 할 수도 있습니다.

static

.static {
  position: static;
}
<div class="static">

static은 기본값입니다. position: static;이 설정된 엘리먼트는 그다지 특별한 방식으로 위치가 지정된 것이 아닙니다. 정적(static) 엘리먼트는 위치가 지정된 것이 아니라고 표현하며, static이 아닌 다른 값으로 지정된 엘리먼트에 대해 위치가 지정됐다고 표현합니다.

</div>

relative

.relative1 {
  position: relative;
}
.relative2 {
  position: relative;
  top: -20px;
  left: 20px;
  background-color: white;
  width: 500px;
}
<div class="relative1">

relative는 별도의 프로퍼티를 지정하지 않는 이상 static과 동일하게 동작합니다.

</div>
<div class="relative2">

상대 위치가 지정된 엘리먼트에 top이나 rightbottomleft를 지정하면 기본 위치와 다르게 위치가 조정됩니다. 다른 콘텐츠는 해당 엘리먼트에서 남긴 공백에 맞춰 들어가게끔 조정되지 않을 것입니다.

</div>

fixed

<div class="fixed">

안녕하세요! 아직은 저한테 관심을 보이지 마세요.

</div>

고정(fixed) 엘리먼트는 뷰포트(viewport)에 상대적으로 위치가 지정되는데, 이는 페이지가 스크롤되더라도 늘 같은 곳에 위치한다는 뜻입니다. relative와 마찬가지로 top이나 rightbottomleft 프로퍼티가 사용됩니다.

페이지의 우측 하단 구석에 고정된 엘리먼트가 있다는 사실을 눈치채셨을 겁니다. 이 엘리먼트를 눈여겨보세요. 다음은 이 엘리먼트를 그 자리에 놓이게 만든 CSS 코드입니다.

.fixed {
  position: fixed;
  bottom: 0;
  right: 0;
  width: 200px;
  background-color: white;
}

고정 엘리먼트는 평소대로라면 있었을 법한 공백을 페이지에 남기지 않습니다.

모바일 브라우저의 경우 고정 엘리먼트 지원이 굉장히 불안정합니다. 이와 관련된 사항은 이곳에서 좀 더 자세히 확인하실 수 있습니다.

absolute

absolute는 가장 다루기 까다로운 위치 지정 값입니다. absolute는 뷰포트에 상대적으로 위치가 지정되는 게 아니라 가장 가까운 곳에 위치한 조상 엘리먼트에 상대적으로 위치가 지정된다는 점을 제외하면 fixed와 비슷하게 동작합니다. 절대 위치가 지정된 엘리먼트가 기준으로 삼는 조상 엘리먼트가 없으면 문서 본문(document body)을 기준으로 삼고, 페이지 스크롤에 따라 움직입니다. "위치가 지정된" 엘리먼트는 positionstatic으로 지정되지 않은 엘리먼트를 가리킨다는 사실을 기억하세요.

다음은 간단한 예제입니다.

.relative {
  position: relative;
  width: 600px;
  height: 400px;
}
.absolute {
  position: absolute;
  top: 120px;
  right: 0;
  width: 300px;
  height: 200px;
}
<div class="relative">

이 엘리먼트는 상대 위치가 지정돼 있습니다. 이 엘리먼트가 position: static;이었다면 절대 위치가 지정된 자식 엘리먼트는 이 엘리먼트에서 빠져나와 문서 본문을 기준으로 상대 위치가 지정됐을 것입니다.

<div class="absolute">

이 엘리먼트에는 절대 위치가 지정돼 있습니다. 부모 엘리먼트를 기준으로 상대 위치가 정해져 있지요.

</div>
</div>

여기서 배운 내용은 꽤나 까다롭지만 멋진 CSS 레이아웃을 만드는 데 필수적인 내용입니다. 다음 페이지에서는 좀 더 실전 예제에서 position을 사용해 보겠습니다.