float을 clear하는 4가지 방법.
CSS 속성 가운데 float 속성은 자기 자신의 위치를 주변의 콘텐츠로부터 상대적으로 배치하는 속성입니다. float은 사전적 의미로 ‘뜨다, 띄우다, 뜨는 물건, 부유물’ 이라는 의미가 담겨져 있습니다. float은 높이가 가변적인 다단 컬럼 형태의 CSS 레이아웃을 위하여 반드시 요구되는 속성으로서 처음 CSS 배치기법을 익힐 때 가장 이해하기 어려운 속성중의 하나 입니다. float 속성이 부여된 엘리먼트는 좌측이나 우측으로 배치되면서 주변 콘텐츠의 배치에도 영향을 미친다는 사실은 어렵지 않게 학습되나 ‘float 된 엘리먼트가 부모 엘리먼트의 높이에 영향을 주지 않는다는 사실’은 몇 번의 경험 또는 선배들의 조언으로 깨닫게 되는 것이지요.
오늘은 float 속성을 이해하고 다단 컬럼형 레이아웃을 시도할 때 주변 엘리먼트들이 원하는 상태로 배치될 수 있도록 이것에 대응하거나 clear 하는 방법에 대하여 공유하고자 합니다. clear 속성은 float이 더이상 주변 엘리먼트의 배치에 영향을 미치지 않도록 해제시키는 속성입니다. 만약 Internet Explorer 브라우저를 사용하여 학습을 시도하신다면 일단 멈추시고 표준계열 브라우저에서 먼저 시도해 보세요. CSS 표준 렌더링을 엄격하게 준수하는 Opera와 Safari를 권장합니다. Internet Explorer와 Firefox 브라우저는 float, clear 속성에 관한 버그를 포함하고 있으므로 float과 clear의 표준 렌더링이 어떻게 구현되는지를 학습할 때 도움이 되지 않습니다. 하지만 버그를 해결하는 방법도 소개되어 있으니 안심하세요.
오늘 글의 핵심은 ‘float된 자식 엘리먼트의 높이를 부모 엘리먼트에 반영하도록 대응하는 방법’ 이라고 한마디로 설명할 수 있겠습니다. 부모 떠난 자식을 다시 부모의 품 안으로 돌아오도록 하려면 어떻게 해야 하는지 한번 살펴 보시죠.
float에 아무런 대응도 하지 않은 상태
#container는 부모 엘리먼트이며 #lnb와 #content는 자식 엘리먼트로서 현재 float된 상태 입니다. 아래 예제는 float에 아무런 대응을 하지 않으면 자식 엘리먼트가 부모 엘리먼트의 높이에 영향을 주지 않는다는 사실을 보여주고 있습니다. #container의 높이가 자식 엘리먼트의 높이를 반영하지 않고 있다는 사실에 주목해 주세요. float에 아무런 대응도 하지 않은 상태의 예제가 준비되어 있습니다.

float에 float으로 대응하는 방법
자식 엘리먼트의 높이를 부모에게 반영하는 방법으로 부모에게도 float 속성을 부여하는 방법이 있습니다. 부모에게 float 속성을 부여하게 되면 부모엘리먼트는 자식 엘리먼트의 높이를 반영합니다. 하지만 부모 엘리먼트의 너비는 float된 두 자식의 너비를 담을만큼만 작게 줄어든다는 사실에 주목해 주세요. 부모의 너비가 브라우저 크기에 따라 가변적이어야 하는 경우에 적용하기 어려운 단점이 있습니다. 또한 조상 엘리먼트들이 겹겹이 존재하는 경우 자식의 높이를 조상 엘리먼트에게 각각 전달하기 위하여 조상 엘리먼트들을 모두 float 시켜야 하므로 일반적으로 사용하는것을 권장하지 않습니다. float에 float으로 대응하는 방법 예제.

float에 overflow 속성으로 대응하는 방법
자식 엘리먼트의 높이를 부모에게 반영하는 방법으로 부모 엘리먼트에 overflow:auto 또는 overflow:hidden 속성을 부여하는 방법이 있습니다. overflow:auto 속성은 자식의 너비가 가변적이고 부모의 너비보다 커지는 상황이 발생할 때 가로 스크롤바를 유발하기 때문에 일반적으로 권장하는 방식이 아닙니다. overflow:hidden 속성은 그러한 상황에서 가로 스크롤바를 유발하지는 않지만 자식의 너비가 넘치는 경우 넘치는 부분이 잘리기 때문에 이 역시 완전하게 안전한 방법은 아닙니다. float에 overflow 속성으로 대응하는 방법 예제.

float을 빈 엘리먼트로 clear 하는 방법
이 방법은 #container 영역이 끝나기 직전 빈 엘리먼트를 넣고 빈 엘리먼트에 clear:both 속성을 부여하여 부모가 자식의 높이를 인식하도록 하는 방법입니다. 하지만 의미 없는 빈 엘리먼트를 사용하기 때문에 이 역시 권장되는 방법은 아닙니다. float을 빈 엘리먼트로 clear 하는 방법 예제. 예제에서는 .clear 라는 빈 엘리먼트를 가시적으로 보이도록 하였지만 실무에서는 보통 .clear {clear:both; height:0; overflow:hidden;} 처리하여 .clear 라는 빈 엘리먼트가 스스로 높이를 갖지 않도록 하고 보이지 않도록 처리 합니다.

float을 가상 선택자 :after로 clear 하는 방법
가장 탁월하다고 생각하는 방법 입니다. 우선 ‘가상 선택자‘라는 개념을 이해하셔야 하기 때문에 약간 상세히 설명드리겠습니다. 여러분들이 익히 알고 계시는 :link, :visited, :hover, :active, :focus는 모두 가상 선택자 입니다. ‘가상 선택자’는 다시 ‘가상 클래스‘와 ‘가상 엘리먼트‘로 구분할 수 있는데요. ‘가상 클래스‘는 특정 엘리먼트에 대하여 아무런 class를 부여하지 않았지만 마치 역동적으로 class를 변경한것과 같은 효과를 낼 수 있는 것들로서 이미 존재하는 엘리먼트에 조합해서 사용할 수 있습니다. :link, :visited, :hover, :active, :focus, :first-child가 가상 클래스에 해당됩니다. 한편 ‘가상 엘리먼트‘란, 존재하지 않는 엘리먼트를 가상으로 생성해내는 선택자로서 :first-line, :first-letter, :before, :after가 있습니다. 심지어 :before와 :after는 HTML문서상에 존재하지 않는 콘텐츠를 출력시키기도 합니다. Hello World Collection이라는 웹 사이트에 신현석님이 ‘Hello World’라는 메시지를 어떻게 출력했는지 살펴보시면 재미있고 이해하기도 쉽죠. 이렇게 가상의 엘리먼트를 생성 #container:after {content:" "} 시킨 다음 display:block; clear:both 처리를 추가하게 되면 의미 없는 빈 엘리먼트를 사용하지 않으면서도 가상 엘리먼트를 이용하여 깔끔하게 float이 clear됩니다. float을 가상 선택자 :after로 clear 하는 방법 예제.

