본문 바로가기
CSS 레이아웃 - Float 속성을 이용한 레이아웃 만들기 #JS HTML PHP

http://wireframe.tistory.com/entry/CSS-%EB%A0%88%EC%9D%B4%EC%95%84%EC%9B%83-Float-%EC%86%8D%EC%84%B1%EC%9D%84-%EC%9D%B4%EC%9A%A9%ED%95%9C-%EB%A0%88%EC%9D%B4%EC%95%84%EC%9B%83-%EB%A7%8C%EB%93%A4%EA%B8%B0

*예전에 작성했던 강좌의 마지막 부분입니다. CSS를 통해 이전 강좌에서 작성한 마크업에 모양새를 입히기 전에 한 번 복습 하는 의미로 참고하면 좋겠네요


float 속성



이번 시간에는 css를 통해 레이아우팅을 할 때 가장 중요한 요소인 float에 대해서 살펴보도록 하겠습니다. css의 float 속성은 margin이나 position 속성과 함께 레이아웃을 만드는 가장 기본적인 원리 입니다. 우선 대략 다음의 코드를 가진 HTML 문서를 생각해보겠습니다.

<body>
  <div id="spDiv">content of DIV whose id is "spDvi"</div>
  <div id="norDiv">blah~ blah~ * 100 </div>
</body>
body엘레멘트 내부에 두 개의 div 엘레멘트가 들어있습니다. 이 들에는 각각 텍스트로 된 컨텐츠를 포함하고 있지요. 이를 도식으로 나타내면 대략 다음과 같을 겁니다. (정확한 스크린샷이 아닌 도식적으로 나타낸 그림입니다.)
사용자 삽입 이미지

위에 그림에서 볼 수 있듯이 div 엘레멘트는 하나의 블럭으로 디스플레이되고, 하나의 엘레멘트가 위치한 아래쪽으로 그 다음 엘레멘트가 위치하게 됩니다. 따라서  스타일 시트에서 다음과 같이 spDiv의 폭을 줄여준다면 어떻게 될까요?
#spDiv{
    width:300px;
}

폭만 줄어든 div 태그의
block으로 디스플레이되기 때문에 옆 공간은 모두 여백이 되고 아래쪽에서 다음 div 엘레멘트가 시작되어 위치합니다. float는 이러한 공간의 낭비를 줄여줄 수 있는 속성입니다. 엘레멘트를 '띄워서' 여백이 공간을 차지하는 것을 없앱니다. 예를 들어 신문이나 잡지 등에서 사진의 옆으로 글이 이어지다가 사진이 끝나는 부분에서는 글이 지면의 왼쪽으로 튀어나오는 것을 볼 수 있을 것입니다. float는 바로 그러한 레이아웃을 가능하게 하는 겁니다. 예를 들어
p img{
    float:left;
}

와 같이 준다면 p 엘레멘트 안에 위치한 이미지 파일은 그러한 잡지의 사진처럼 보이겠지요.
그럼 예시 코드를 갖고 해보도록 하겠습니다. 스타일시트에서 다음과 같이 float 속성을 추가하겠습니다. left라 함은 왼쪽으로 붙어 띄운다는 의미입니다.

#spDiv{
    width:300px;
    float:left;
}
이렇게 하면 예상할 수 있듯이 아래와 같은 모양이 될 것입니다. (두번째 div 엘레멘트가 왼쪽으로 좀 삐져나간 것은 애교입니다.) 또한 아래 그림에서 주의할 것은 텍스트가 채운 영역을 표기하기 위해 테두리선을 그렸지만 실제로 두번째 div 엘레멘트의 박스모양은 사각형입니다. float 속성을 첫번째 spDiv에 부여함으로서 두번째 norDiv 엘레멘트는 그 시작점(왼쪽 위 모서리)이 spDiv와 같은 지점이 됩니다.
float 속성을 부여, '어울림' 배치를
그럼 두 번째 엘레멘트인 norDiv의 폭을 500px로 줄인다면 어떤 결과가 될까요? 간단합니다. 폭이 줄어들었다뿐이지 위와 동일한 모양이 됩니다. 따라서 아래 그림과 같은 레이아웃을 만들기 위해서는 오른쪽으로 보내고자하는 norDiv 엘레멘트에 대해서 다음과 같이 스타일시트에서 float 속성을 지정해주면 됩니다. 이때 left 값을 주어도 현재로서는 같은 결과를 기대할 수 있습니다.
#norDiv{
    width:500px;
    float:right;
}

