정렬(정열x)의 요정 float
가운데 정렬이든, 양쪽 정렬이든 무언가 나란히 놓아야 했을 때는 무조건 flex를 사용했다. 처음 이해하기는 어려웠지만 한 번 습득하고 나면 다른 세부적인 조정 없이 세로든, 가로든 정렬할 수 있었으니까.
정렬을 손쉽게 해주는 flex. 하지만 그런 flex에도 단점이 있다. flex를 사용할 경우 부모 요소를 기준으로 하여 자식 요소들을 정렬하므로, 정렬할 요소들을 감쌀 “부모 요소”가 꼭 필요하다는 것. 물론 나쁘지만은 않지만, flex를 사용하기 위한 의미없는 div가 늘어나며 마크업이 길어지는 것을 경계해야 한다.
오늘은 float 속성에 대해서 배웠는데, flex의 단점을 커버해주면서도 세밀한 조정 없이 요소들을 정렬할 수 있는 훌륭한 대체재였다.
⛵Float
원래 float 속성은 아래 사진처럼 그림을 따라 흐르는 텍스트 레이아웃을 웹에서 구현하기 위해 탄생한 속성이다. 신문에서도 자주 보이고, 문서편집기 한글의 '어울림'이라는 속성으로 제법 익숙한 레이아웃이다.
HTML에서, 부모 요소 아래에서 이미지와 텍스트를 함께 사용하면 기본적으로 아래의 구조를 가지게 된다.
<img>
태그를 이용해 이미지를 삽입하면 인라인 속성을 갖기 때문에, 텍스트와 같은 base line을 공유하고 있는 것을 알 수 있다. 덕분에 사진의 높이만큼 의도치 않은 여백이 커다랗게 생기고 만다.
이 때, float: left;
속성을 부여하면 아래와 같이 된다.
이미지 옆에 빈 공간을 남기지 않고, 텍스트들을 밀어내며 안정적인 구조를 이루고 있는 것을 확인할 수 있다.
float: left
와 right
float의 속성값은 none
을 제외하고 left
와 right
두 가지가 존재한다.
페이지의 위쪽 박스가 float: left를, 아래가 float: right를 적용한 예이다. 요트가 각 지정한 곳에 둥둥 잘 떠있다.
위쪽, float: left를 적용한 화면은 블록 박스에 이미지의 지정한 너비만큼만 차지하고, 나머지 내용은 박스의 오른쪽에 위치하고 있다. float: right는 반대로 나머지 내용이 왼쪽으로 위치하게 된다.
float를 정렬에 활용하는 법
float에는 특별한 성질이 있다. 위와 같이 요소를 왼쪽 혹은 오른쪽으로 정렬시키는 특성 덕분에 현재는 블록 박스 요소를 정렬하는 가장 기본적인 방법으로 사용되고 있다.
블록 레벨 요소이더라도, float를 적용시키면 박스들끼리 나란히 정렬시킬 수 있게 된다.
<figure>
는 블록 레벨 요소이기 때문에 한 줄에 정렬할 수 없지만, 단정하게 나열된 모습이다.
원래 블록 레벨 요소는 가로폭 전체의 넓이를 가지는 속성을 가지고 있지만, float 속성을 주면 콘텐츠에 해당하는 너비만큼만 차지하고 다른 요소에 대해 왼쪽, 혹은 오른쪽으로 배치된다. 와우!
게다가 inline 요소나 display: inline-box;
속성을 가진 요소에 float
속성을 주면 vertical-align의 영향을 벗어나게 되어, 나란히 정렬된 요소들이 자동으로 수직 정렬된다.
이러한 특성으로 다른 position등으로 세밀한 조정을 거치지 않고도 손쉽게 형제 요소들을 정렬할 수 있다.
float 속성의 문제점
하지만, flex 방식에 단점이 있듯 float을 사용할 때도 유념해야하는 문제점이 존재한다.
1. 부모 요소가 콘텐츠의 높이를 인식하지 못한다
전체를 감싸는 컨테이너의 자식 요소들이 모두 float 속성을 가질 때, 자식 요소들의 높이를 반영하지 못하고 자신의 높이만큼만 보여준다.
그니까, 부모가 자식을 품지 못한다는 뜻이다!
아래 코드를 살펴보자. 아직 float 속성을 설정하지 않은 상황이라, 부모 안에 div 두 녀석이 고스란히 포장되어 있다.
<!doctype html>
<html>
<head>
<style>
.wrap{
border: 4px solid blue;
}
.content{
margin: 5px;
height: 20px;
border: 2px solid green;
}
</style>
</head>
<body>
<div class="wrap">
<div class="content">내용1</div>
<div class="content">내용2</div>
</div>
</body>
</html>
아주 안정적인, 단란한 가정의 모습이다. 그럼 이 두 개의 자식 div를 float을 이용해 정렬해볼까?
content
클래스에 float: left;
만 한 줄 추가한 결과는 다음과 같다.
"키워주셔서 감사합니다!" - div.content
div.content가 부모의 품을 빠져나와버렸다. 자식 요소들이 기존의 레이어를 벗어나 붕 띄워진 상태이기 때문에, 부모 요소가 자식 요소들의 존재를 인식하지 못해 발생한 일이다. 부모가 자식을 못알아본다.
2. float 속성이 없는 형제가 영역을 침범한다
부모 요소 아래에 여러 개의 형제 요소가 존재할 때 일부의 요소에만 float 속성이 적용되면, 적용되지 않은 요소가 정렬된 다른 요소의 자리까지 영역을 가진다.
이번에는 첫 번째 div에만 float: left;
속성을 부여하고, 두 번째 div에는 float을 부여하지 않았다.
이렇게 보아서는, 아무런 문제가 없어보인다. 기존 float의 속성을 따라 첫 번째 요소는 콘텐츠만큼의 너비를 가지며 왼쪽으로 정렬되었고, 나머지 공간을 두 번재 요소가 자리를 차지한 것처럼 보인다.
하지만 여기서 주의할 점은, 두 번째 요소는 <div>
이고 여전히 블록 레벨의 요소라는 점이다.
두 번째 블록의 border를 살짝 바꿔보면 문제점이 드러난다. 두 번째 블록에만 border: 5px solid cadeblue
속성을 부여해보았다.
내용2 : "이제 이 자리는 제 것입니다."
텍스트는 float된 요소를 비껴갔지만, 블록 레벨 요소이기 때문에 라인 한 줄의 자리를 모두 차지하고 있는 모습이다.
대체 왜 이러는 걸까요
브라우저가 요소들을 화면에 어떻게 보여줄 지 결정하는 여러 방법들이 있다. 그 중에서도 세 가지 방법이 대표적인데, 바로 normal flow
, float
, position
이다.
대부분의 요소들은 normal flow에 따라 레이아웃이 결정된다. HTML 마크업을 작성할 때 요소가 작성된 순서에 따라 기본적으로 블록이 쌓이게 된다.
<header> ... </header>
<div> ... </div>
<main>
<article></article>
<div></div>
</main>
위와 같은 코드가 있다면, header 위에 div, div 위에 main이 있다는 식. 이와 같이 밑으로 쌓이고 쌓이는 방식을 normal flow라고 생각하면 된다.
하지만, 스타일 시트를 적용하며 float, position(absolute, fixed)등의 방법을 사용하면 해당 요소는 이 normal flow에서 벗어나게 된다.
이 때 normal flow에 속한 요소들은 normal flow에서 벗어난 float, position 속성이 적용된 요소들을 인식하지 못하게 되면서, 위와 같은 문제점들이 생겨나게 되는 것.
해결 방법
이러한 문제점들을 해결하는 방법은 다양하게 존재한다.
1. 부모 요소의 높이 값 지정 👎
부모 요소가 자식 요소의 존재를 인식하지 못해, 자신이 콘텐츠를 가지고 있지 않다고 생각해 높이가 생기지 않는 문제에 대해서는 개발자가 직접 요소의 높이 값을 지정하여 해결할 수도 있다.
하지만 이 방법은 만약 자식 요소의 높이가 변경되거나 다른 자식 요소가 추가될 경우에는 그 때마다 부모 요소의 높이를 수정해주어야 하므로 매우 비효율적이다.
2. 부모 요소에 overflow 속성 추가
overflow 속성에 visible 외의 다른 값(hidden, scroll 등)을 주면, 부모 요소가 자식 요소를 인식할 수 있게 되어 높이 값을 가질 수 있다.
overflow 속성을 주면 새로운 block format contex(BFC)를 생성하는데, BFC가 float 속성이 적용된 요소를 컨테이너가 인식하도록 만들어주기 때문.
block format context가 더 궁금하다면?
MDN-블록 서식 맥락 (BFC가 생성되는 예)
단, 부모 요소에 height를 준 상태에서 overflow: hidden
을 사용하게 되면 자식 요소의 콘텐츠가 늘어날 때 일부가 잘려 보일 수 있으니 다른 방법을 사용해야 한다.
3. clear-fix
clear의 속성값으로는 left
, right
, both
가 있으며 , 좌-우측, 혹은 양측 부유 흐름을 제거할 수 있다. float 요소 옆으로 텍스트가 흐르는 효과가 제거되므로, 자식 요소에 이 속성을 부여해 영역을 침범하는 형제 요소 문제를 해결할 수 있다. overflow를 다른 용도로 사용해야 할 때, 가장 깔끔한 방법.
그렇다면 부모 요소가 float 속성을 먹은 자식의 존재를 인식하지 못하는 현상은 어떻게 해결할 수 있을까?
부모 요소에 가상요소 ::after를 주고 그 속성에 clear를 사용하면 된다. 잃어버린 자식들의 자리를 유사-자식으로 채워 그 공간을 인식하게 하는 방법이다.
맺으며
float을 배운 만큼, vending-machine 페이지를 작업하면서 평소라면 flex나 grid를 사용할 법한 디자인에 float를 사용해서 정렬을 시도해보았다. 아무래도 처음 써보는 방법이라 속도가 무진장 더뎠음...
하다가 마주친 난관들이 있는데, float으로 정렬한 아이템과 아이템 사이의 여백을 어떻게 주느냐였다. 부모 요소의 width가 정해져 있고 아이템들의 개수가 여럿이라 줄바꿈이 일어나는데, 3개의 아이템이 나란히 있고 다음 아이템부터는 줄바꿈이 생기는 레이아웃에서 아이템 간에 일정한 여백을 주는 방법을 고민하느라 머리를 엄청 굴렸다.
우리 팀 팀장 밍코딩님이 nth-child로 마진을 줘보면 어떻겠냐는 의견을 주셔서, nth-child(3n+2)를 먹였더니... 와 진짜 됨 민석님은 천재인듯
아직 아이템목록 하단은 어떻게 채워야 할지 모르겠다 :-)
이 방식을 사용하면 목록에 들어가는 아이템 개수가 늘어나도 가로로 3개씩 정렬이 유지되면 계속 유효하다. 하지만... 반응형 디자인에서는 화면의 가로 너비가 줄어들면 아이템 3개 정렬이 깨지면서 난잡한 구조가 되어버렸다. 이 부분에서 grid가 가슴시리게 그리워졌다. 하지만 IE가 이 세상에 아직 버티고 있는 만큼, float으로 정렬하는 방법도 확실히 익혀두자는 마음가짐으로 꿋꿋이 아이템 목록 정렬을 만들어냈다.
아무튼 내가 이김.
그치만 float을 사용하면 수직 가운데 정렬을 하지 않아도 되고, margin으로 미세 조정을 한다는 점에서 조금만 더 실습해보면 float과도 가까워질 수 있을거라는 생각이 든다.
float 너 가만안둬 딱 두고봐
Author And Source
이 문제에 관하여(정렬(정열x)의 요정 float), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@devsaza/likealion014저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)