1. 程式人生 > >頁面佈局之聖盃佈局和雙飛翼佈局

頁面佈局之聖盃佈局和雙飛翼佈局

關於marin負值

提到這兩種佈局,離不開margin負值,我們首先了解一下margin負值;
1、當元素不存在width屬性或width:auto時,負margin會增加元素寬度

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>margin負值問題</title>
    <style type="text/css">
        .container{
            width:500
px
; 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>

這裡寫圖片描述
由上圖可以看出,粉色背景的main的寬度左邊增加了;這就是margin-left的負值增加的寬度。
2、margin-top為負值不會增加高度,但是會產生向上位移

<!DOCTYPE html>
<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>

這裡寫圖片描述
3、margin-bottom為負值不會產生位移,會減少自身的高度
這裡存在小問題,等弄明白了再來更新。

4、margin負值對文件流的影響
對元素設定margin-left:-20px;其自身會向左偏移20px,但是沒有脫離文件流,其後的元素會跟著移動,看下面的兩組對比圖,可以明顯看出每組的第二張圖片粉色的地方都有移動,其後的元素跟著它移動;所以,在不脫離文件流不使用float的情況下,負margin元素是不會破壞頁面的文件流。
未移動元素
這裡寫圖片描述

這裡寫圖片描述
這裡寫圖片描述

5、margin負值對浮動的影響
這裡可以參考https://www.jianshu.com/p/549aaa5fabaa 這篇部落格,寫的特別清晰,我也是看這個看明白的。
首先,我們有三個盒子,讓這三個盒子全部float:left;它們會在一排顯示

<!DOCTYPE html>
<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>

這裡寫圖片描述

1、第一個例子,給第二個盒子和第三個盒子新增margin-left:-25px;

這裡寫程式碼片<!DOCTYPE html>
<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負值的原圖
這裡寫圖片描述
給第二個盒子和第三個盒子新增margin-left:-25px;
首先,第二個盒子先向左移動25px,第三個盒子緊隨其後:
這裡寫圖片描述
其次,第三個盒子也有margin負值,所以它再次向左移動25px,形成最終渲染在瀏覽器上的樣式;此時的三個盒子的“寬度”(在瀏覽器顯示且不被覆蓋的寬度)分別是75px,75px,100px;
這裡寫圖片描述
若是三個盒子同時新增margin-left(即第一個盒子也新增),那麼這三個盒子的“寬度”(在瀏覽器顯示且不被覆蓋的寬度)分別是50px,75px,100px;
這裡寫圖片描述

2、第二個例子,給第二個盒子和第三個盒子新增margin-left:-50px;
這裡同上面流程,第二個盒子先向左移動50px,第三個和緊隨其後,然後第三個盒子再向左移動50px;
這裡寫圖片描述
3、第三個例子,給第三個盒子新增margin-left:-200px;
第三個向左移動200px,第一個盒子完全被第三個盒子覆蓋,呈現以下效果:
這裡寫圖片描述
總結:負margin會改變浮動元素的顯示位置,即使我的元素寫在DOM的後面,我也能讓它顯示在最前面。聖盃佈局、雙飛翼佈局都是利用這個原理實現的。
6、margin負值對絕對定位的影響
對於絕對定位元素,負margin會基於其絕對定位座標再偏移,這個可以應用在元素垂直水平居中上:

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

這裡寫圖片描述
缺點:必須知道需居中定位元素的高度和寬度。
7、margin負值可以用來去除列表的右邊框
要實現下圖佈局,即兩邊對齊,中間均勻分佈,可以只用margin負值增加寬度的作用,使用margin-right:-10px;增加10px的寬度;
這裡寫圖片描述
實現程式碼如下:

<!DOCTYPE html>
<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”的底部邊框會比其他的邊粗一些!
這裡寫圖片描述
利用margin-bottom負值,解決這個問題
這裡寫圖片描述
程式碼如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <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>

接下來我們來看一下聖盃佈局:

聖盃佈局

<div class="container">
    <div class="main">我是中間自適應</div>
    <div class="left">我是左邊,我有固定寬度</div>
    <div class="right">我是右邊,我有固定寬度</div>
</div>

實現程式碼如下:

<!DOCTYPE html>
<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>

實現效果,中間自適應部分安全顯示,左右盒子也正確顯示在自己的位置上。
這裡寫圖片描述

雙飛翼佈局

參考連結 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>

程式碼實現如下:

<!DOCTYPE html>
<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,但不用相對佈局了。