이제 두 박스 엘레멘트는 대략 다음과 같이 위치하게 됩니다. (폭의 픽셀값의 대한 상대적 크기는 역시 애교입니다.) 이 두 엘레멘트는 현재 float 속성을 받고 있습니다. 하나는 왼쪽으로 붙어서 떠 있고, 다른 하나는 오른쪽으로 붙어서 떠 있는 상태라 할 수 있습니다. 만약 두 번 째 엘레멘트에 float:left라고 지정해도 같은 결과를 볼 수 있습니다이는 float 속성을 부여 받은 엘레멘트는 '위로 떠올라' 그 다음에 나오는 엘레멘트와 겹치게 되지만, 실제로 컨텐츠가 보이는 영역을 밀어내는 작용을 하기 때문입니다. 하지만 float 속성을 부여받고 위로 떠오른 엘레멘트들 끼리는 서로 겹침이 없이 밀어 내게 되는 것입니다.
float 속성을 이용 2단으로
그럼 세번째 div 태그를 하나 추가해보도록하겠습니다. 그럼 어떻게 될까요?

<body>
  <div id="spDiv">content of DIV whose id is "spDvi"</div>
  <div id="norDiv">blah~ blah~ * 100 </div>
  <div id="thirdDiv">
</body>
float 속성이 없는 텍스트를
세번째 div 엘레멘트인 thirdDiv는 float 속성이 없습니다. 단지 그 보다 앞서 등장한 두 개의 div 엘레멘트들은 float 속성을 받고 위로 떠 버렸습니다. 따라서 두 개의 엘레멘트를 무시하고 body의 왼쪽 상단에서 thirdDiv는 시작됩니다. 파란색의 ㄴ 자 모양의 블럭은 텍스트의 흐름을 뜻하는 것입니다. 실제 모양은 앞에서 말씀드린 바와 같이 그냥 박스입니다. 곧 두 개의 박스(spDiv, norDiv)는 float 속성을 부여받고 위로 떠올랐습니다. 떠오른 엘레멘트와 그렇지 않은 엘레멘트들은 서로 충돌하지 않습니다. 다만 나중에 등장한 (문서 상에서 뒤에 나오는) 엘레멘트는 그 보다 앞서 등장한 엘레멘트들이 차지하는 공간만큼 비켜주게 됩니다.  따라서 세번째 thirdDiv 엘레멘트는 시작은 왼쪽 위에서 하지만, 왼쪽 위의 공간은 spDiv가 차지하고 있습니다. 그 오른쪽에는 norDiv가 차지하고 있지요. 따라서 결국 위와 같은 모양으로 텍스트가 흐르게 됩니다. (조금 복잡한가요?)

여기서 재밌는 것은 이 엘레멘트들을 하나로 묶는 div 태그를 따로 사용하지 않았습니다. 따라서 이들의 상위 엘레멘트는 body가 됩니다.  즉 브라우저 화면의 크기에 따라 변동이 심할 수 있다는 것이지요. 만약, 브라우저 창이 충분히 넓다면 (혹은 spDiv,norDiv의 폭이 충분히 작다면) 다음과 같은 상황이 연출됩니다

float 속성이 없는 텍스트의 레이아웃

위의 그림에서 분홍색으로 하이라이트된 박스는 spDiv 이고 푸른색으로 하이라이트된 박스는 norDiv입니다. 두 개가 벌어지고 가운데 빈 공간이 생기자 세번째 thirdDiv의 내용이 그 틈새로 흘러들어갑니다. 그럼, norDiv에게 float:left 속성을 부여했다면 어떻게 될까요? 답이 나오나요? ㅎㅎㅎ

