css布局之圣杯布局和双飞翼布局

1. 圣杯布局

  1. 我对header和footer没有设置宽度
  2. 对left 和right 有设置固定宽度
  3. 对left,right 和 middle 有设置高度
  4. 对middle 宽度设置为100%
  5. 使用定位和margin值将left 和 right 元素进行布局
    圣杯布局
    代码上附有步骤:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style> *{padding:0;margin: 0;} header{ background-color: darkcyan; height: 50px; } .container{ background-color:cyan; overflow: hidden; /*4. 因为文字会被left元素挡住,所以使用padding将内容显示出来,同时需要知道left的宽度*/ padding-left:200px; padding-right: 300px; } .middle,.left, .right{ float: left; /* 1. 三者都设置为float left,且三者都有高度*/ height: 500px; /*5. 此时left也会跟着回来,所以使用相对定位*/ position: relative; word-wrap: break-word;/*解决文字换行*/ } .middle{ background-color: palevioletred; width: 100%; /* 2. middle 宽度使用100% */ } .left{ width: 200px; background-color: tomato; margin-left: -100%; /*3. 使用margin-left: -100% 将left元素拉回来*/ /*5.1 对left进行设置*/ left: -200px; } .right{ background-color: purple; width: 300px; /*5.2 将right盒子拉回*/ margin-left: -300px; right: -300px; } footer{ background-color: yellowgreen; height: 60px; } </style>
</head>
<body>
    <header>
        <h4>header</h4>
    </header>
    <div class="container">
        <div class="middle">
            <h4>middle</h4>
            <p>mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm</p>
        </div>
        <div class="left">
            <h4>left</h4>
            <p>llllllllllllllllllllllllllllllllllll</p>
        </div>
        <div class="right">
            <h4>right</h4>
            <p>rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr</p>
        </div>
    </div>
    <footer>
        <h4>footer</h4>
        <p>pppppppppppppppppp</p>
    </footer>
</body>
</html>

2. 双飞翼布局

注意:从图片上看感觉布局一样
但还是要看代码哟,双飞翼布局没有使用position,而且container只包括了middle元素哦

  1. 设置了四个高度,分别是left right container,middle
  2. 对container设置了100%,使用margin 将left 和right 拉回来
  3. 对middle 进行设置,使用margin 为left和right 进行留白
  4. 底部使用clear:both 清除浮动
    双飞翼
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>双飞翼布局</title>
    <style> * { padding: 0; margin: 0; text-align: center; word-wrap: break-word; } header { background-color: darkcyan; height: 50px; } .container { width: 100%;/*2. width:100%*/ } .container,.left,.right{ float: left;/*1.float*/ height: 500px; } .middle { background-color: palevioletred; margin-left: 300px;/*4.使用margin 将左右两边留白*/ margin-right: 200px; height: 500px; } .left { background-color: tomato; width: 300px; margin-left: -100%; /*3.1 将left拉回来*/ } .right { background-color: purple; width: 200px; margin-left: -200px; /*3.2 将right拉回来*/ } footer { background-color: yellowgreen; height: 60px; clear: both;/*5.使底部恢复 clear 属性规定元素的哪一侧不允许其他浮动元素。*/ } </style>
</head>
<body>
    <header>
        <h4>header</h4>
    </header>
    <div class="container">
        <div class="middle">
            <h4>middle</h4>
            <p>mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm</p>
        </div>
    </div>

    <div class="left">
        <h4>left</h4>
        <p>llllllllllllllllllllllllllllllllllll</p>
    </div>
    <div class="right">
        <h4>right</h4>
        <p>rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr</p>
    </div>

    <footer>
        <h4>footer</h4>
        <p>pppppppppppppppppp</p>
    </footer>
</body>
</html>

3. flex弹性盒布局

  1. 设置了left middle right 的高度
  2. 设置了left 和 right 的宽度
  3. 对left middle right 的父级元素container设置display:flex后就会自动这样
    弹性盒布局
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>flex弹性布局</title>
    <style> * { padding: 0; margin: 0; text-align: center; } header { background-color: darkcyan; height: 50px; } .container { background-color: cyan; display: flex; } .middle, .left, .right { height: 500px; word-wrap: break-word; /*解决文字换行*/ } .middle { background-color: palevioletred; } .left { width: 200px; } .right { background-color: purple; } footer { background-color: yellowgreen; height: 60px; } </style>
</head>
<body>
    <header>
        <h4>header</h4>
    </header>
    <div class="container">
        <div class="left">
            <h4>left</h4>
            <p>llllllllllllllllllllllllllllllllllll</p>
        </div>
        <div class="middle">
            <h4>middle</h4>
            <p>mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm</p>
        </div>
        <div class="right">
            <h4>right</h4>
            <p>rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr</p>
        </div>
    </div>
    <footer>
        <h4>footer</h4>
        <p>pppppppppppppppppp</p>
    </footer>
