1. 问题场景
三列布局中,如果想要将主要内容main优先加载优化,则DOM如下所示
1 2 3 4 5
| <div class="g-container"> <div class="g-main">我是主列</div> <div class="g-left">我是左列</div> <div class="g-right">我是右列</div> </div>
|
但又想将主要内容在中间位置显示,便有如下css
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| .g-container { float: left; width: 100%;
& > div { width: 190px; min-height: 30px; } }
.g-container .g-main { float: left; width: 100%; background: #cc6630; }
.g-left { float: left; margin-left: -100%; background: #f00; }
.g-right { float: left; margin-left: -190px; background: #00f; }
|
下面逐行分析一下:
第1行:grid-s5m0e5 是一个布局框的名称,我们为其定义了宽度100%(在IE6一不定义100%时,有点小问题,亲们自己可以一试)
第2行:col-main 【主列】:浮动左侧,宽度100%(宽度全让它给占了,左右两侧的层该怎么办?)
第3行:col-sub 【子列】:浮动左侧,宽度190,左边界为-100%(此处是关键:浮动情况下,负边界值会导致DIV上移,而使用-100%可以确实它移动到最左侧。)
第4行:col-extra 【附加列】:左浮动,宽度190,左边界为-190px(道理同上,注意的是,负左边界一定要大于或等于该DIV的宽度,才能靠到上一行去)
让我们看看效果
但这样布局后发现主列中的文字不见了,经过DOM分析发现,原来是被col-sub挡住了,那么如何给main正确的定位呢。
1.圣杯布局(margin+position)
左右两列通过margin-left
与left和right
准确定位,中间列用width:100%撑开
圣杯布局的关键点父元素需要设置padding
margin-left
取值为百分比时,是以其父元素的宽度为基准的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| .g-container { position: relative; padding: 0 190px;
& > div { float: left; min-height: 30px; } }
.g-main { position: relative; width: 100%; background: #cc6630; }
.g-left { position: relative; width: 190px; margin-left: -100%; left: -190px; background: #ffcc00; }
.g-right { position: relative; width: 190px; margin-left: -190px; right: -190px; background: pink; }
|
2. 圣杯布局(flex)
利用flex的order属性调整位置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| .g-container { width: 100%; display: flex; flex-direction: row; flex-wrap: nowrap;
& > div { min-height: 30px; } }
.g-main { order: 2; flex: auto 1 0; background: #cc6630; }
.g-left { order: 1; flex: 200px 0 0; background: #ffcc00; }
.g-right { order: 3; flex: 200px 0 0; background: pink; }
|
这种写法更加简洁,但是兼容性不太好
3.双飞翼布局(margin)
利用margin-left
属性将左右两列放置到准确的位置,通过控制 main列 的margin
空出左右两列
下面是淘宝的做法:
1、DOM结构的改变:在.col-main下再次添加一个 .main-wrap
2、利用CSS调整.main-wrap的位置。【这里很简单,就是把左右被挡住的部分,设置为main-wrap的左 右边界即可】
1 2 3 4 5 6 7 8 9
| <div class="g-container"> <div class="g-main"> <div class="main-wrap"> 我是主列,出来吧! </div> </div> <div class="g-left">我是左列</div> <div class="g-right">我是右列</div> </div>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| .g-container { float: left; width: 100%;
& > div { float: left; width: 190px; min-height: 30px; } }
.g-container .g-main { width: 100%; background: #cc6630; .main-wrap { margin-left: 200px; margin-right: 200px; background: #0f0; } }
.g-left { margin-left: -100%; background: #f00; }
.g-right { margin-left: -190px; background: #00f; }
|
最终效果
优点
- 实现了内容与布局的分离,即Eric提到的Any-Order Columns.
- main部分是自适应宽度的,很容易在定宽布局和流体布局中切换。
- 任何一栏都可以是最高栏,不会出问题。
- 需要的hack非常少(就一个针对ie6的清除浮动hack:_zoom: 1;)
- 在浏览器上的兼容性非常好,IE5.5以上都支持。
不足