页面布局之圣杯布局和双飞翼布局

关于marin负值

提到这两种布局,离不开margin负值,我们首先了解一下margin负值;
1、当元素不存在width属性或width:auto时,负margin会增加元素宽度


<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>margin负值问题title>
    <style type="text/css">
        .container{
            width:500px;
            height:150px;
            margin:0 auto;
            border:3px solid #ccc;
        }
        .main{
            height:100px;
            margin-left:-20px;/*左边增加宽度20px*/
            background:pink;
        }
    style>
head>
<body>
    <div class="container">
        <div class="main">
            我没有宽度
        div>
    div>
body>
html>

页面布局之圣杯布局和双飞翼布局_第1张图片
由上图可以看出,粉色背景的main的宽度左边增加了;这就是margin-left的负值增加的宽度。
2、margin-top为负值不会增加高度,但是会产生向上位移


<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>margin负值问题title>
    <style type="text/css">
        .container{
            position:absolute;
            top:200px;
            width:500px;
            height:100px;
            border:3px solid #ccc;
        }
        .main{
            height:100px;
            margin-top:-20px;/*不会增加高度,会产生向上的位移20px*/
            background:pink;
        }
    style>
head>
<body>
    <div class="container">
        <div class="main">
            我没有增加高度,我只是向上移动了
        div>
    div>
body>
html>

页面布局之圣杯布局和双飞翼布局_第2张图片
3、margin-bottom为负值不会产生位移,会减少自身的高度
这里存在小问题,等弄明白了再来更新。

4、margin负值对文档流的影响
对元素设置margin-left:-20px;其自身会向左偏移20px,但是没有脱离文档流,其后的元素会跟着移动,看下面的两组对比图,可以明显看出每组的第二张图片粉色的地方都有移动,其后的元素跟着它移动;所以,在不脱离文档流不使用float的情况下,负margin元素是不会破坏页面的文档流。
页面布局之圣杯布局和双飞翼布局_第3张图片
页面布局之圣杯布局和双飞翼布局_第4张图片

页面布局之圣杯布局和双飞翼布局_第5张图片
页面布局之圣杯布局和双飞翼布局_第6张图片

5、margin负值对浮动的影响
这里可以参考https://www.jianshu.com/p/549aaa5fabaa 这篇博客,写的特别清晰,我也是看这个看明白的。
首先,我们有三个盒子,让这三个盒子全部float:left;它们会在一排显示


<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>margin负值问题title>
    <style type="text/css">
        .container{
            width:500px;
            height:100px;
            margin:0 auto;
            border:3px solid #000;
        }
        .fl{
            width:100px;
            height:100px;
            float:left; /*全部左浮动*/
        }
        .one{
            background: rgba(233,123,11,0.8);
        }
        .two{
            background: rgba(150,123,100,0.8);
        }
        .three{
            background: rgba(10,255,100,0.8);
        }

    style>
head>
<body>
    <div class="container">
        <div class="one fl">第一个盒子div>
        <div class="two fl">第二个盒子div>
        <div class="three fl">第三个盒子div>
    div>
body>
html>

页面布局之圣杯布局和双飞翼布局_第7张图片

1、第一个例子,给第二个盒子和第三个盒子添加margin-left:-25px;

这里写代码片
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>margin负值问题title>
    <style type="text/css">
        *{
            padding:0;
            margin:0;
        }
        .container{
            width:500px;
            height:100px;
            margin:0 auto;
            border:3px solid #000;
        }
        .fl{
            width:100px;
            height:100px;
            float:left;
        }
        .one{
            background: rgba(233,123,11,0.8);
        }
        .two{
            background: rgba(150,123,100,0.8);
            margin-left:-25px;/*添加margin负值*/
        }
        .three{
            background: rgba(10,255,100,0.8);
            margin-left:-25px;/*添加margin负值*/
        }

    style>
head>
<body>
    <div class="container">
        <div class="one fl">第一个盒子div>
        <div class="two fl">第二个盒子div>
        <div class="three fl">第三个盒子div>
    div>
body>
html>

