前端面试(CSS)中常问的几个布局

CSS中常用的页面布局:两栏布局三栏布局

注意:只要用到了浮动,都要考虑要让父元素包含它

1. 两栏布局

1.1 两栏固定布局

width+left

width+right

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style type="text/css">
        * {margin:0;padding:0;}
        #wrapper{
            width:800px;
            background-color: yellow;
            overflow: hidden;/*包含浮动子元素*/
        }
        .left {
            width:200px;
            height:200px;
            background-color: rgba(0,0,255,0.3);
            float: left;
        }
        .right {
            width:400px;
            height:300px;
            background-color: rgba(0,0,255,0.3);
            float: right;
        }
    </style>

</head>
<body>
    <div id="wrapper">
        <div class="left">
            <p>
                这是<em>左栏</em>哦!
                width:200px;
                height:200px;
            </p>
        </div>
        <div class="right">
            <p>
                这是<em>右栏</em>哦!
                width:300px;
                height:400px;
            </p>
        </div>
    </div>
</body>
</html>

1.2 左侧宽度固定、右侧宽度自适应

1.2.1 左侧浮动+右侧margin-left/padding-left隔开

DOM结构中左栏在上方

左栏:固定width+float:left

右栏:padding-left/margin-left

原理:不设置width、height的普通block元素,水平方向的margin能够修改border box的水平尺寸。

           不设置width、height的普通block元素,水平方向的padding能够修改content box的水平尺寸。

间隔:如果想让左、右栏之间有间隔,比如30px,可以增大当前使用的padding-left为width+间隔,或者margin-left为width+间隔,或者在当前使用的padding-left或者margin-left的基础上增加margin-left:30px;或者padding-left:30px;

(1)用margin-left实现

       这种实现方法中,整个border box从div.left的右侧紧贴着放置。

HTML结构
<div id="wrapper">
    <div class="left">
        <p>
            这是左栏哦!
        </p>
    </div>
    <div class="right">
        <img src="https://ss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=2096432854,4113309096&fm=26&gp=0.jpg"
             width="150" height="150" alt="Some of a team">
    </div>
</div>

CSS代码
        #wrapper{
            width:500px;
            background-color: yellow;
            overflow: hidden;/*包含浮动子元素*/
            resize:both;
        }
        .left {
            width:200px;
            height:200px;
            background-color:green;
            float: left;
        }
        .right {
            background-color: blue;
            margin-left: 200px;
        }

         如果想让左右栏右一定的间隔,可以在原本代码的基础上,在div.right中添加padding-left。或者把margin-left的值增大相应的值也行,比如margin-left:230px;

margin-left:230px;

margin-left:200px; + padding-left:30px;的效果:

(2)用padding-left实现

    仅将1.2.1中的margin-left:200px;换成padding-left:200px;这种实现方法中,整个border box依然从包含块的左上角放置。

如果想让左右栏有一定的间距,可以通过padding-left:200px;+margin-left:30px;实现,或者通过padding-left:230px;实现。

1.2.2 左侧浮动+右侧BFC

DOM结构不变,CSS代码:如需左右的间隔,可在left中加margin或者padding

        #wrapper{
            width:500px;
            background-color: yellow;
            overflow: hidden;/*包含浮动子元素*/
            resize:both;
        }
        .left {
            width:200px;
            height:200px;
            background-color:green;
            float: left;
        }
        .right {
            background-color: blue;
            overflow:hidden;/*右侧BFC*/
        }

 

1.3 右侧宽度固定、左侧宽度自适应

1.3.1 DOM结构right栏在上方

DOM结构中右栏在上方

右栏:固定width+float:right

左栏:padding-right/margin-right

原理:不设置width、height的普通block元素,水平方向的margin能够修改border box的水平尺寸。

           不设置width、height的普通block元素,水平方向的padding能够修改content box的水平尺寸。

间隔:如果想让左、右栏之间有间隔,比如30px,可以增大当前使用的padding-right为width+间隔,或者margin-right为width+间隔,或者在当前使用的padding-right或者margin-right的基础上增加margin-right:30px;或者padding-right:30px;

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>两栏自适应布局:右侧固定,左侧自适应</title>
    <style type="text/css">
        * {margin:0;padding:0;}
        #wrapper{
            width:500px;
            background-color: yellow;
            overflow: hidden;/*包含浮动子元素*/
            resize:both;
        }
        .left {
            background-color: green;
            margin-right: 150px;
        }
        .right {
            float: right;
            width:150px;
            height:150px;
            background-color: blue;
        }
    </style>

</head>
<body>
<div id="wrapper">
    <div class="right">
        <img src="https://ss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=2096432854,4113309096&fm=26&gp=0.jpg"
             width="150" height="150" alt="Some of a team">
    </div>
    <div class="left">
        <p>
            这是左栏哦!这是左栏哦!这是左栏哦!这是左栏哦!这是左栏哦!
        </p>
    </div>
