为了账号安全,请及时绑定邮箱和手机立即绑定

双飞翼布局介绍-始于淘宝UED

/ 猿问

双飞翼布局介绍-始于淘宝UED

仔细分析各种布局的技术实现,可以发现下面三种技术被经常使用:

浮动 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效果

仔细查看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代码就可以搞定一切。最近在一个论坛项目中准备尝试使用这个布局。希望大家有更好的布局方法一定要多多分享。


原文来自:http://www.dqqd.me/flying-wing/

查看完整描述

22 回答

已采纳
?
你在我记忆里

哎 应该早点看到了,阿里笔试题啊

查看完整回答
7 反对 回复 2015-04-14
?
Zayne137

这篇文章有些细节方面没有介绍,大家可以先看这篇博客,对双飞翼布局有所了解之后看这个会轻松很多http://www.cnblogs.com/langzs/archive/2013/01/27/taobaoshuangfeiyi.html

查看完整回答
8 反对 回复 2016-02-01
?
mosile

贴绝对定位的我也是醉了 就不能撑开父元素高度这一条就被毙了。

查看完整回答
3 反对 回复 2016-01-04
?
qq_绯红的倩影_0

在圣杯布局中,将main设置padding(不设置bd),然后设置box-sizing:border-box,后面相对定位增加的那一块就不需要了

查看完整回答
反对 回复 2018-06-05
?
苏陌浅

.extra根本出不来,不知道怎么回事


查看完整回答
反对 回复 2017-06-27
?
qq_青枣工作室_0

怎么链接里是澳门博彩的网址

查看完整回答
反对 回复 2016-05-01
?
慕粉3238884

为什么链接打不开。

查看完整回答
反对 回复 2016-05-01
?
拾7

圣杯布局中,extra的宽度最开始设置的是190PX,后面又突然改成230PX了,这点需要注意,extra完整的css应该是

.extra {        

             float: left;        

             width: 230px;        

             margin-left: -230px;        

             position: relative;        

             right: -230px;    }

查看完整回答
反对 回复 2016-03-17
?
这是步好棋

哈哈,评论里的小伙伴真有趣

查看完整回答
反对 回复 2016-03-14
?
BorisGong

.extra {        

             float: left;        

             width: 230px;        

             margin-left: -230px;        

             position: relative;        

             right: -230px;    }

这里用margin-right和去掉right-230就能实现,这样会少一个标签

查看完整回答
反对 回复 2015-09-21
?
加入滚烫开水

双飞翼布局主要解决俩问题:1、三列布局,中间宽度自适应,两边定宽; 2、中间栏要在浏览器中优先展示渲染。

先去搜搜什么叫双飞翼再来贴代码吧。

查看完整回答
反对 回复 2015-09-16
?
野山椒鸡杂

开了脑洞。。

查看完整回答
反对 回复 2015-07-12
?
谭谭谭

解释的是一坨坨屎似的。看不懂只能复制粘贴了~~

查看完整回答
反对 回复 2015-05-31
?
aadega

你这个DOM解析还是从left开始的,

        <div class="left">left</div>

        <div class="middle">main</div>

        <div class="right">right</div>


查看完整回答
反对 回复 2015-04-17
?
sally127

great and thanks

查看完整回答
反对 回复 2015-04-15
?
creepwalk

看不懂。。。。。。唉

查看完整回答
反对 回复 2015-04-05
?
我才是深蓝
<!DOCTYPE html>
<html>
<head>
	<title></title>
	<style type="text/css">
	.left-column {
		width: 300px;
		height: 300px;
		/*margin-left: -100%;*/
		float: left;
		background-color: blue;
	}

	.center-column {
		height: 300px;
		margin-left: 300px;
		margin-right: 300px;
		background-color: green;
	}

	.right-column {
		width: 300px;
		height: 300px;
		margin-left: -100%;
		float: right;
		background-color: yellow;
	}
	</style>
</head>
<body>
	<div class="wrapper">
		<div class="left-column">
			
		</div>
		<div class="right-column">
			
		</div>
		<div class="center-column">
			
		</div>
	</div>

	<div class="test"></div>
</body>
</html>

我这样也行,只不过 html 顺序需要改变

查看完整回答
1 反对 回复 2015-04-04
  • weibo_煮了吧_0
    weibo_煮了吧_0
    真的可以哎,目前还没发现什么错误,但比双飞翼简洁多了,淘宝的大神不可能想不到这种方式啊,求大神解释1!!!
  • 我才是深蓝
    我才是深蓝
    需要改变顺序 不喜欢。
  • weibo_我喜欢大海洋_0
    weibo_我喜欢大海洋_0
    淘宝在DOM中是按主列、子列、扩展列的顺序书写的,此时网页被浏览器解析时,按照主、子、附加的顺序进行加载 —— 也就是我们常说的”重要的内容先加载”。这种结构会更好一些。(淘宝的大神就是这样考虑的。。。)
点击展开后面1
?
Perona

嘿嘿~~知道啦~~~

查看完整回答
反对 回复 2015-04-04
?
qq_心的回归_0

这评论也是醉了,稍微了解下双飞翼再来贴代码吧,否则只会是笑柄

查看完整回答
反对 回复 2015-10-24
?
Light1980

...我貌似发现了不添加新标签的完美布局?不太确定……sub漂浮到左上,定宽。main宽度自适应,margin-right设置为负值,等同于padding-right的正值。然后extra漂浮到右上,width等于main的margin-right。如此就是两边定宽,main宽度自适应的布局了。

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
     <meta http-equiv="X-UA-Compatible" content="IE=Edge">
<title>测试页</title>
<link rel="stylesheet" href="test.css">
        <style>
        #header {
    width: 100%;
    height:50px;
box-sizing:border-box;
    border: 1px solid black;
background: #474;
}
#footer{
    width: 100%;
    height: 50px;
    box-sizing:border-box;
border: 1px solid black;
background: #747;
clear:both;
}
#div6 {
    margin-bottom: 10px;
}
.div6-a {
    float: left;
    width: 50px;
    height: 50px;
    background: #f00;
box-sizing:border-box;
    border: 1px solid black;
}
.div6-b {
    margin: 0 0 -50px 0;
padding: 0 50px 0 50px;
    height: 50px;
    background: #00f;
    box-sizing:border-box;
    border: 1px solid black;
    
}
.div6-c {
    float: right;
    width: 50px;
    box-sizing:border-box;
    border: 1px solid black;
    height: 50px;
    background: #ff0;

}   
</style>
</head>
<body>
   <div id="header">header</div>
   <div id="div6">
            <div>111</div>
            <div>111</div>
            <div>111</div>
        </div>
<div id="footer">footer</div>
    </body>
</html>


查看完整回答
反对 回复 2015-04-21
  • cfancc
    cfancc
    这种想法是另一种实现三列布局的形式,但是你实现的很多地方都不完善,如果详细测试一下就会发现很多问题,这个是定高的,比如如何撑满整个屏幕?。应该将main元素不浮动放到最后面,float元素放前面,然后main上加左右margin
  • Light1980
    Light1980
    不太理解您说的“如何撑满整个屏幕”这句话。能再阐释一下吗?
  • cfancc
    cfancc
    垂直方向上,各分栏的高度一致且以最高的为准
首页上一页12下一页尾页

添加回答

回复

举报

0/150
提交
取消
意见反馈 常见问题 APP下载
官方微信