</body>
</html>

注意:
我发现虽然设置了left 和 right 的宽度 但是随着,middle 里内容的文字增加,right的宽度会变化


我对上面的代码进行了修改,如下

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>flex弹性布局</title>
    <style> * { padding: 0; margin: 0; text-align: center; word-wrap: break-word; } header { background-color: darkcyan; height: 50px; } .container { background-color: cyan; display: flex;/*1.设置flex属性*/ } .middle, .left, .right { height: 500px; word-wrap: break-word; /*解决文字换行*/ } .middle { background-color: palevioletred; flex-grow: 1; } .left { order: -1; /*2.设置布局,定义项目的排列顺序,越小越靠前,默认为0*/ flex-basis:200px; } .right { background-color: purple; flex-basis:300px; } footer { background-color: yellowgreen; height: 60px; } </style>
</head>
<body>
    <header>
        <h4>header</h4>
    </header>
    <div class="container">
        <div class="middle">
            <h4>middle</h4>
            <p>mmmmmmmmmmmmmmmmmmmmmmmmm</p>
        </div>
        <div class="left">
            <h4>left</h4>
            <p>lllllllllllllllllllllllll</p>
        </div>
        <div class="right">
            <h4>right</h4>
            <p>rrrrrrrrrrrrrrrrrrrr</p>
        </div>
    </div>
    <footer>
        <h4>footer</h4>
        <p>pppppppppppppppppp</p>
    </footer>
</body>
</html>

加入了flex-grow:使其剩下的填满
flex-basis:设置规定值
得到了下面的布局
flex
但是还是会随着每个内容的长度进行比例切换
比如当m增加时,会这样,对于left 和right里内容也是这样
在这里插入图片描述
我又重新查了一下flex的属性

display:flex;如果一个容器设置了这个属性,则这个盒子里的所有子元素都会变成伸缩项

阮一峰大神 flex 布局实例

  • justify-content 设置子元素的排列方式 flex-start,flex-end,center
    • space-between
  • sapce-between 左右对齐父容器的开始和结束,中间平均分布,产生相同的间距
  • sapce-around 将多余的空间平均分布在每一个子元素的两边(主轴上的)中间的减减压是左右两边的两倍
  • flex-wrap 控制子元素是否换行 nwrap 不换行 wrap 换行
  • flex-direction:元素排列方向,主轴方向默认为row(水平方向)
    • row 水平方向–主轴 垂直方向 —侧轴 默认row-reverse
    • column 垂直方向–主轴 水平方向为–侧轴 column-reverse从上到下
  • flex-flow 由flex-wrap 和 flex-direction 组成
  • flex-grow 扩展了子元素的宽度,设置当前元素应该占据剩余空间的比例值(默认为0)
  • flex-shrink 定义收缩比例,通过设置的值来计算收缩空间(默认为1)
    • 比例值计算:flex-grow/所有兄弟的flex-grow的和
  • flex:用来设置当前伸缩子项占据剩余空间的比例值
  • align-item 设置子元素(伸缩项)在侧轴上的对齐方式
    • center 侧轴上居中对齐
    • stretch 侧轴方向上进行拉伸,填充满整个侧轴方向(默认值)
    • baseline 基线对齐
  • align-self:设置单个元素在侧轴方向上的对齐方式

.box {
  display: flex;
  justify-content: center;
  align-items: flex-end;
}

在这里插入图片描述
使用sapce-between

.box {
  display: flex;
  justify-content: space-between;
}

在这里插入图片描述

.box {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
}

在这里插入图片描述
align-self

.box {
  display: flex;
}

.item:nth-child(2) {
  align-self: center;
}

在这里插入图片描述

4. 使用flex做的圣杯布局(by 阮一峰)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style> .HolyGrail { display: flex; min-height: 100vh; flex-direction: column; } header, footer { flex: 1; background-color: darkcyan; } .HolyGrail-body { display: flex; flex: 1; background-color: blueviolet; } .HolyGrail-content { flex: 1; background-color: red; } .HolyGrail-nav, .HolyGrail-ads { /* 两个边栏的宽度设为12em */ flex: 0 0 12em; background-color: yellow; } .HolyGrail-nav { /* 导航放到最左边 */ order: -1; } </style>
</head>
<body class="HolyGrail">
    <header>...</header>
    <div class="HolyGrail-body">
      <main class="HolyGrail-content">cccccccccccccccccccccccccccccccccccccccccccccccccccccccccc</main>
      <nav class="HolyGrail-nav">lllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllll</nav>
      <aside class="HolyGrail-ads">...</aside>
    </div>
    <footer>...</footer>
  </body>
</html>

在这里插入图片描述
我在对body中加入了文字换行,但是结果布局的左边还是会被内容撑到变形
在这里插入图片描述