만약에 브라우저가 작아지거나 북마크 사이드바를 연다든지 해서 body의 폭이 충분히 작아진다면 황당한 결과물을 만날 수 있습니다. float 속성을 가지고 정해진 width 값을 가진 두 개의 박스의 전체폭의 합보다 body의 width 값이 작아진다면, 맨 처음 상황처럼 nodDiv는 아래로 밀리게 됩니다. (감싸고 있는 엘레멘트의 폭이 커지는게 아닙니다) 그랬을 때 세번째 thirdDiv의 내용은 norDiv보다 위로 올라갈 수도 있습니다. 누누히 말하지만 float 속성이 없는 thirdDiv는 float 속성이 있는 엘레멘트들을 무시하고 시작합니다. 그림으로 보자면 아래와 같이 되는 것이지요.
세번째 div가 맨위로 올라간

clear 속성



이러한 증상을 방지하기 위해서는 이들을 감싸는 상위 엘레멘트를 하나 만들어주고, width값을 지정해 주어야합니다. 그리고 두 엘레멘트가 나란히 표시되기를 원한다면 두 개의 박스의 폭의 값(width를 포함하여 margin, border, padding이 모두 포함된)을 계산하여 상위 엘레멘트의 내부폭(width값)을 넘지 않도록 해야합니다.

그렇다면 float 속성이 없는 thirdDiv 가 정상적으로 두 엘레멘트의 아래쪽에 위치하려면 어떻게 해야할까요? 그것은 float으로부터의 영향을 제거하는 clear:both 라는 속성을 스타일시트에서 부여하면 됩니다.

#thirdDiv{
    clear:both
}
이제 아래 그림과 같이 각각의 box 엘레멘트들이 얌전히 자기 자리를 찾은 것을 확인할 수 있습니다.
clear:both;
또한 clear 속성은 이것 이외에도 다른 부작용을 해결하는 좋은 수단이 됩니다. 다시 #thirdDiv 가 없던 때로 돌아가 보겠습니다.

<body>
  <div id="wrapper">
      <div id="spDiv">content of DIV whose id is "spDvi"</div>
      <div id="norDiv">blah~ blah~ * 100 </div>
  </div>
</body>
이 번에는 spDiv와 norDiv를 둘러싸는 wrapper라는 div 태그를 넣었습니다. 두 엘레멘트들의 부모엘레멘트가 되는 셈이지요. 이 wrapper라는 엘레멘트에는 폭과 '배경색'을 넣겠습니다. 어떻게 위치하는지를 살펴볼 속셈이거든요.
#wrapper{
    width:900px;
    background-color:#ffffc3; /*노란색입니다*/
}
float으로 떠오른 녀석들은 단순히 아래에 인접한 엘레멘트에만 영향을 미치는 것이 아니라 부모엘레멘트를 완전히 벗어나 버립니다. 아래 그림에서 얇고 노란 박스가 wrapper입니다만, 다른 엘레멘트들은 그 외부로 벗어나와 보입니다. 
wrapper를 추가한 그림
이를 해결하는 방법은 두 가지가 있습니다.
  1. 첫번째 방법은 부모 엘레멘트인 wrapper에 float 속성을 부여하는 것입니다. float 속성을 가진 wrapper는 함께 떠올라 두 자식 엘레멘트들을 감싸게 됩니다.
  2. 두번째 방법은 norDiv 다음에, 컨텐츠를 가지지 않는 div 엘레멘트를 하나 만들고 이 세번째 보이지 않는 엘레멘트에 clear:both를 적용하는 방법입니다.

이제 어느정도 float 속성에 대한 개념이 잡혔는지 모르겠습니다. 각각의 경우마다 간단한 html 문서를 직접 만들어서 확인해 보는 것이 이러한 개념을 이해하는데 도움이 되리라 생각됩니다. 보다 자세한 사항은 [고급 웹표준 사이트 제작을 위한 CSS 마스터 전략 : 에이콘 출판사]를 참조하시면 됩니다. (어쩌다가 책 광고를.. orz)

다음 시간에는 구조적인 마크업을 통한 네비게이션 메뉴를 만들어 보도록 하겠습니다. 간단한 리스트용 마크업 요소와 CSS를 통한 그래픽 요소와의 통합과 인터렉션에 대해 알아보겠습니다. ( 다음 시간에 소개할 내용은 CSS2 규격에 맞는 내용입니다. IE6 이하 버전에서는 자바스크립트나 기타 방법을 동원해야합니다.)

긴 글 읽어주셔서 감사합니다.

 

댓글