仔細分析各種布局的技術實現,可以發現下面三種技術被經常使用:
- 浮動 float
- 負邊距 negative margin
- 相對定位 relative position
這是實現布局的三個最基本的原子技術。只要巧妙組合,並加以靈活運用,就能“拼”出各種布局的實現方案。
嘗試之路考慮以下DOM結構:
<div id="page"> <div id="hd"></div> <div id="bd"> <div class="main"></div> <div class="sub"></div> <div class="extra"></div> </div> <div id="ft"></div> </div>
利用浮動元素的負邊距來定位:
.main { float: left; width: 100%; } .sub { float: left; width: 190px; margin-left: -100%; } .extra { float: left; width: 190px; margin-left: -190px; }
這樣我們得到了第一個嘗試頁面 點擊這里查看效果
可以看出,通過簡單的負邊距,已經讓sub和extra定位到正確的位置。剩下的問題是如何讓main也定位到正確的位置。
一個自然的想法是,給main的容器#bd添加padding:
#bd { padding: 0 230px 0 190px; }
點擊這里查看效果
這樣能讓main定位到正確的位置,但sub和extra的位置不對了。這是一個思考的關卡。既然sub和extra的位置不對,那就想辦法調整到正確的位置。相對定位隆重登場:
.sub { float: left; width: 190px; margin-left: -100%; position: relative; left: -190px; } .extra { float: left; width: 230px; margin-left: -230px; position: relative; right: -230px; }
點擊這里查看完成頁面
很明顯,這就是聖杯布局!
在不增加任何額外標簽的假設上,我嘗試了各種想法,但始終都沒找到完美的布局實現(聖杯布局是我覺得所有想法中最接近完美的)。
既然不添加額外標簽時,完美布局的實現如此困難,那如果允許添加一個額外標簽呢?在淘寶UED內部的探討中,給main增加了一層包裹:
<div id="main" class="column"> <div id="main-content">#main</div> </div>
里層main-content的作用就是將main定位到合適的位置,並方便設置padding等屬性。想到此處,就像牛頓被蘋果砸傻了一樣,原來的main定位問題迎刃而解:
<div id="page"> <div id="bd"> <div class="main"></div> </div> </div>
CSS僅需增加一行:
.main-wrap { margin: 0 230px 0 190px;}
想看example4效果點這里
一切如此簡單!除了添加了一個額外標簽,其它各方面,表現都很完美(試了下IE5.5, 也沒任何問題)。目前只用到了浮動和負邊距,如果再引入相對定位,還可以實現三欄布局的各種組合
.extra { float: left; width: 230px; margin-left: -100%; position: relative; left: 190px; } .main-wrap { margin-left: 430px; }
仔細查看example5和example4的源代碼,可以發現DOM結構是完全一樣的,僅僅CSS稍有不同。這意味着HTML結構和CSS布局在一定程度上解耦了,我們開發HTML代碼時,從內容出發即可,無需過多的考慮布局。這正是漸進增強在前端工作流程上的體現。
如果把三欄布局比作一只大鳥,可以把main看成是鳥的身體,sub和extra則是鳥的翅膀。這個布局的實現思路是,先把最重要的身體部分放好,然后再將翅膀移動到適當的地方。因此請容許我給這個布局實現取名為雙飛翼布局(Flying Swing Layout).
就如上圖中的鳥有各種姿勢一樣,利用雙飛翼布局,我們也可以實現各種布局。這里有個嘗試頁面,利用雙飛翼,實現了一套柵格化布局系統。
優點
- 實現了內容與布局的分離,即Eric提到的Any-Order Columns.
- main部分是自適應寬度的,很容易在定寬布局和流體布局中切換。
- 任何一欄都可以是最高欄,不會出問題。
- 需要的hack非常少(就一個針對ie6的清除浮動hack:_zoom: 1;)
- 在瀏覽器上的兼容性非常好,IE5.5以上都支持。
不足
- main需要添加一個額外的包裹層。
- 等待你的發現與反饋。
雙飛翼的布局非常靈活,只要調整css代碼就可以搞定一切。最近在一個論壇項目中准備嘗試使用這個布局。希望大家有更好的布局方法一定要多多分享。
