【百度前端学院学习笔记】Day9 圣杯布局和双飞翼布局

【百度前端学院学习笔记】Day9 圣杯布局和双飞翼布局

参考资料:
In search of the Holy Grail - A list apart
CSS布局 – 圣杯布局 & 双飞翼布局
双飞翼布局介绍-始于淘宝UED

其实圣杯布局跟双飞翼布局的实现,目的都是左右两栏固定宽度,中间部分自适应。在实现上,DOM结构中先出现中间的部分并让它占据父元素100%宽度。两种方法中间部分不被两边遮挡的时候有所不同。

考虑这样一个DOM结构(完整html代码会放在每个方法的后面)

<div id="header"></div><div id="container">
  <div id="center" class="column"></div>
  <div id="left" class="column"></div>
  <div id="right" class="column"></div></div><div id="footer">
</div>

在指定左边蓝色的宽度为200px,右边橘色的宽度为150px的情况下,如何实现下面的布局(中间灰色自适应)?
在这里插入图片描述

圣杯布局(古老而费解的方法)

  1. DOM结构中(也就是html中),三个div出现的顺序为中、左、右,为什么不是左、中、右呢?接着往下看。
  2. container中留下足够的空间给leftright元素,注意这里用padding给出空间,不影响content(也就是子元素width = 100%)的大小。
    #container{
        padding-left: 200px;
        padding-right:190px;
        overflow: hidden /* 闭合浮动 */
    }

示意图如下:
在这里插入图片描述

  1. 中、左、右三个div都向左浮动,并将定位改成relative待用。
    #container .column{
        float: left;
        position: relative;
    }

此时效果示意图如下:由于center占据了父元素的content 100%的宽度,所以本来应该紧贴着centerleftright不得不被挤到下一行。
在这里插入图片描述

  1. left拉到上一行:
#left {
  width: 200px;        /* LC width */
  margin-left: -100%;  
}

这里要理解一下margin-left设为负值的含义:

margin为正数是向外推开相邻元素以扩展空间,那么margin为负数就是让相邻元素入侵本元素的空间,或者说往反方向推元素。
经过margin-left: -100%的设置,left左边的元素 (即center) 挤占了left100%的宽度(相当于父元素content的宽度),因此会出现这样的情况:leftcenter重叠。

就像下图我画的一样,红色阴影部分为left的margin-left移动经过的区域,蓝笔为left元素的运动轨迹。本来left的位置应该是悬在center左边的,只是因为一行放不下换行了。现在将left的margin-left设为-100%就可以让left移动到新的位置,与center一行,而且遮挡了部分的center
在这里插入图片描述

这时候relative的定位就派上用场了:给#left 添加一个right定位,把它向右推200px,正好占满父元素container的left-padding

#left {
  width: 200px;        /* LC width */
  margin-left: -100%;  
  right: 200px;        /* LC width */
}

在这里插入图片描述
5. 把right也按照同样的方法,先左推进center同一行内,再通过relative定位推到右边。

#right {
 width: 150px;          /* RC width */
 margin-left: -150px;  /* RC width */
 left: 150px;
}

大功告成
在这里插入图片描述
6. 考虑到窗口缩小,直到center自适应的宽度小于left,就会出现这样的情况(双飞翼布局的缺点):
在这里插入图片描述
为了避免这种情况,我们给body设置一个最小宽度:

    body{
        min-width: 550px;
    }

7.考虑到美观性,我们应该给三个div设置一个padding,这样文字才不会紧贴着边。

【栏内的padding规则】:

  • 这里left维持大小不变,通过缩小width来给padding腾出空间。
#left {
 width: 180px;        /* LC fullwidth - padding */
 padding: 0 10px;
 margin-left: -100%;
}
  • 然后right也是同样地通过调整width来留出padding。
  • center则维持content的宽度100%不变,额外增加10px的上下padding和20px的左右边距(当然也可以通过box-sizing: border-box,这样不改变中间元素的实际宽度,会容易很多,但是为了演示需要,这样还是在100%的基础上额外增加了中间元素的宽度)。

【栏内padding后如何保持布局】:

  • 相应的,left元素的right位置属性要加上center的padding,因为要越过center元素,仅仅靠着margin-left:100%是不够的,还差了一个left-padding和一个right-padding。这是圣杯布局十分麻烦的一个点。
  • right则维持原样。
body {
  min-width: 630px;      /* 2x (LC fullwidth +
                            CC padding) + RC fullwidth */
}
#container {
  padding-left: 200px;   /* LC fullwidth */
  padding-right: 190px;  /* RC fullwidth + CC padding */
}
#container .column {
  position: relative;
  float: left;
}
#center {
  padding: 10px 20px;    /* CC padding */
  width: 100%;
}
#left {
  width: 180px;          /* LC width */
  padding: 0 10px;       /* LC padding */
  right: 240px;          /* LC fullwidth + CC padding */
  margin-left: -100%;
}
#right {
  width: 130px;          /* RC width */
  padding: 0 10px;       /* RC padding */
  margin-left: -150px;  /* RC fullwidth */
  left: 150px;
}
#footer {
  clear: both;
}/*** IE Fix ***/
* html #left {
  left: 150px;           /* RC fullwidth */
}
  1. 最后如何使三栏的底部对齐
    在这里插入图片描述