</div>
</body>
</html>

​

1.3.2 DOM结构right栏在下方

DOM结构:right在下方

写法:

  1. left外面加上一层div标签,父标签float:left,并且宽度100%
  2. 原始left设置margin-right为right栏的宽度
  3. right栏float:left,margin-left为自身宽度的负值

注意:由于二者都浮动了,需要让父元素包含浮动的子元素

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>两栏自适应布局:右侧固定,左侧自适应</title>
    <style type="text/css">
        * {margin:0;padding:0;}
        #wrapper{
            width:500px;
            background-color: yellow;
            overflow: hidden;/*包含浮动子元素*/
            resize:both;
        }
        .outerDiv {
            width:100%;
            float: left;
        }
        .left {
            background-color: green;
            margin-right: 150px;/*防止wrapper较小时右栏遮挡左栏内容*/
        }
        .right {
            float: left;
            width:150px;
            height:150px;
            background-color: blue;
            margin-left: -150px;/*将右栏向左拉*/
        }
    </style>

</head>
<body>
<div id="wrapper">
    <div class="outerDiv">
        <div class="left">
            这是左栏哦!这是左栏哦!这是左栏哦!这是左栏哦!这是左栏哦!
        </div>
    </div>
    <div class="right">
        <img src="https://ss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=2096432854,4113309096&fm=26&gp=0.jpg"
             width="150" height="150" alt="Some of a team">
    </div>
</div>
</body>
</html>

​

1.4 左右两侧都自适应(不理解?)

 左侧固定时,改变容器,右侧自适应;左侧改变且容器不变时,右侧自适应改变。

   思路:只将左侧元素浮动,另一侧元素采用display:table-cell(IE8+)或者display:inline-block(IE7)而实现跟随的效果。

   总结:

   元素1:float:left(不设置width)

   元素2:display:table-cell(IE8+)或者display:inline-block(IE7)

兼容IE浏览器的CSS属性写法:在属性前面添加*,例如

自适应宽度的一般不设置width。

2.三栏布局

三栏布局一般指的是左、右宽度固定,中间宽度自适应的布局

2.1 简单的浮动布局

DOM结构:left、right、middle,即middle最后渲染

写法:left:width+左浮动,right:width+右浮动,middle:不设置width,margin-left=左宽度,margin-right=右宽度

思路:利用了没有设置width的普通block元素,通过设置水平margin能够修改border box尺寸的特性

注意:让父元素包含浮动子元素,但是此处不加父元素也不会高度塌陷,因为middle是普通元素,但是还是加上最好。

类比:这个思路相当于结合了水平margin实现两栏自适应布局1.3.1和1.2.1的思路。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        *{margin:0;padding:0;}
        body {
            overflow: hidden;
        }
        .left {
            width:100px;
            height:300px;
            background-color: rgba(255,0,0,0.5);
            float: left;
        }
        .right {
            width: 200px;
            height:300px;
            background-color: rgba(0,0,255,0.5);
            float: right;
        }
        .middle {
            height:300px;
            margin:0 200px 0 100px;
            background-color: rgba(0,255,0,0.5);
        }
    </style>
</head>
<body>
    <div class="left"></div>
    <div class="right"></div>
    <div class="middle"></div>
</body>
</html>

2.2 绝对定位布局

DOM结构:无所谓,此处用left、middle、right吧,当然如果需求要求中间栏优先渲染,那么可以将middle放在最上面

写法:

  1. left和right分别绝对定位,这里相对于初始包含块的;
  2. middle不加定位,用margin-left和margin-right与左栏和右栏隔开,防止被遮挡

 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style type="text/css">
        * {margin:0;padding:0;}
        .left {
            position: absolute;
            left: 0;  width: 100px;
            top:0;height:300px;
            background-color: rgba(255,0,0,0.3);
        }
        .right {
            position: absolute;
            right:0;width:200px;
            top:0;height:300px;
            background-color: rgba(0,0,255,0.3);
        }
        .middle {
            height:300px;
            margin: 0 200px 0 100px;
            background-color: rgba(0,255,0,0.3);
        }
    </style>
</head>
<body>
    <div class="left"></div>
    <div class="middle"></div>
    <div class="right"></div>
</body>
</html>

         疑问,下面的代码中,wrapper为什么不能拉伸?大概原因是wrapper的层叠顺序低,但是,middle的背景色为什么会在wrapper的背景色之上呢,wrapper至少是absolute呀

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style type="text/css">
        * {margin:0;padding:0;}
        #wrapper {
            position: absolute;
            width:500px;
            height:300px;
            overflow: hidden;
            resize: both;
            background-color: yellow;
        }
        .left {
            position: absolute;
            left: 0;  width: 100px;
            top:0;bottom: 0;/*高度与包含块同高*/
            background-color: rgba(255,0,0,1);
        }
        .right {
            position: absolute;
            right:0;width:200px;
            top:0;bottom: 0;/*高度与包含块同高*/
            background-color: rgba(0,0,255,1);
        }
        .middle {
            height:200px;
            margin: 0 200px 0 100px;
            background-color: rgba(0,255,0,1);
        }
    </style>
