본문으로 바로 이동 페이지 설정으로 이동 메뉴로 이동
페이지 설정
  • 어떠한 의견도 좋습니다. 웨버스터디가 더 나은 모습이 되도록 의견을 보내주세요.

float 레이아웃

최초 작성일
최종 수정일
이번 시간에는...
CSS 레이아웃을 위해, 지난 시간에 배운 float, clear, overflow를 이용해서 요소의 가로 정렬 하는 방법을 알아봅니다. 이를 통해 float를 해제하는 방법과 overflow:hidden의 특성, float의 중첩 등을 살펴 봅니다.

이번 시간에는 저번 시간에 살펴본, float, clear, overflow 속성들을 이용하여, 기본적으로 요소를 배치하도록 해보겠습니다.

일단, 가장 기초적인 배치부터 해보도록 하겠습니다.

기본적인 float 배치

나란히 놓인 정사각형 형태의 요소들
기초적인 float 배치 예시

이러한 배치는 아주 자주 있는 일입니다. 이미지 슬라이드라던가, 콘텐츠를 가로로 나열하거나 하는데 자주 사용됩니다. 또한 다단의 레이아웃 역시 결국은 이를 기본으로 응용해서 만들어지는 것입니다.

일단, 이를 만들기 위해서 마크 업부터 작성해보도록 합시다. 최대한 간단히 만들어 보겠습니다.

간단하게, div.float-frame으로 전체를 감싸는 요소를 만들고, 그 안에 div.float-unit 여러 개로 배치할 요소들을 만들었습니다.

먼저, 전체를 감싸는 div.float-frame에 배경색과 테두리를 주고, 안에 여백을 조금 주도록 하겠습니다.

그 다음에 div.float-unit에 스타일을 주도록 하죠. 일단 네모난 형태를 만들기 위해서, 너비를 주고 다른 스타일들을 주도록 하겠습니다.

이로써 일단 네모난 형태의 배치 요소의 스타일을 줬습니다. 하지만, 아직은 가로로 나란히 있지 않고, 세로로 배치되어있습니다. 아주 당연합니다. 기본적으로 블록요소는 너비에 상관없이 줄 바꿈이 되도록 되어있기 때문이죠.

이제 float 속성을 이용해서 가로로 나란히 오도록 만들겠습니다. div.float-unitfloat:left;를 추가해주세요.

그리고 나서, 브라우저를 새로 고침 하도록 합시다. 먼가 이상하다는 것을 눈치 채셨나요? 네, 바로 div.float-frame이 먼가 이상합니다. 아까까지만 해도, div.float-unit들을 잘 포함한 높이 값을 가지고 있던 요소가 지금은 굉장히 높이가 작아졌습니다. div.float-unit하고는 전혀 따로 놀고 있습니다. 그나마 div.float-frame에 아까 padding을 줬기 때문에 그나마 높이가 한 20px정도를 유지하는 것입니다. 아마 padding 값 마저 없었다면, border만 남은 채 아무런 높이를 가지지 않은 요소가 되었을 것입니다.

부모 요소가 자식을 포함하지 못한채 높이가 줄어들었습니다.
float된 자식 요소를 인식하지 못하는 부모 요소

왜 이렇게 된 걸까요?

float라는 속성은 전에 살펴봤지만, 기본적으로 요소가 띄워지게(floating) 만드는 속성을 가지고 있습니다. 그렇기 때문에 요소가 띄어진 상태에서는 그의 부모 요소(div.float-frame)가 해당 요소(div.float-unit)를 인식하지 못합니다. 오로지 float되지 않은 요소들만 인식하여 포함합니다.

float된 요소를 포함하기 위한 방법

그렇다면 이를 해결하기 위한 해결책으로는 무엇이 있을까요?

부모 요소의 높이 값 조절