移动过程可以分解成以下的三图
没有添加margin负值的原图
页面布局之圣杯布局和双飞翼布局_第8张图片
给第二个盒子和第三个盒子添加margin-left:-25px;
首先,第二个盒子先向左移动25px,第三个盒子紧随其后:
页面布局之圣杯布局和双飞翼布局_第9张图片
其次,第三个盒子也有margin负值,所以它再次向左移动25px,形成最终渲染在浏览器上的样式;此时的三个盒子的“宽度”(在浏览器显示且不被覆盖的宽度)分别是75px,75px,100px;
页面布局之圣杯布局和双飞翼布局_第10张图片
若是三个盒子同时添加margin-left(即第一个盒子也添加),那么这三个盒子的“宽度”(在浏览器显示且不被覆盖的宽度)分别是50px,75px,100px;
页面布局之圣杯布局和双飞翼布局_第11张图片

2、第二个例子,给第二个盒子和第三个盒子添加margin-left:-50px;
这里同上面流程,第二个盒子先向左移动50px,第三个和紧随其后,然后第三个盒子再向左移动50px;
页面布局之圣杯布局和双飞翼布局_第12张图片
3、第三个例子,给第三个盒子添加margin-left:-200px;
第三个向左移动200px,第一个盒子完全被第三个盒子覆盖,呈现以下效果:
页面布局之圣杯布局和双飞翼布局_第13张图片
总结:负margin会改变浮动元素的显示位置,即使我的元素写在DOM的后面,我也能让它显示在最前面。圣杯布局、双飞翼布局都是利用这个原理实现的。
6、margin负值对绝对定位的影响
对于绝对定位元素,负margin会基于其绝对定位坐标再偏移,这个可以应用在元素垂直水平居中上:

.box{
    width:100px;
    height:100px;
    position:absolute;
    top:50%;
    left:50%;
    margin-left:-50px; /*要居中元素宽度的一半*/
    margin-top:-50px; /*要居中元素高度的一半*/
    background: pink;
}

页面布局之圣杯布局和双飞翼布局_第14张图片
缺点:必须知道需居中定位元素的高度和宽度。
7、margin负值可以用来去除列表的右边框
要实现下图布局,即两边对齐,中间均匀分布,可以只用margin负值增加宽度的作用,使用margin-right:-10px;增加10px的宽度;
页面布局之圣杯布局和双飞翼布局_第15张图片
实现代码如下:


<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>margin负值title>
    <style type="text/css">
        ul,li{ /*清除初始化样式*/
            padding:0;
            margin:0;
            list-style:none
        }
        .container{
            width:500px;
            margin:0 auto;
            border:1px solid #ccc;
        }
        .list{
            overflow: hidden;
            margin-right:-10px;/*宽度增加10px*/
        }
        .list li{
            width:92px;
            height:92px;
            float:left;
            background: pink;
            margin-right:10px;
            margin-bottom:10px;
        }
    style>
head>
<body>
    <div class="container">
        <ul class="list">
            <li>我是一个列表li>
            <li>我是一个列表li>
            <li>我是一个列表li>
            <li>我是一个列表li>
            <li>我是一个列表li>
            <li>我是一个列表li>
            <li>我是一个列表li>
            <li>我是一个列表li>
            <li>我是一个列表li>
            <li>我是一个列表li>
        ul>
    div>
body>
html>

也可以使用flex实现这一布局。
8、去除列表最后一个li元素的border-bottom
很多情况下,我们会用li标签来模拟表格,再给li标签添加下边距的时候,最后一个li标签表格会和父元素的边框靠在一起,会显得整个“table”的底部边框会比其他的边粗一些!
页面布局之圣杯布局和双飞翼布局_第16张图片
利用margin-bottom负值,解决这个问题
页面布局之圣杯布局和双飞翼布局_第17张图片
代码如下:


<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Documenttitle>
    <style type="text/css">
        ul,li{
            padding:0;
            margin:0;
            list-style: none;
        }
        ul.list{
            width:200px;
            margin:0 auto;
            border:1px solid #ccc;

        }
        li{
            border-bottom:1px solid #ccc;
            margin-bottom:-1px;/*margin负值*/
        }
    style>