</head>
<body>
    <div id="wrapper">
        <div class="left"></div>
        <div class="middle"></div>
        <div class="right"></div>
    </div>
</body>
</html>

2.3 圣杯布局

DOM结构:middle、left、right(左右两栏顺序无所谓,但是还是左栏在前好看一点)

思路:内容区本身与其padding是间隔的,那么可以将左栏和右栏放置在middle的水平padding区,那么就可以实现middle的内容区与左右栏分隔的效果。

写法:

  1. 三栏都float:left,左右栏设置宽度,middle栏的宽度设置为100%
  2. 将左栏拉到上一行,使得其左边缘与包含块左边缘对齐,即margin-left:-100%;这个百分比是相对于包含块的宽度的,包含块为离它最近的block、inline-block、table-cell的content box
  3. 将右栏拉到上一行,使得其右边缘与包含块右边缘对齐,即margin-left:自身宽度的负值。
  4. 上述左右栏移动以后会对中间栏造成遮挡,因此采用对包含块元素#box添加padding-left:左栏宽度、padding-right:右栏宽度,且左栏relative,向左移动自身宽度,右栏relative,向右移动自身宽度。

注意:

  1. 包含块为content box,所以relative以及相应的移动必不可少。
  2. 注意让父元素包含浮动的子元素。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style type="text/css">
        * {margin:0;padding:0;}
        #box {
            overflow: hidden;/*包含浮动子元素*/
            background-color: #8BD400;
            padding-left: 100px;
            padding-right: 200px;
        }
        .middle {
            float: left;
            height:300px;
            background-color: yellow;
            width: 100%;
        }
        .left{
            float: left;
            width: 100px;
            height:300px;
            background-color: red;
            margin-left: -100%;
            position: relative;
            left:-100px;/*相对其原来的位置,向左移动100px*/
        }
        .right{
            float: left;
            width:200px;
            height:300px;
            background-color: green;
            margin-left: -200px;
            position: relative;
            left:200px;/*相对其原来的位置,向右移动100px,right:-200px;效果一样*/
        }
    </style>
</head>
<body>
    <div id="box">
        <div class="middle"></div>
        <div class="left"></div>
        <div class="right"></div>
    </div>
</body>
</html>

疑问:如果DOM中没有#box,那么如果给body设置oveflow:hidden,并不会包含其中的三个浮动子元素,为什么?

2.4 双飞翼布局

DOM结构:middle外面嵌套div、left、right

写法:

  1. .outerDiv、left、right三者左浮动,.outerDiv宽度100%,left和right固定宽度
  2. .middle左右margin分别与左右栏宽度相等
  3. 左右栏通过margin-left换到上一行middle的margin的相应位置

类比:如果只看middle和right,那么与1.3.2中两栏自适应布局(右侧固定左侧自适应)的思路一样

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style type="text/css">
        * {margin:0;padding:0;}
        #box {
            overflow: hidden;/*包含浮动子元素*/
        }
        .outerDiv {
            float: left;
            width: 100%;
        }
        .middle {
            margin-left: 100px;  
            margin-right: 200px;/*与左右栏间隔*/
            height:300px;
            background-color: yellow;
        }
        .left {
            float: left;
            width: 100px;
            height:300px;
            background-color: red;
            margin-left: -100%;
        }
        .right {
            float: left;
            width:200px;
            height:300px;
            background-color: green;
            margin-left: -200px;
        }
    </style>
</head>
<body>
    <div id="box">
        <div class="outerDiv"><!--嵌套的div标签-->
            <div class="middle"></div>
        </div>
        <div class="left"></div>
        <div class="right"></div>
    </div>
</body>
</html>

2.5 圣杯布局和双飞翼布局的对比

    双飞翼布局比圣杯布局多用了一个div,但是少用了4个css属性(少用了左右栏的relative以及相应的偏移量)

2.6 其他可供参考的博客

https://cloud.tencent.com/developer/article/1351068

http://www.cnblogs.com/imwtr/p/4441741.html#top

https://www.jianshu.com/p/81ef7e7094e8 (讲了圣杯布局和双飞翼布局中,关于最小宽度的设置问题)

https://www.cnblogs.com/woodk/p/5147085.html(讲了圣杯布局和双飞翼布局的区别)

https://www.jianshu.com/p/2fe0e6953d0f(讲了圣杯布局和双飞翼布局的其他实现方法)

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值