일단 가장 먼저 생각할 수 있는 방법은 작아진 div.float-frame 요소에 직접 높이 값(height)를 주도록 하는 것입니다. 안에 띄어진 요소들 만큼의 높이 값을 준다면, 분명 마치 안에 포함된 것처럼 보일 것입니다.

하지만, 이것은 깔끔한 방법이 아닙니다. 일단 마치 요소를 포함한 것처럼 보이지만, 요소를 포함한 것이 아니기 때문에, 안에 띄어진 요소의 높이 값이 달라진다면, div.float-frame의 높이 값 역시 같게 조절해야만 합니다. 이게 그나마 앞선 예시처럼 안의 요소들의 높이가 고정이라면 다행이지만, 내용의 양에 따라 더 길어질 수 있다면, 이 방법은 전혀 도움이 안될 것입니다.

float를 해제시킬 임의의 요소 삽입

또 다른 방법으로는 좀 더 근원적인 방법입니다. 기본적으로 부모 요소는 float 속성이 들어가지 않은 요소만을 인식합니다. 그렇다면, 띄어진 요소 다음에 띄어지지 않은 요소를 넣게 된다면 부모 요소는 이를 인식할 것입니다. 그럼 다음과 같이 빈 요소를 넣어보도록 하겠습니다.

div.float-unit들 다음에 div.clear라는 빈 div 요소를 추가했습니다. (요소는 span이나 br로 넣기도 합니다.) 하지만, 비어있는 요소이기 때문에 그 자체로 높이 값이 없으며, 심지어 실은 떠있는 요소 보다 아래에 위치하지도 않습니다. 떠있는 요소 뒤로 깔려 있게 됩니다. 만약 다음처럼 어느 정도 임의의 높이 값을 주고, 배경 색을 지정해보면, 보다 확실히 알 수 있습니다.

div.clear에 높이를 주어 보이게 했지만, 이 요소는 float된 요소 밑에 깔려버립니다
div.clear에 높이 20px을 주고, 갈색 배경을 넣은 모습, float을 준 요소들 아래에 위치하지 않고 뒤로 들어갔습니다.

이와 같이 블록 요소는 기본적으로 float된 요소를 인식하지 못합니다. float된 요소를 인식하는 것은 텍스트들과 인라인 요소, 그리고 float된 요소 뿐입니다.

여기서 우리는 이 div.clear요소를 떠있는 요소 아래로 위치시킬 수 있는 속성을 하나 배웠습니다. 네, 바로 clear 속성입니다. 이 속성은 float를 해제하여 새롭게 줄 바꿈을 시작해 줍니다. div.clearclear:both 속성을 넣어주도록 합니다. 그리고 아까 임의로 넣은 높이 값과, 배경 색을 없애보면, 정확히 의도하는 대로 보여지는 것을 확인할 수 있습니다. (참고로 만약 span같은 인라인 요소를 사용했다면, display:block 속성을 추가하여, 블록 요소처럼 만들어 주셔야 합니다. 또는, span대신 br 요소를 사용할 수도 있습니다.)

이 방법을 통해서는 보다 근원적인 해결책을 가져다 주기 때문에, 띄어진 요소의 높이가 늘어나더라도, 이제 div.float-frame가 알아서 인식합니다.

아주 깔끔한 방법이긴 하지만, 한가지 께름칙한 부분이 있습니다. 바로 비어있는 임의의 요소를 넣어야 한다는 것이죠. 물론 비어있는 divspan 요소를 넣는 일은 종종 부득이하게 생길 수 있으며, 그 자체로 사실 별 문제가 되진 않습니다. 하지만 HTML에 외형을 위한 요소를 넣었다는 점이 웹 표준의 관점에서 아무래도 께름칙하게 느껴질 수 있습니다.

overflow를 이용한 방법

이번엔 또 다른 방법입니다. 이 방법은 임의의 요소를 넣지 않으면서도, 부모 요소가 떠있는 요소들을 인식하게 만들어 줍니다. 바로 'overflow' 속성을 이용한 방법으로, 부모 요소(div.float-frame)에 'overflow:hidden' 속성을 넣어 주는 것입니다.