상기 예제로부터 가상 엘리먼트가 스스로 높이를 갖지 않고 화면에 보이지 않도록 처리 하려면 추가적으로 아래와 같이 높이를 제거하고 visibility 속성을 hidden으로 처리 합니다.
#container:after {content:" "; display:block; clear:both; height:0; visibility:hidden;}
하지만 Internet Explorer는 :before, :after 가상 엘리먼트 선택자를 지원하지 않기 때문에 다음과 같은 Hack이 필요합니다.
#container {*height:1%;} /* IE5.5~7 브라우저 대응 Hack */
#container:after {content:" "; display:block; clear:both; height:0; visibility:hidden;} /* 표준계열 브라우저에 대응하는 float 해제용 가상 엘리먼트의 생성 */
Internet Explorer는 엘리먼트에 높이값을 부여했을 때 min-height 속성을 부여한 것처럼 렌더링하는 특징이 있는데 이때부터 float된 자식의 높이까지 인식하게 되는 버그가 있고 이러한 특성을 이용한 것입니다. Internet Explorer 버그와 관련하여 Wystan님 께서 오류를 지적해 주셨습니다. 정확하게 말해서 #container라는 엘리먼트가 min-height속성을 부여한 것처럼 렌더링 하는 특징은 #container라는 엘리먼트에 height 속성뿐만 아니라 width 속성을 부여하는 경우에도 동일하게 나타납니다. 이것은 IE가 hasLayout이 라는 IE만의 속성을 지니고 있기 때문입니다. 그리고 min-height속성을 부여한 것처럼 렌더링 하는 특징은 IE6 이하 브라우저와 IE7이 조금 다릅니다. #container의 부모 엘리먼트에 높이값이 지정되어 있지 않은경우라면 IE6과 IE7은 min-height 속성을 부여한 것처럼 동일하게 렌더링 하지만 #container의 부모 엘리먼트에 높이값이 지정되어 있는 경우라면 IE7은 min-height 속성을 부여한 것처럼 렌더링 하지 않습니다. 따라서 이 팁은 #container의 부모 엘리먼트에 height값이 명시되어 있는 경우 IE7에서 원하는 형태로 렌더링 하지 않으므로 상황에 맞게 제한적으로 사용하여야 합니다. Wystan님께 감사드립니다.^^
2008년 11월 14일 내용 추가.
IE 브라우저에서 float을 해제하는 핵으로 { *height:1% } 대신 { *zoom:1 }을 사용하셔도 됩니다. 높이를 지정하는 방법은 IE7에서 부모 엘리먼트에 높이 값이 존재하는 경우 부모의 높이값으로 부터 1%를 계산하기 때문에 다양한 상황에 적용하기 어려운 단점이 있는 반면 zoom 속성을 사용하게 되면 부모의 높이값과 무관하게 float을 해제할 수 있기 때문에 브라우저 호환성 유지를 위한 더 좋은 방법이라고 생각됩니다.
참조
- Cascading Style Sheets, level 2 CSS2 Specification – http://www.w3.org/TR/REC-CSS2/
- CSS2 규격 한글 번역문 – http://trio.co.kr/webrefer/css2/cover.html
- YAML > How Floats Work – http://www.yaml.de/en/documentation/basics/how-floats-work.html
- 신현석 > CSS Floating and Clearing – http://hyeonseok.com/soojung/web/2005/03/07/123.html
말로 설명만 했었는데, 깔끔하게 정리되어서 동료들에게 보여주면 되겠네요.
^^
성민장군님, 좋은아침입니다 ^^
이눔 포스팅 시간이 ‘2008년 5월 27일, 6:59′ 인 것 보니 아직도 밤샘 즐겨 하는구나…
집에 좀 들어가라~~~~
별별~ 밤새 글썼다. 지금은 어느별에서 뭣하고 있는고~ ㅎㅎㅎ
정말 필요했던 노하우입니다~ 감사합니다..
늘 좋은정보 혼자 가져가 버리네여..
정리된 설명 잘 읽었습니다. 안그래도 정리가 잘 안되고 있었는데, 좋은 정보 얻어갑니다.
전 언제나 overflow 로 처리 했는데 맨 마지막 방법이 있었군요! 좋은 글 고맙습니다. :D
좋은 글 올려주셔서 고맙습니다. ^^
IE가 가상 엘리먼트를 제대로만 처리하면 참 좋을텐데 이상과 현실은 참 머네요~ ^^;
그런데 IE의 height: 1% hack 설명에 조금 의아한 부분이 있습니다.
관련해서 메일 드렸으니 확인 부탁드려요~
좋은 정보 감사합니다.
음, 마지막 방법이 가장 좋은 방법같지만,
ie6와 ie7에 대한 코드를 또 만들어 주어야 한다는것이 조금 걸리네요.
ie때문에 정말 이래저래 골치가 아프군요.
Wystan님, 감사합니다. 어제 저녁에 너무 바빠서 오늘 아침에서야 수정 하였습니다. (__) 좋은 하루 보내시구요 ^^
좋은글이라 담아갈게용
좋은 내용 감사합니다. 블로그에 출처 명시하고 퍼가도 될까요?
네, 물론입니다 ^^ 이 저작물은 크리에이티브 커먼즈의 2.0 라이센스(저작자표시, 비영리, 변경금지)에 따라 이용하실 수 있습니다. http://creativecommons.org/licenses/by-nc-nd/2.0/kr/ 좋은하루 되세요!
감사합니다.
플로트 때문에 골치아팠던 적이 한두번이 아니었는데 ^^
제 스프링노트로 출처 표시하고 퍼갔어요, 공부하려고..^^
저도 이문제에 대해서 많이 고심 해보았습니다
현재는 빈 엘리먼트를 이용 하는 방법을 사용중입니다
망할! 익스플로러 구버전에서도 적당히 잘 보여주니까요 :D
NL님, nuzl님 안녕하세요? 아무쪼록 골치아픈 문제를 이제는 벗어나셨길 바랍니다. float이 아니고도 IE에서 골치 아플일이 무지하게 많잖아요 ㅜㅜ; 저는 아마 죽어서 묘비에 이렇게 새길껍니다. ‘내가 일찍 죽은건 IE 다 네 탓이다!’ 라구요.
대단하십니다
강진현님, 안녕하세요 ^^; 아니 뭐가 대단하다는건지요 ㅜㅜ;
overflow:hidden을 부모엘리먼트에 줘서 float를 해제하는 방법은 IE에서는 overflow 속성이 엘리먼트에 hasLayout을 부여하기 때문에 가능한 방법이죠.
가끔 가다가 디자인 때문에 overflow:hidden을 적용하지 못하는 엄한 상황이 생기기도 하는데 저는 그때 overflow대신 _zoom:1; 을 줘서 해결하기도 합니다.
아, 그런 방법도 있군요 ^^ 감사해요~
消除浮动元素对浏览器的支持
{overflow:hidden; zoom:1;}、{display:table; width:100%;}、{overflow:hidden; height:1%;}
http://blog.gulu77.com/?p=24
네, IE에서 float을 clear시키는 방법으로 *height:1% 외에도 위와 같은 다양한 방법(zoom, width)이 있다고 설명해 주신것 같네요 ^^
Thank you!
한방에 이해했습니다. 저도 저렇게 정리잘~~ 하는 능력 좀 있었으면 좋겠습니다. ^^
덕분에… 감사합니다 *^^*
질문있습니다. ^^;
float:right를 가진 부분과
float:left를 가진 부분이 있습니다.
다른 로 쌓여 있지 않는 상태에서
바로 밑에 clear:both를 사용안하고 해제 할 수 있는 방법은 없나여?
배혜진님, 감사합니다 ^^
김도훈님, clear:both 속성을 사용하지 않아야 하는 상황이 궁금합니다. 혹시 예제 페이지나 코드로 보여주실 수 있을까요? 이곳 댓글 입력창에서는 HTML 코드를 입력하셔도 코드가 그대로 출력되지 않기 때문에 꺽쇠 대신 다른 기호를 사용하시거나 예제를 보여주시는게 제가 이해하기 빠를 것 같습니다.
[div class="float_right"] A contents [/div]
[div class="float_left"] B contents [/div]
바로 밑에
[div] C contents [/div]
이럴경우 C contents가 위로 올라오는 경우가 있는데 현재 float해제 방법은 둘러쌓고 있는 박스가 있어야만 적용이 되는것 같아서여…
이렇게 박스가 존재하지 않으면서 양쪽으로 float를 사용할 경우 밑에 적용되는 내용에 float이 적용안되게 할 수는 없나여? clear:both를 사용안하고 할 경우…
정말 많은 공부가 되고 있습니다. 이렇게 좋은 사이트가 있다는걸 진작 알았어야 했는데요..
웹눈님 블로그도 충분히 멋지신데요 ^^ 감사합니다.
김도훈님, 댓글을 엄청 늦게 드려서 죄송하네요. 깜빡했습니다. ㅜㅜ; C contents 에 clear:both 를 부여하면 간단하게 해결되는 문제라고 생각했는데요. 혹시 C contents 에도 clear:both 속성을 사용하면 안되는 이유가 있을까요?
^^ 네
그런데 밑에 있는 컨텐츠에 margin-top을 줄 경우 적용이 안되는 것 같아서여
그래서 중간에 clear:both;를 사용했는데….
마진을 적용시킬 수 있는건가여?
김도훈님께, 다시는 안오실줄 알았습니다 ㅜㅜ; 각설하고 제가 테스트해본 결과를 말씀드리자면 float 된 박스 아래쪽에 있는 ‘C’의 margin-top 은 작용하지 않는것이 맞는 것(표준 렌더링) 같습니다. OP, SF, FF 모두 작용하지 않았지만 IE에서만 작용이 되더라구요. 왜 작용하지 않는것이 표준인지에 대해서는 신빙성 있는 설명을 찾지 못했고 표준계열 브라우저들이 렌더링 하는 방식에 따라 추측했을 뿐입니다. 아무래도 float 된 박스와 float 되지 않은 박스이기 때문(서로 다른 층에 떠있는 이유)인것 같구요. 해결 방법은 두 가지가 있네요.
첫째는 A, B 상자에 동일한 margin-bottom 을 부여하는 것.
둘째는 C 상자에 margin-top을 부여하고 float:left; clear:both 하는 것.
김도훈님께 답변 드리려고 다시한번 margin 스펙을 뒤적거렸는데요. 이것과 직접적인 관계는 없지만 찾아낸걸 추가로 말씀드리면 다음과 같습니다. margin-top, margin-bottom 을 통털어 수직 마진이라고 하지요. 근데 이 수직 마진은 수평마진과 다르게 작용하는 점이 있어서 정리해 봅니다.
첫째, 형제끼리 또는 삼촌간의 수직 마진은 통합된다.
형 또는 삼촌에게 margin-bottom:1em, 아우 또는 조카에게 margin-top:1em 을 적용한 경우 두 마진의 합이 2em 이므로 2em 의 마진이 발생할 것 같지만 그렇지 않고 이 둘은 통합되어 1em 의 마진만 표현된다 라는 점 입니다. 만약 두 마진 가운데 큰 값이 있으면 작은 값의 마진은 적용되지 않습니다. 양수끼리 만나면 더 큰 양수가 적용되고 음수끼리 만나면 더 큰 음수만 적용이 되며 양수와 음수가 함께 만나면 두 값을 더한 값이 마진이 됩니다. 이 부분은 4대 브라우저(IE, FF, OP, SF)가 모두 표준대로 렌더링 합니다. 삼촌이란 부모의 형제를 말합니다.
둘째, 수직 마진은 부모 자식간에는 소용없다.
부모 상자로부터 이격시키기 위하여 자식 상자에 수직 마진을 부여하는 경우 부모 자식간 마진은 작용하지 않고 형제 또는 삼촌(부모의 형제)에게만 작용합니다. FF, OP, SF 모두 동일하게 이와 같이 렌더링 하는데 IE만 유독 부모 자식간 수직 마진이 작용하고 삼촌에게는 마진이 작용하지 않았습니다. 이와 관련된 스펙에 대하여 찾아보려 했지만 못찾겠더라구요. 이와 관련된 설명을 찾으면 float 된 위쪽 상자에 수직 마진이 작용하지 않는 원리도 이해할 수 있으리라 봅니다. 혹시 누구라도 찾으시면 댓글 부탁드립니다.
감사합니다. ^^ 흐흐
height:1%;이건 피카푸 버그를 우회할때 유용 합니다.
IE7 인 지금도 피카푸 버그 때문에 냐먼애ㅑㅓㅗㅁ냐어ㅐㅑㅁㄴㅇ
form 을 이쁘게 만들려고 할때 피카푸 버그가 보입니다.
그래서 그냥 테이블로 떼우거나…-_-;
윈도 버전 IE7 불여시3.01 오페라로 테스트 해본 결과
그냥 적당히 완전히 빗나갈 정도만 아니라면 그냥코딩 할수 밖에 없다는 결론을 내렸습니다.
PS: 제가 코멘트 단후에도 코멘트 많이 올라와있네요 float 문제는 여전히 너무 끔찍 합니다 ㅜㅜ
nuzl님, 안녕하세요? form은 보통 th, td 로 마크업되는 구조 아닌가요? ^^ 물론 dt, dd 로 하는 방법도 있겠지만 그런 경우라면 table도 부적절하다고는 생각하지 않습니다.
*heigh:1%; 가 유용한 Hack임은 틀림 없는데 부모의 높이가 지정되어 있지 않을 때에만 사용해야 해서 다소 조심스럽긴 하네요. ^^ 좋은 하루 되세요.
와-정말좋은정보입니다 ^^
float과 clear.. 사실상 우리나라에서는 인터넷 익스플로러가 독점하고 있는 상황이라 -
그다지 신경쓰지 않고, 레이아웃을 설정했더니,
구글 크롬에서 엉망으로 나오더군요. ㅜㅜ
인터넷 익스플로러 8.0에서는 사용해보니 어느정도 크롬과 거의 대등한 표준화를 준수하는거 같더군요 ^ ^
아무튼 좋은 정보 감사합니다. :)
좋은정보 감사해요~ 친구들한테도 주소 슝슝~ 날려보내줬습니당~
아넵, 감사합니다. 참고로 IE에 대응 하는 핵 {*height:1%} 를 대신해서 {*zoom:1} 핵을 사용하셔도 됩니다. zoom 속성을 사용하시면 부모 높이가 지정되어 있는지의 여부와 무관하게 float을 해제할 수 있어서 좋더라구요. ^^
왼쪽 header 영역에 100% 되는 방법 없을까요?
코드는 아래와 같습니다만..^^; 여기 남겨도 되는지 모르겠네요;
MyNote
/* 글로벌 */
* { margin:0; padding:0; font-size:small; font-family:돋움, Dotum, AppleGothic, sans-serif;}
html {height:100%;}
body{background:url(http://eond.com/eond/files/attach/images/120347/900/162/bg_body.gif);height:100%;}
/* 전체 구조 */
#wrapper{float:left;background:url(http://eond.com/eond/files/attach/images/120347/900/162/bg_wrapper.gif) right bottom no-repeat fixed;width:100%;height:100%;overflow:auto;}
#header{float:left;width:52px;height:100%;background-color:#F6F6F6;}
#container {float:left;width:500px;border:1px solid white;}
#footer{float:left;width:200px;}
/* 컨테이너 */
/* 푸터 */
1
아..;; 메일로 보내겠습니다;
앗, 다른 분들도 참고하실 수 있기 때문에 댓글로 써주시면 더 좋습니다. ^^;
코멘트에는 HTML코드가 가능하지 않도록 하는 것이 더 좋을 것 같기도;;
[!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"]
[html]
[head]
[title]MyNote[/title]
[style]
/* 글로벌 */
* { margin:0; padding:0; font-size:small; font-family:돋움, Dotum, AppleGothic, sans-serif;}
html {height:100%;}
body{background:url(http://eond.com/eond/files/attach/images/120347/900/162/bg_body.gif);height:100%;}
/* 전체 구조 */
#wrapper{float:left;background:url(http://eond.com/eond/files/attach/images/120347/900/162/bg_wrapper.gif) right bottom no-repeat fixed;width:100%;height:100%;overflow:auto;}
#header{float:left;width:52px;height:100%;background-color:#F6F6F6;}
#container {float:left;width:500px;border:1px solid white;}
#footer{float:left;width:200px;}
/* 컨테이너 */
/* 푸터 */
[/style]
[/head]
[body]
[div style="clear:both;"][/div]
[div id="wrapper"]
[div id="header"]1
[/div]
[div id="container"]
[br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /][br /]
[/div]
[div id="footer"]
[/div]
[div style="clear:both;"][/div]
[/div]
[div style="clear:both;"][/div]
[/body]
[/html]
현재 #header의 높이는 100%가 적용되어 있지만 콘텐츠에 따라서 가변적으로 늘어나는 상대적인 높이가 아니라 브라우저의 뷰포트를 기준으로 100%가 잡히게 되는데요. 이렇게 되는 이유는 #header가 부모 엘리먼트를 기준으로 상대적인 높이를 갖게 되는데 부모인 html, body의 높이 100%는 바로 뷰포트의 높이이기 때문에 결국 #header의 높이 100%는 한 화면의 뷰포트 높이보다 더 클 수 없게 됩니다.
만약 #header가 콘텐츠 영역의 높이에 따라 가변적인 높이를 가져야 하는 상태로 배경을 넣고자 하는 것이라면 이렇게 할 수 있습니다.
1. 현재 body 요소에 적용된 background는 html 요소에 적용.
2. 현재 #wrapper에 적용된 background는 body 요소에 적용.
3. #header에 적용하고자 하는 background는 #wrapper에 적용.
그러나 만약 #header가 라운딩된 디자인 상자라서 위/아래 추가로 이미지를 적용해야 한다면 이때는 어쩔 수 없이 빈 엘리먼트(span)가 두개 필요하겠지요. 이 때 사용되는 빈 엘리먼트는 #header의 자식이 되어서는 안되고 #header, #container와 형제 관계로 존재해야 합니다. 라운딩 모서리에 필요한 span에는 각각 .hTop .hBottom 이라는 클래스를 부여 합니다.
#wrapper의 position을 relative로 설정한 다음 .hTop .hBottom의 position은 absolute 상태로 처리하고 .hTop 은 top:0 으로 위치지정 하고 .hBottom은 bottom:0 으로 위치를 지정 합니다. 이렇게 되면 라운딩 된 위/아래 모서리들은 콘텐츠의 높이에 따라서 자신들의 수직 위치는 가변적이 됩니다.
제가 질문을 제대로 이해하고 답변 했는지 모르겠군요. 이럴때는 왜 #header를 100%로 만드려고 하는지, 그리고 100%라는 표현은 상대적인 값이기 때문에 무엇을 기준으로 100% 인지 설명해 주시면 더 좋을것 같습니다. 부족한게 있으면 다시 질문해 주세요. ^^
PS : 코드 붙여넣기 불편하시죠? 이럴때는 정낙훈님 웹 계정에 예제 파일 올려주시고 링크 해주시면 더 편하지 않을까요? ^^
답변 감사합니다. html 요소에까지 배경을 넣는다는 생각은 못했네요.
하지만 #header의 배경은 단색이라 그냥 background-color 로 처리하려고 그랬거든요.
되도록이면 이미지는 사용하지 않으려고 했는데, #header의 높이가 뷰포트보다 어쩔 수 없이 더 클 수 없는 상황이라면, 배경그림을 넣는 것이 더 머리 아프지 않게 하는 방법인 것 같습니다. 다음부터는 제 계정에 예제 파일을 올려놓고 링크하도록 하겠습니다. 제가 여기에만 너무 집착한 나머지 그 외에 필요한 부분에 대한 생각은 전혀 하질 못했네요. ^^;
아 제가 찾던 답변이 여기 있네요.
제가 지금 레이아웃 짜고 있는데요. 저도
clear:both;를 했더니 margin-top이 안먹어서 애좀 먹었어요..
그래서 찬명님 해결 방법으로 해결했더니. 첫번째 방법은 되더군요..
도훈님이 주신 질문과는 조금 다르지만..
http://blossomm.mireene.com/margins_clear.html
이렇게 해봤는데, 두번째 방법은 IE에서는 겹쳐진다는..(아.난감)
IE에서의 해결 방법은 없을까요??(갑자기 막 궁금해서,,ㅎㅎ)
이게 왜 이런건지..?제 소스는 margin부분이 겹치지도 않는데 ,,,;;
collapse margins이라고,계속 찾아봤는데. 아직은 이해하기가 어렵더라구요.
담엔 collapse margins 대해서 자세하게,,으하하하하하;;;(뻘….쭘;;)
강짱님 예제를 봤는데요. #lnb의 float을 빼고 clear:both를 주면 간단하게 원하는 배치가 나오지 않나요? 그런 예제가 이미 페이지에 포함되어 있던데요?
저 같은 경우는 박스를 2~3단의 컬럼으로 몇개 배치하고 그 컬럼들의 높이를 부모에게 전달해서 아래쪽에 등장하는 박스들을 자연스럽게 밀어내 줄 필요가 있을 때에만 float을 사용하는데요. 예제를 딱 보아하니 저것들은 굳이 float을 사용하지 않아도 될 것 같아요. 저라면 IE 에서 버그 만날 확률이 높기 때문에 float 대신 #gnb는 absolute 처리하고 헤더부분의 높이는 #gnb와 #lnb의 부모 요소에 padding-top을 부여하는 것으로 해결할 것 같습니다.
마진 병합에 관한 이야기는 다시 한번 설명해 보겠습니다. 아래와 같은 HTML 구조를 먼저 생각해 주세요.
[부모]
[난형]…[/난형]
[난제]…[/난제]
[/부모]
[삼촌]…[/삼촌]
서로간의 관계가 파악이 되셨다면 이제 설명을 들을 준비가 되신겁니다.
일단 형제, 삼촌, 부모를 통털어 수평 마진은 서로의 마진을 있는 힘껏 밀어내서 절대로 병합되지 않습니다. 수식으로 표현하면
‘난형 우측 마진 10px’ + ‘난제 좌측 마진 10px’ = ‘형제간 수평으로 20px 마진 발생’
과 같이 정상적인 계산 방식으로 마진이 작용합니다.
그러나 수직 마진은 적은 마진 수치를 가진 녀석이 자신의 마진을 숨겨버립니다.
‘난형 아래쪽 마진 20px’ + ‘난제 위쪽 마진 10px’ = ‘형제간 수직으로 20px 마진 발생’
상식적으로 ‘난형’과 ‘난제’는 수직으로 ‘30px’의 마진이 발생해야 할 것 같지만 마진 수치가 작은 ‘난제’의 마진은 작용하지 않고 ‘난형’ 마진에 병합되어 버려서 고작 ‘20px’의 마진만 발생합니다. 이런일 흔히 있잖아요. 형제간에 한 녀석이 너무 잘나면 다른 녀석이 상대적으로 박탈감 느껴서 탈선하는. ㅜㅜ; 그런데 CSS 에서는 형제뿐만 아니라 ‘삼촌’ 관계에서도 이런 일이 발생한다는. ㅎㅎㅎ.
결국 수직 마진은 아래와 같이 간단명료하게 정리할 수 있습니다.
1. 형제 또는 삼촌 관계에서 발생하는 수직 마진은 병합(merge)이 되는데
2. 양수끼리 만나거나 음수끼리 만날때는 수치가 작은 값은 병합되어 큰 값만 작용하고
3. 양수와 음수가 만날때는 병합됨 없이 그 두 값을 더한 값이 작용하고
4. 형제나 삼촌 관계 아닌 부모자식 사이에서는 마진이 작용하지 않는다
라는 겁니다. 나름 쉽게 다시 한번 쓴다고 고민 했는데 여전히 어려울 수 있겠네요. 누가 이 원리를 잘 설명해줄 예제 팍팍! ㅋㅋㅋ.
오웃.
아 저도 absolute로 해결하긴했지만..
그냥 문득 이런저런 해결방법이 궁금해서요~ㅎㅎ
저거때문에 일 안하고 괜히 끄적거리고 있었다는.
‘그러나 수직 마진은 적은 마진 수치를 가진 녀석이 자신의 마진을 숨겨버립니다.’
다는 아니지만 이해가 많이 되네요.
쌩유해요~
아 저 제 예제에서 첫번째 방법이 IE에서는 되지만..FF에서는 margin-top이
안먹어서 물어본거였다는…흠..
아, 이제서야 강짱님이 궁금해 하던 문제가 무엇이었는지 파악했어요. 사실 이 문제를 이해하기 전까지는 저도 그렇게 작용하는지 몰랐었습니다.
문제는 float된 ‘난형’과 float되지 않고 clear된 ‘난제’ 사이에서 ‘난형’의 아래쪽 마진은 작용하는데 ‘난제’의 위쪽 마진은 왜 작용하지 않는지 그걸 물어보신 거로군요. 맞죠?
CSS 명세에서 적당한 설명을 찾기 못했기 때문에 표준계열 브라우저들의 작동박식을 근거로 설명해 보자면 ‘난제’의 위쪽 마진은 현재 ‘난형’에게 작용하지 않고 ‘부모’에게만 작용하고 있습니다.
표준계열 브라우저들의 작동 방식이 옳다는 전제 아래 남은 숙제는 일단 float된 ‘난형’과 float 안된 ‘난제’ 사이에 발생하는 ‘마진까지 clear 되지 않는 현상’ 이로군요.
실험을 위해 ‘난형’과 ‘난제’의 마크업 순서를 바꿔 놓아 보면 아래쪽에 놓여 float된 ‘난형’에게 발생하는 위쪽 마진은 ‘난제’에게 작용하지만 원래의 마크업 순서로 다시 돌아와서 ‘난제’에게 위쪽 마진을 설정해 보면 이 마진은 ‘난형’에게 작용하지 않습니다.
현재로써는 아마도 ‘float된 요소와 float 안된 요소가 서로 다른층에 떠 있고 float 없이 clear된 ‘난제’의 위쪽 마진은 float된 형재에게 작용하지 않는다’ 라는 류의 설명이 CSS 스펙에는
생략되어있지만 브라우저 벤더들 사이에서 누군가 먼저 이렇게 구현했고 그것을 따라하지는 않았을까 라는추측잘못된 추측도 해봅니다.결국 현상만 설명이 되었고 원리는 제 깜냥으로는 설명이 안되네요. 원리를 알고 이해하는것이 가장 좋겠지만 말이죠. 아, CSS 너무 어렵네요. ㅎㅎㅎ.
조금전 winstan님과 담배를 한대 태우며 자문을 구했더니 이렇게 구현되는 방식이 CSS 명세에 설명되어 있다고 하더군요. 저는 아무리 눈 씻고 찾아봐도 안보이던데 ㅡㅡ;
원리는 이랬습니다.
float된 ‘난형’과 float 없이 clear된 ‘난제’가 있을 때 ‘난제’는 ‘난형’의 높이값에 해당하는 margin-top을 자동으로 가지게 된다. 따라서 ‘난제’에 ‘난형’의 높이보다 작은 수치의 위쪽 마진을 설정하면 마치 마진이 적용되지 않은 것 처럼 보이고 ‘난형’의 높이보다 높은 수치의 마진을 적용해야만 비로소 ‘난형’과 멀어지게 되는 겁니다.
어쨌든 키 포인트는 ‘둘이 서로 다른 층에 떠 있다’는 점이고 새롭게 알게된 사실은 이런 경우에 ‘난제’에게 자동으로 ‘난형’의 높이에 해당하는 margin-top이 발생한다는 사실 이네요.
관련 속성이 어디에 설명되어 있는지는 wynstan님께서 어느부분인지 알려주신다고 하시니 잠시 후에 다시 뵙겠습니다. ^^
float과 clear된 요소의 margin-top 부분에 대하여 여기 설명이 되어 있습니다.
http://www.w3.org/TR/CSS21/visuren.html#floats
HTML 구조
<body>
<p>Some sample text <img /> that has no other... </p>
<p>The second paragraph...</p>
</body>
CSS 구조
img { float:left; }
p { margin:2em; clear:left; }
설명
두 문단에는 ‘clear:left’가 설정되어 둘째 문단은 float 아래로 떨어진다. clear 처리는 float을 해제하기 위하여 아래쪽에 놓인 상자에 위쪽 마진을 추가한다.
즉, clear 시키기 위해서 둘째 문단에 가상의(?) 위쪽 마진을 두는데 이 마진은 딱 float된 녀석의 높이 만큼만 발생하기 때문에 둘째 문단보다 margin-top의 수치가 크지 않으면 마치 마진이 사라진 것처럼 보인다는 겁니다.
이해는 했지만 또 설명하기란 쉽지 않군요. 덕분에 float, clear, margin 공부 새로 했습니다. ㅎㅎㅎ.
윽..역시나 이해하기 어려운…
한참 레이아웃 에 빠져있다보니 여기까지 저도 와버려서
더 헷갈려서리,,,margin-top에 수치가 커야 적용이 된다는거까지…알겠는데..
질문 하나만 ,,더 드릴께요~(이해력이 부족한 저를 용서해주세요.ㅜㅜ)
그럼 아래 주소에서 첫번째 레이아웃 소스를 보면
FF에서 마진 적용아 아예 안먹던데요..
(익스에서는 적용 되던데요)
왜 난형에게 마진값을 주지도 않았는데-
난제에게 마진값이 적용이 안되는것인지요?
http://blossomm.mireene.com/margins_clear.html
#lnbwrap1{width:704px;border:1px solid red;}
#lnbwrap1 #gnb{float:right;width:440px;margin:10px 0 0 0;padding:0;border:1px solid blue;}
#lnbwrap1 #gnb li{display:inline;}
#lnbwrap1 #lnb{clear:both;width:100%;margin:20px 0 0 0;/* FF Collapsing margins */ padding:0;border:2px solid green;}
#lnbwrap1 #lnb ul{}
#lnbwrap1 #lnb ul li{display:inline;}
아 궁금함은 참을수 없다!
강짱님! 저는 지금까지 그걸 열심히 설명했다고 생각하고 있었는데요. 갑자기 살아나는 흡연욕구 이거 어떻게 하실꺼에요! ㅜㅜ; (웃자고 하는 이야기 입니다 ㅎㅎ)
일단 IE를 믿지 마세요. 그부분은 확실히 IE 6~7 렌더링이 틀린겁니다. 확인해 보시면 아시겠지만 OP, SF, CR 모두 FF와 동일하게 렌더링 하고 있습니다. 왜냐하면 CSS 표준 명세가 그런 방식으로 렌더링 하도록 설명하고 있기 때문이죠.
CSS 명세가 왜 그렇게 렌더링 되도록 하는지 다시한번 설명해 보겠습니다. ^^;
1. #gnb는 현재 float:right 되어 있습니다.
2. #lnb는 float:none 상태이고 clear:both 상태 입니다.
3. 그러므로 #gnb와 #lnb는 현재 서로 다른 층에 떠 있습니다.
float된 녀석들은 마치 position:absolute 된 것처럼 float 되지 않은 주변 요소로부터 다른 층에 떠 있다는 사실은 이미 알고 계시리라 믿습니다. 그렇다면 지금 당장 #lnb 에서 clear:both 속성과 margin-top 속성을 지워보세요. #gnb와 #lnb는 서로 겹치게 된다는 것을 알 수 있습니다. 왜냐하면 서로 다른 층에 떠 있기 때문에 겹침이 발생 합니다.
다시 #lnb에 clear:both 속성을 추가해 보세요. 이 때 어떤 현상이 발생하는지를 이해하는 것이 강짱님의 궁금증을 풀어드릴 수 있을것 같습니다.
clear 요녀석 사실 알고보면 참 웃긴 녀석입니다. clear:both 속성을 부여 했을 때 아래쪽에 오는 블럭은 더 이상 자신의 행에 오지 못하도록 강제로 개행 시키지만 위쪽에 오는 블럭은 개행시키지 않습니다. 개행 되는 것처럼 보일 뿐 실제로는 #gnb의 높이만큼 가상의 margin-top이 형성 됩니다. 보더를 포함한 #gnb의 높이가 현재 21px이기 때문에 #lnb는 가상의 위쪽 마진이 margin-top:21px 이렇게 설정되어 버렸습니다.
이 가상의 margin-top은 Firebug 같은 디버깅 툴로 확인해 봐도 보이지 않습니다. 오직 #gnb로부터 개행된 것처럼 보이기 위하여 정확히 #gnb의 높이만큼만 설정된 가상의 마진입니다. 이때 저작자가 설정한 마진은 가상의 마진보다 수치가 작으면 무시해 버리기 때문에 저작자의 마진이 적용되지 않는 것처럼 보일 뿐입니다.
따라서 이 상황에서 #lnb의 margin-top을 이용해서 #gnb로부터 이격시키고자 한다면 margin-top 값은 21px 이상의 값을 사용해야 합니다. 저작자가 설정한 #lnb의 margin-top을 22px 으로 변경해 보세요. 그때부터는 마진이 발생하기 시작한 것처럼 보일 것입니다.
이 문제는 이해가 되실때까지 제가 책임지고 설명 드리겠습니다! ㅎㅎㅎ.
흑. 찬명님 바쁘실텐데…
답변 감사해요~
이제 확실히 이해 됫답니다.
잠시 IE를 믿었던게 문제였군요.ㅋㅋㅋ
IE 역시.ㅜㅜ
숨겨진 margin-top 부분을 확인 할수 없다는게
참으로,,,,난감한..;;;
훌륭하신 답변 보고 감탄하고 가요~
찬명님 흡연수를 늘려드리는것 같아 살짝
죄송스럽다는,,,ㅡ,.,.ㅡ;;;;하하
이해 안되시면 정말 다시 질문 하셔야 되요. ^^; 즐겁게 댓글 달 마음에 준비가 되어 있습니다. ㅋㅋㅋ.
글 잘 봤습니다. 정말 유용했습니다.
zoom이라는 속성 자체를 처음 들었습니다.
그런데 원래 핵이라는 거는 w3 css 밸리데이터를 통과하지 못하는 건가요?
w3 css 2.1상세에서도 zoom 속성은 찾을 수가 없네요.
네, zoom 이라는 속성은 표준 문법이 아니라 MS IE 전용 문법입니다. 따라서 CSS 유효성 검사는 통과하지 못합니다. 그 밖에 핵이라고 불리우는 것들 대부분은 CSS 유효성 검사에서 오류로 표시 됩니다. 수 많은 MS IE 브라우저의 버그를 해결하기 위해서 어쩔 수 없이 사용할 수밖에 없는 상황이나 그럼에도 불구하고 되도록 자제하는 것이 좋겠다는 의견도 드립니다. 감사합니다.
저 그럼 zoom대신에 overflow:hidden; height:1%;를 사용하면 css 유효성 검사에서 오류는 안 나오는데 문제점이 뭔가요???저는 zoom을 쓰다가 핵을 쓰면 안좋다고해서 height:1%로 바꿔서 해서 괜찮을줄 알았는데…어떤분이 height:1%로도 그다지 좋지않은 방법이라고 해서요…도대체 height:1%가 안좋은 점인 뭔가요???
height:1% 라는 속성과 값을 사용할 때 이 값은 상대적인 값이 됩니다. 상대적인 값의 특징은 자기 자신의 값이 부모를 기준으로 결정된다는 점인데요. 만약 자식에게 1%의 높이를 부여 했는데 부모가 100px 이라는 절대적인 높이 값을 지니고 있으면 어떻게 될까요?
자식의 높이는 부모가 지닌 100px 높이의 1%에 해당하는 높이를 갖기 때문에 px으로 환산하는 경우 자식요소의 실제 렌더링 높이는 1px이 됩니다. 즉, 부모에게 높이값이 지정되어 있는 경우 사용이 제한적이라는 점이 단점이라고 할 수 있습니다. 1%라는 값을 사용하려면 부모에게 높이값을 지정해서는 안되니까요.
핵 사용을 줄여야 한다는 의견에도 동의하고 유효성 검사를 통과하는 것이 좋다는 의견에도 모두 동의하지만 저는 현실적으로 CSS의 유효성 검사 통과에 대하여 지나치게 집착하지 않아도 된다고 생각합니다.
현실적으로 핵을 사용하지 않으려면 때로는 디자인을 변경하거나 또는 몇 픽셀의 오차쯤은 발생하더라도 허용되는 환경이어야 하는데 그렇지 못한 환경에서 핵조차도 사용하지 않으려는 노력은 너무 많은 비용을 증가시키기 때문이라고 생각합니다.
HTML의 유효성은 화면 깨짐등 브라우저 렌더링에 직접적으로 큰 영향을 주기도 하고 의미론적인 마크업을 유지해야 하는 관점에서 반드시 지켜져야 한다고 생각하지만 CSS의 유효성은 적당한 선에서 타협할 필요가 있다고 생각합니다.
답변에 감사합니다…항상 좋은 자료와 정보 많이 배워가네요…
오옷~!!! 좋은 정보 감사합니다. 많이 배우고 가네요.^^
여태 overflow를 썼었는데 이제는 :after로 써야겠군요.
표준계열 브라우저들을 위한 :after 와 IE7 이하의 브라우저들을 위한 ms 전용 속성 { zoom:1 } 병행 표기 잊지 마세요. ^^
웹표준 할꺼면 웹표준만 하세요.
잡태그 쓸거면 웹표준 운운하지 마시구요.
자기가 할수 있으면 다 해야하고, 자기가 못하면 그정도는 해도…
이런식은 합당한 논리가 아닙니다.
웹표준 단어 삭제하시고, 크로스브라우징 전문 블로그라고 타이틀을 달아야 할 것 같아요. 이 블로그가 웹표준의 의미를 퇴색시키고 있습니다.
이 사람 뜸하다가 또 심심해서 왔나부다 하지시고 다시함 생각해 보세요.
제가 볼땐 웹표준 블로그는 아닙니다.
잡태그 운운해서 심기 불편하게 해드려 죄송하네요. ^^
조소님께서는 어떻게 하면 이런 잡태그를 쓰지 않고도 브라우저 호환성 문제를 극복하고 계신지 제게 노하우를 공유해 주실 수 있으신지요?
뭔가 대안을 가지고 계시기에 이런 말씀 하시는 줄로 알고 고수님의 댓글을 기다려 보겠습니다. 한 수 가르쳐 주세요.
잡태그.ㅋㅋㅋ
맘이 안타깝네요.ㅋㅋ
머가 잡태그 인지……
웹표준….크로스 브라우징…. 진정 하고 싶으신 말은 무엇이신지..
정말 알 수 없는 분이시네요 ^^
아니 싫으면 안오면 되지
왜 이렇게 마이너스 기운만 내뿜는 댓글만 다시는지
모르겠네요 -.-;
아니 조소님 그렇게 말만 쓰지마시고 더 좋은 방안이 있으면 알려주신던가 해야죠…뭐 말도 없고 대안도 없으면서 잡태그 이런말을 하다니…한심하군요…
도대체 그럼 저사람은 핵을 안쓰고 완전한 웹표준으로 작업을 하신다는건가??도대체 만든 사이트라도 알려주시던가…
다크대불님 같은 경우 때문에 블로그에 정체성을 애기했던거죠.
님이 언급하신 완존한 웹표준은 잘못된 표현이라는 것입니다.
완존한 멀티브라우징(크로스브라우져) 이렇케 애기하셔야 정확한 표현 아닐까요?
웹표준개발자의 IE8 고려사항이라는 글도 잘못된 겁니다.
웹호환개발자의 IE8 고려사항 이라고 해야 정확하다는 겁니다.
찬명님이 올리신 글 내용이 그렇타는 애기입니다.
그러니까 다크대불님처럼 웹표준과 멀티브라우징을 구분 못하시는 경우가 다반사라는 거져.
도대체 왜 웹표준에서 DD LI 태그를 사용해서 구현하는지 의미도 알지못한채
크로스브라우져를 완존한 웹표준이라고 생각하시니…. 정말 큰일이져…
아니…그러니깐 조소님은 웹표준이랑 멀티브라우저랑 구별한다는건데…그걸 알면 님블로그나 사이트가 있으면 알려달라는거죠??정확히 모르니깐 여기저기 돌아다니면서 알려고 하는거 아닙니깐….
정말 님이 얼마나 고수인지는 모르겠지만…그렇게 잘 알면 블로그를 만드셔서 웹표준이 이런거다 알려야 하는거 아닙니깐…그렇게 말로만 뭐가 잘못된다고 하지 마시고요…
조소님 주장의 핵심은 제 블로그의 정체성 인것으로 파악 됩니다. “웹 표준 아닌 잡 태그를 사용하면서 웹 표준 운운하지 말고 차라리 웹 상호 운용성 블로거라고 해라.” 맞나요?
만약 제가 조소님 논의의 핵심을 잘 간파 했다면 제 블로그에 ‘상호 운용성’ 이라는 주제를 추가하면 될 것 같습니다.
제가 받아들일 수 있는 부분은 제가 웹 표준에 대한 글만 쓰지 않는 블로거라는 논리인데 이 부분은 조소님께서 정확히 보셨습니다. 저는 웹의 상호 운용성을 극대화 하기 위한 방법의 하나로써 웹 표준을 이해하고 있고 웹 표준은 제가 다루는 여러가지 주제 가운데 하나일 뿐 입니다.
하지만 웹 표준에 대한 주제만 쓰기로 독자들과 약속한 적도 없고 웹 표준이 만능이라고 생각하지도 않기 때문에 조소님께서 말씀하시는 브라우저 호환성이나 웹 표준 아닌 수단에 대한 경험적인 이야기들을 되도록 가감없이 풀어놓고 있습니다.
제 경험을 나누는데 있어서 조소님이나 다른 분들께 득이 될지 실이 될지의 여부는 각자가 판단 해주셔야 합니다. 왜냐하면 저는 제 글을 강요하는 것이 아니기 때문이며 제 글의 파급효과로 인해서 많은 분들께 잘못된 견해가 전파되는 상황이 온다면 저는 조소님과 같은 비평가분들께 혹평을 받는것이 당연하고 제 잘못을 인정할 준비가 되어 있습니다.
다시 한번 조소님께 여쭈어 봅니다.
웹 표준이 아닌 잡태그를 사용하면 왜 나쁜지?
만약 잡태그가 나쁘다면 정말로 잡태그를 사용하지 않고 웹 표준을 잘 지키면서 얼마든지 웹을 구현할 수 있는지?
좀 알려주세요. 제가 더 이상 웹 표준의 의미를 퇴색시키면 안되지 않겠습니까?
웹 표준과 상호 운용성이라는 개념은 조소님 설명 덕분에 저도 이제 잘 알겠습니다. 더 이상 그런 원론적인 이야기는 안하셔도 될 것 같습니다.
오늘 ‘웹 접근성 향상을 위한 국가표준 기술 가이드라인 발표’ 되었습니다. 이제 우리나라도 가이드라인이 생겼으니, 기준에 더 가까운 사이트 제작이 가능해졌다고 할 수 있겠죠?
저도 많이 고민하는 부분입니다.
Fragment로 접근할 필요가 없음에도 남용되는 `id` 속성, CSS 작성에 도움이 되기는 하나 마크업 상 아무 의미 없는 `[div class="wrap"]`(더 나쁜 것은 `[div id="wrap"]`), 둥근 박스를 만들기 위해 낭비되는 무의미한 엘리먼트들, 칩셋의 정확한 부위를 정확하게 표시하기 위한 투명한 `[img ... /]`. 기계가 쉽게 읽을 수 있는 순수한 문서를 작성할 수 없게 만드는 필요악들입니다. 그나마 정적인 문서에서는 CSS 디자이너의 고된 노력이 있다면 마크업을 순수하게 유지한 채 어떻게든 원하는 디자인을 만들어낼 수야 있겠지만, 자바스크립트를 사용한 애니메이션 효과라도 추가되는 날에는 눈앞이 캄캄해집니다. 의미 상, 마크업 상 떨어져있지만 디자인 상 붙어있는 엘리먼트들이 한 덩이처럼 스르르 움직이게 해야할때 그것들을 묶어주는 부모 엘리먼트가 없음에 괴로워할 것입니다(`$(’.authentication, .logo, .navigator, …’).move(…)` vs. `$(’.header’).move(…)`).
이전까지 저는 복잡한 애니메이션은 포기하고 최대한 CSS만을 사용하게 순수한 마크업을 유지하는데 초점을 맞췄습니다. 하지만 시간이 지나면서 원하는 디자인(그리고 개선사항이 반영되며 점점 변해가는 디자인)을 순수한 마크업만으로 만들기란 불가능에 가깝다는 것을 깨닫게 되었습니다. 그렇다고 위에서 나열한 필요악들을 무작정 사용할 수는 없었습니다. 적어도 기계가 읽을 때 ATOM 포맷만큼의 깔끔한 마크업은 포기할 수 없었기 때문입니다. 다른 사람이 작성한 문서를 파싱할 때 그 문서에 사용된 필요악들이 작업을 무척 어렵게 만들던 기억이 많습니다.
한 동안 주위 사람들과 함께 고민한 결과 나름대로의 대안을 찾아낼 수 있었습니다.
[script type="text/javascript"]/*[!CDATA[*/{document.write('[div class="wrap"][div class="contents"]‘);}/*]]]*/[/script]
[h1]Subject[/h1]
[p]…………………[/p]
[p]……………[/p]
[p]………………[/p]
[script type="text/javascript"]/*[!CDATA[*/{document.write('[/div][div class="header"]‘);}/*]]]*/[/script]
[div class="navigator"]…[/div]
[div class="authentication"]…[/div]
[div class="logo"]…[/div]
[script type="text/javascript"]/*[!CDATA[*/{document.write('[/div][/div]‘);}/*]]]*/[/script]
디자인을 위한 필요악을 문서에 직접 쓰지 않고 스크립트로 추가시키는 방법입니다. JS 엔진이 포함된 브라우저 이외에는 `[script type="text/javascript"]`를 해석하지 않습니다. 별도의 파서를 사용해 파싱하는 경우에도 `[script]`는 간단히 무시하게끔 만들 수 있습니다. CSS 디자인과 JS 작업 시 활용할 수 있는 엘리먼트를 마음껏 추가할 수 있고 웹표준에서 벗어나지도 않았습니다. 치명적인 단점이 있다면 CSS는 작동하지만 JS는 작동하지 않는 환경에서는 디자인이 어떻게 망가질지 보장할 수 없단 것입니다. 물론 “JS가 작동하지 않는 환경에서도 모든 기능을 사용할 수 있어야 한다”는 원칙에는 아무런 영향도 주지 않습니다. 이 경우에는 다음과 같은 방법을 사용할 수 있을 것입니다.
[head]
…
[style type="text/css"]
/*[![CDATA[*/
body.js-enabled h1 { ... }
body.js-enabled p { ... }
body.js-enabled blockquote { ... }
/*]]]*/
[/style]
[/head]
[body]
[script type="text/javascript"]/*[!CDATA[*/{document.body.className = 'js-enabled';}/*]]]*/[/script]
…
[/body]
서버사이드에서 처리해줄 수 있다면 더 편하게 작업할 수 있을 것입니다. 가령….
[fake:div class="wrap"]
[fake:div class="contents"]
[h1]Subject[/h1]
[p]…………………[/p]
[p]……………[/p]
[p]………………[/p]
[/fake:div]
[fake:div class="header"]
[div class="navigator"]…[/div]
[div class="authentication"]…[/div]
[div class="logo"]…[/div]
[/fake:div]
[/fake:div]
이 방법이 모든걸 취하지는 못한단 것은 자명합니다. JS가 작동하지 않을 때 기능 사용에만 문제가 없다면 삭막한 기본 스타일밖에 보이지 않을지라도 그정도는 감수할 수 있다고 생각합니다. 적어도 제게는 나머지 부분들이 더 중요하게 여겨집니다.
엥 사각괄호 사용하면 되는 것 아니었나요 ㅠㅠ.
만약 꺽쇠를 사용했다면 [script]…[/script] 부분의 코드는 화면에 출력되지 않았을 꺼야. HTML을 지원하거든. 꺽쇠 사용에 대한 내 설명이 부족했나보다. 이해해 주렴.
흥섭이 제안해준 코드도 결국 현실 세계의 HTML에 대한 한계를 반증하는 것으로 보여. 그리고 자바스크립트를 이용해서 해결하려는 발상은 정말 결벽에 가까울 정도의 노력이라고 생각해.
하지만 그렇게까지 웹 표준 문법이나 의미론적 마크업을 완벽하게 지켜내서 얻을 수 있는것은 뭘까? 갑자기 내가 웹 표준에 반기를 든것 같이 보일지도 모르겠지만 나는 항상 현실과 타협할 준비가 되어 있어.
웹 표준 문법을 지키지 않아도 된다고 말하는게 아니라 지금 내가 작성하고 있는 코드는 웹 표준을 지키고 싶은 웹 표준 개발자의 결벽주의와 그것을 호락호락하게 받아주지 못하는 현실 사이에서 나온 타협안이 아닐까?
이렇게 나온 코드들을 웹 표준 문법에 맞지 않는다는 이유로 쓰레기 같다고 말할 수 있을까? 이런 쓰레기 같은 코드를 작성한 사람들에게 돌을 던질 수 있는 사람은 얼마나 될까?
조소님 같은 분이라면 그럴 수 있을지 모르지. ㅎㅎ.
예나 지금이나 댓글을 보고있는데;;
조소님 한번 뵙고 같이 이야기 해보고싶네요 좋은 의미임 !
서로의 차이란게 있지만 예전의 저처럼 접근하는 방식이 많이 틀렸다고 할까요
아는 형님이 저한테 그러더군요
“아무리 맞는 말이라도 접근방법이 나쁘면 이해해주지 않는다고”
이말에 심히 공감해서 요세는 많이 바꼈다죠…. (__ ;;
와….엄청난 정보였습니다…
float을 해제하려고 float을 해제시키는 속성 clear에 이런저런 속성값 아무리 넣어봐도, IE에서 생기는 약간의 높이…마진,패딩,폰트,높이 0으로 줘도 해결이 안되던걸 이렇게 해결할 수 있었군요…
점점 더 좋은 방법을 찾아갈 수 있도록 도움주셔서 감사합니다…
엄청난 피드백 감사합니다. ^^;
세상에 이런 방법이 있었다니… 정말 잘 보고 갑니다. ^^
글 하나하나가 감탄을 자아내게 하는군요!
앞으로도 많이 보도록 하겠습니다. 감사!