head>
<body>
    <ul class="list">
        <li>我是li标签li>
        <li>我是li标签li>
        <li>我是li标签li>
        <li>我是li标签li>
        <li>我是li标签li>
    ul>
body>
html>

接下来我们来看一下圣杯布局:

圣杯布局

主要过程参考博客 https://www.jianshu.com/p/f9bcddb0e8b4
两边固宽,中间自适应
但是中间部分先渲染,即html结构是这样的

<div class="container">
    <div class="main">我是中间自适应div>
    <div class="left">我是左边,我有固定宽度div>
    <div class="right">我是右边,我有固定宽度div>
div>

实现代码如下:


<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>圣杯模型title>
    <style type="text/css">
        .container{
            padding:0 200px;/*给父容器设置左右padding为200px,这是左右盒子的宽度*/
        }
        .main, .left, .right{
            min-height: 100px;
            float:left; /*全部向左浮动*/
        }
        .main{
            background: #ccc;
            width:100%;
        }
        .left{
            position:relative;
            width:200px;
            margin-left:-100%; /*为了让左盒子移到最左边*/
            left:-200px; /*为了不覆盖中间部分*/
            background: red;
        }
        .right{
            position:relative;
            width:200px;
            margin-left:-200px;/*为了让右盒子移到最右边*/
            right:-200px; /*为了不覆盖中间部分*/
            background:yellow;
        }
    style>
head>
<body>
    <div class="container">
        <div class="main">我是中间自适应部分我是中间自适应部分我是中间自适应部分我是中间自适应部分我是中间自适应部分我是中间自适应部分我是中间自适应部分我是中间自适应部分我是中间自适应部分div>
        <div class="left">我是左边,我有固定宽度div>
        <div class="right">我是右边,我有固定宽度div>
    div>
body>
html>

实现效果,中间自适应部分安全显示,左右盒子也正确显示在自己的位置上。
页面布局之圣杯布局和双飞翼布局_第18张图片

双飞翼布局

参考链接 https://blog.csdn.net/wangchengiii/article/details/77926868
圣杯布局和双飞翼布局解决问题的方案在前一半是相同的,也就是三栏全部float浮动,但左右两栏加上负margin让其跟中间栏div并排,以形成三栏布局。
不同在于解决 “中间栏div内容不被遮挡”问题的思路不一样。
它的html结构如下:

<div class="container">
    <div class="main">
        <div class="content">
            我是中间自适应部分
        div>
    div>
    <div class="left">我是左边,我有固定宽度div>
    <div class="right">我是右边,我有固定宽度div>
div>

代码实现如下:


<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>圣杯模型title>
    <style type="text/css">
        .main, .left, .right{
            min-height: 100px;
            float:left;
        }
        .main{
            background: #ccc;
            width:100%;
        }
        .content{
            margin:0 200px; /*给里层的content设置margin或者padding*/
        }
        .left{
            position:relative;
            width:200px;
            margin-left:-100%;/*这里只需要margin负值*/
            background: red;
        }
        .right{
            position:relative;
            width:200px;
            margin-left:-200px;/*这里只需要margin负值*/
            background:yellow;
        }
    style>
head>
<body>
    <div class="container">
        <div class="main">
            <div class="content">我是中间自适应部分我是中间自适应部分我是中间自适应部分我是中间自适应部分我是中间自适应部分我是中间自适应部分我是中间自适应部分我是中间自适应部分我是中间自适应部分
            div>
        div>
        <div class="left">我是左边,我有固定宽度div>
        <div class="right">我是右边,我有固定宽度div>
    div>
body>
html>

双飞翼布局比圣杯布局多使用了1个div,少用大致4个css属性(圣杯布局container的 padding-left和padding-right这2个属性,加上左右两个div用相对布局position: relative及对应的right和left共4个属性,;而双飞翼布局子div里用margin-left和margin-right共2个属性,比圣杯布局思路更直接和简洁一点。
简单说起来就是:双飞翼布局比圣杯布局多创建了一个div,但不用相对布局了。

你可能感兴趣的:(css,前端)