이렇게 되면, 신기하게도 부모 요소가 떠있는 요소를 인식합니다. (속성 값에 hidden이 아닌, auto를 줘도 같은 효과를 받습니다만, 사실 해당 요소의 높이 값이 지정 안된 경우에 주는 auto는 hidden과 동일한 효과를 보입니다.) 이는 overflow:hidden이 조금 독특한 특성을 가지고 있기 때문입니다.

overflow:hidden의 특성

overflow:hiddenoverflow:visible 때에는 인식하지 못 했던 몇 가지를 인식하게 합니다. 그 중에 하나가 방금 살펴본 float처리된 요소이고, 다른 하나는 자식 요소의 margin 입니다.

만약 visible이고 내부 여백(padding)과 테두리(border)가 없는 상태에서 자식요소가 margin-top을 가지고 있을 경우, 마치 요소 자신의 margin-top처럼 보여집니다. 하지만, hidden인 상태에서는 그 margin-top이 자신의 요소 안에서 이뤄집니다. 물론 부모 요소가 해당 margin에 상응하는 padding이나, border를 가지고 있다면, hidden 처럼 인식할 수 있습니다.

다음의 예시는, 세가지 요소들에 각각 overflow:visible, overflow:hidden, border-width:1px를 준 뒤, 자식 요소에 margin:10px를 적용한 모습입니다. overflow:hidden과 테두리를 적용한 요소에서는 자식 요소의 margin 값 만큼, 내부 여백이 생긴 반면, 맨 위 visible의 경우, 내부 여백이 아닌, 바깥 여백으로 표현되고 있습니다.

이 부분은 언뜻 이해가 되지 않으시더라도, 나중에 더 작업을 하다 보면 자연스럽게 알 수 있는 부분이니, 잘 읽히지 않는다면 넘어가셔도 좋습니다.

'margin: 10px' in visible
'margin: 10px' in hidden
'margin: 10px' in border

어쨌든 이 방법은 임의의 요소도 추가하지 않고 잘 인식하기 때문에, 아주 좋은 방법으로 보이지만, 그럼에도 약간의 문제점은 가지고 있습니다.

그 중에 한가지는 IE7 이하에서는 작동하지 않습니다. IE7 이하에서는 이 속성으로는 띄어져 있는 요소를 인식하지 못합니다. 하지만, IE7에서 대응할 수 있는 방법은 있습니다. 바로 전에 display:inline-block에서 잠깐 다뤘던 zoom:1 속성입니다. 이 zoom:1을 넣게되면, overflow:hidden과 거의 비슷하게 보여줍니다.

그리고 또 하나의 문제가 있습니다. 이는 지금 다룰 수 있는 문제는 아니지만, 레이어 같은 형태를 만들었을 때, 레이어의 위치가 해당 요소의 밖으로 넘어섰을 때, 레이어가 가려지는 문제를 가지고 있습니다. 다만 아직까지는 레이어를 어떻게 만드는지 조차 알지 못하기 때문에, 이에 대한 얘기는 나중에 다시 좀 더 다루도록 하겠습니다.

일단 기초적인 float 배치는 여기서 마무리 하도록 하겠습니다.

중첩된 float 배치

이번엔 다음과 같은 형태를 만들어 보도록 하겠습니다.

나란히 놓은 정사각형 안에 4개의 정사각형이 각각 안에 들어가 있는 모습
중첩된 float 배치 예시

단순하긴 하지만, 잘 보시면, float:left 안에 또 float:left가 된 형태입니다. 물론 만드는 것 역시 어렵지 않습니다. 다음이 마크 업 입니다.

큰 구역을 두 개로 만들고, 그 안에 작은 영역들을 만들었습니다. 이제, 이 HTML 소스를 가지고 스타일을 넣어보겠습니다.