这里有一个小技巧,即设置一个很长的padding-bottom(要超过原来最长的那个栏),再通过margin-bottom往回压,最后通过父元素的overflow:hidden来修剪。父元素的overflow:hidden属性根据最长子元素的margin位置来确定在哪里修剪。

#container .column {
 padding-bottom: 20010px;  /* X + padding-bottom */
 margin-bottom: -20000px;  /* X */
}

这里就是根据右边橘色栏向下padding后又往回margin的位置20010-20000=10px(即修改前右边橘色栏下方10px)的位置修建,效果如下:
在这里插入图片描述

最终圣杯布局的完整代码如下:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>圣杯布局</title>
<style type="text/css">

    body{
        min-width: 630px;
    }
    #container{
        padding-left: 200px;
        padding-right:190px;
        overflow: hidden;
    }
    #container .column{
        float: left;
        position: relative;
        padding-bottom: 2000px;
        
  
    }
    #center{
        padding: 10px 20px;
        background-color:#d6d6d6;
        width:100%;
    }
    #left{
        background-color:#77bbdd;
        width: 180px;
        right:240px;
        margin-left: -100%;
        padding: 0 10px;
        margin-bottom: -500px;
    }
    #right{
        background-color:#ff6633;
        width: 130px;
        padding:0 10px;
        margin-left: -150px;
        left:150px;
        margin-bottom: -500px;
    }

    .footer,.header{
        font-size: 30px;
        background-color:#999999;
        clear: both;
        position: relative;
        display: flex;
    }
    .footer h4,.header h4{
        margin:0 auto;
    }
    p{
        word-break: break-all;
    }


</style>
</head>
<body>
<div class="header">
    <h4>header</h4>
</div>
<div id="container">
    <div id="center" class="column">
        <h4>middle</h4> 
        <p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla.</p>
    </div>
    <div id="left" class="column">
    <h4>left</h4>
        <p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla.</p>
    </div>
    <div id="right" class="column">
    <h4>right</h4>
        <p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla.</p>
    </div>
    </div>
    <div class="footer">
        <h4>footer</h4>
    </div>
</body>
</html>

双飞翼布局(圣杯的改进)

双飞翼在圣杯的基础上进行改进,更加直观。

  1. 首先不再在外层容器中通过padding压缩content的空间来给两个侧边栏预留空间。而是在center里添加一个子元素inside,用子元素的margin来预留空间。
    于是DOM结构改成了:
<div id="header"></div><div id="container">
  <div id="center" class="column">
      <div id="inside"></div> <!-- 新增一个inside容器 -->
  </div>
  <div id="left" class="column"></div>
  <div id="right" class="column"></div></div><div id="footer">
</div>

在这里插入图片描述
在这里插入图片描述
3. 用同样的浮动方法,将左栏和右栏目通过margin-left为负值的方法拉到同一行。下图表示了在没有设置insidemargin的情况下的尴尬场景:inside里的文字左右边都受到了遮挡。
在这里插入图片描述
inside加上左右相应大小的margin就可以解决。可以看到,想给center添加额外的padding是很容易的。

    #inside{
        margin-left: 220px; /* 200px是左边元素的宽度,额外加20px是为了美观 */
        margin-right:170px; /* 150px是左边元素的宽度,额外加20px是为了美观 */
    }

在这里插入图片描述
双飞翼的完整代码:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>双飞翼</title>
<style type="text/css">

    body{
        min-width: 630px;
    }
    #container{
        overflow: hidden;
    }
    #container .column{
        float: left; 
        padding-bottom: 2010px;
        margin-bottom: -2000px;
    }
    #center{
        background-color:#d6d6d6;
        width:100%;
    }
    #inside{
        margin-left: 220px;
        margin-right:170px;
    }
    #left{
        background-color:#77bbdd;
        width: 180px;
        padding: 0 10px;
        margin-left: -100%;
    }
    #right{
        background-color:#ff6633;
        width: 130px;
        padding:0 10px;
        margin-left: -150px;
    }

    .footer,.header{
        width: 100%;
        font-size: 30px;
        background-color:#999999;
        clear: both;
        position: relative;
        display: flex;
    }
    .footer h4,.header h4{
        margin:0 auto;
    }
    p{
        word-break: break-all;
    }


</style>
</head>
<body>
<div class="header">
    <h4>header</h4>
</div>
<div id="container">
    <div id="center" class="column">
        <div id="inside">
            <h4>middle</h4> 
            <p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla.</p>
        </div>
       
    </div>
    <div id="left" class="column">
    <h4>left</h4>
        <p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla.</p>
    </div>
    <div id="right" class="column">
    <h4>right</h4>
        <p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla.</p>
    </div>
    </div>
    <div class="footer">
        <h4>footer</h4>
    </div>
</body>
</html>
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值