일단, div.float-frame은 아까 썼던 스타일을 그대로 사용하겠습니다. 이제 div.big-area부터 스타일을 주도록 하죠.

여기서 보면 일단 float:left를 주고, 너비를 100px를 주었습니다. 그리고 색상과 여백을 주었습니다. 그 다음 div.small-unit에 스타일을 주도록 하겠습니다.

너비와 높이는 margin에 1px를 줬기 때문에 48px로 주었습니다. 이렇게 스타일을 주고 나서 브라우저에서 새로 고침을 해보도록 하겠습니다.

아마 제대로 의도한대로 잘 보여질 것입니다. 여기서 혹시 한 가지 의문점을 발견하신 게 있으신가요?

네 보면 div.big-areaoverflow:hidden이나 별다른 clear:both 처리를 안 했음에도 요소를 잘 포함하고 있습니다. 별도로 높이 값을 주지도 않았고요. 이를 통해서 float된 요소는 내부의 float된 요소를 인식한다는 사실을 알 수 있습니다.

그리고 또 한가지 알 수 있는 것은, 띄어진 요소가 너비가 100px에 맞춰서 더 이상 가로로 늘여지지 않고, 자동으로 줄 바꿈 처리가 되었다는 사실입니다. 이렇게 띄어진 요소는 띄어진 요소 서로간을 인식하고 그 다음으로 위치합니다. 이는 나중에 배울 position으로 배치하는 것 간의 차이점이 되는데요, 이 부분은 다음에 다시 다루도록 하겠습니다.

float 레이아웃 예시
/attach/demo/css-2/float-layout.html
모바일의 경우 새창열기로 확인 가능합니다.
새창열기

정리

이로써 float을 이용해서 요소를 배치하는 방법을 살펴보았습니다. 사실 이 float을 이용한 스타일은 은근히 초보자에게 파악하기 어려운 문제 상황을 자주 만들어 줍니다. 이번에 다룬 내용 만으로, float에 대해 완전히 이해하기는 힘드실 것입니다. 하지만 float 스타일을 줄 때, (clear:both또는 overflow:hidden을 통해서) 스타일을 준 요소의 상위 요소가 해당 요소를 온전히 감쌀 수 있도록 하는 습관을 들인다면, 레이아웃을 잡는 일은 전혀 어려운 일이 아닐 것입니다. 이 챕터 마지막에 다시 한번 float을 이용한 다단 레이아웃을 좀 더 다뤄 보도록하고 이번 시간은 마무리하겠습니다.

요점 정리
  • 블록 요소를 가로로 나란히 정렬하기 위해서는 float을 이용
  • float된 요소는 기본적으로 상위 요소가 영역을 파악하지 못함 (float가 요소를 띄움)
  • float는 띄어지기 때문에, 보통 다음 블록 요소는 float된 요소 밑에 깔리게 됨.
  • 블록 요소는 기본적으로 float을 인식하지 못함. 텍스트, 인라인 요소, 그리고 float된 요소만 다른 float요소를 인식 함.
  • float된 요소를 부모 요소가 포함하기 위해, height로 임의의 높이 값을 줄 수 있지만, 내부 float 요소의 높이 바뀔 때마다 직접 바꿔줘야 함.
  • float된 요소들 다음에 비어있는 div에 clear:both 속성을 주어 부모가 높이를 자동으로 인식하게 할 수 있음.
  • float된 요소들의 부모 요소에 overflow:hidden을 줄 경우, 부모 요소는 float된 요소를 인식.
  • overflow:hidden은 자식 요소의 margin 값도 내부로 인식하게 함.
  • float된 요소의 부모가 float 될 경우, 부모 요소는 자식 요소를 인식 함.
  • float 될 경우, 기존 블럭 요소처럼 너비가 넓게 퍼지지 않음. 기본적으로 내부 영역 만큼의 너비를 가짐.

이 글이 유용하셨다면 친구들에게 공유 해주세요.