CSS:经典布局

408 阅读11分钟

一、盒模型

1.1 概念

每个元素,都会形成一个矩形块,主要包括四部分:margin(外边距)+border(边框)+padding(内边距)+content(内容)

  1. W3C盒模型(标准盒子模型):width = content
  2. IE盒模型:width = border+padding+content

1.2 传统盒模型布局方式

  • display属性(文档流布局):按照文档的顺序依次显示,块元素独占一行,行内元素共享一行
  • float属性(浮动布局):使元素脱离文档流,浮动起来
  • position属性(定位布局):通过 position 属性来进行定位

二、定位

2.1 position

positionMDN文档)五个属性值:

  1. static(默认):元素框正常生成。块级元素生成一个矩形框,作为文档流的一部分;行内元素则会创建一个或多个行框,置于其父元素中。
  2. relative:元素框相对于之前正常文档流中的位置发生偏移,并且原先的位置仍然被占据。发生偏移的时候,可能会覆盖其他元素。
  3. absolute:元素框不再占有文档流位置,并且相对于包含块进行偏移(所谓的包含块就是最近一级外层元素position不为static的元素)
  4. fixed:元素框不再占有文档流位置,并且相对于视窗进行定位
  5. sticky:(这是css3新增的属性值)粘性定位,官方的介绍比较简单,或许你不能理解。其实,它就相当于relativefixed混合。最初会被当作是relative,相对于原来的位置进行偏移;一旦超过一定阈值之后,会被当成fixed定位,相对于视口进行定位。源码及演示

2.2 absolute和fixed区别

  1. absolute:它的偏移量是相对于最近一级position不是static的祖先元素的
  2. fixed:它的偏移量是相对于视口的。

三、尺寸

3.1 单位

  1. 百分比:百分比的参照物是父元素,50%相当于父元素width的50%
  2. rem:这个对于复杂的设计图相当有用,它是html的font-size的大小
  3. em:它虽然也是一个相对的单位,相对于父元素的font-size,但是,并不常用,主要是计算太麻烦了。

四、浮动

4.1 概念

设置浮动后的元素会形成BFC(使得内部的元素不会被外部所干扰),并且元素的宽度也不再自适应父元素宽度,而是适应自身内容。这样就可以,轻松地实现多栏布局的效果。

4.2 清除浮动

  1. overflow: 将父元素的overflow,设置成hidden
  2. after伪类:对子元素的after伪类进行设置
  3. 再加一个div,属性设为clear: both

五、居中

5.1 水平居中

  • 行内元素: 对父元素设置text-align: center
  • 定宽块状元素:
    1. 设置左右margin值为auto
    2. margin-top: -25px; margin-left: -50px;(负一半长宽)
  • 不定宽块状元素:
    1. 设置子元素为display: inline,然后在父元素上设置text-align: center
    2. transform: translate(-50%, -50%)
  • 通用方案: flex布局,对父元素设置display: flex; justify-content: center;

5.1.1 固定宽度

  1. magin: 0 auto
  2. margin-top: -25px; margin-left: -50px;
.container{
    width: 300px;
    height: 200px;
    background: pink;
    position: relative;
}
.inner{
    width: 100px;
    height: 50px;
    position: absolute;
    top: 50%;
    left: 50%;
    margin-top: -25px;
    margin-left: -50px;
    background: #fff;
    text-align: center;
}

5.1.2 未知宽度

  1. 将子元素设置为行内元素,然后父元素设置text-align: center
.container{
    width: 300px;
    height: 200px;
    position: relative;
    text-align: center;
}
.inner{
    display: inline-block;
}
  1. transform: translate(-50%, -50%);
.container{
    width: 300px;
    height: 200px;
    background: pink;
    position: relative;
}
.inner{
    width: 100px;
    height: 50px;
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    background: #fff;
    text-align: center;
}

5.1.3 多个块状元素

  1. 将子元素转换为行内块元素
.container{
  width: 250px;
  height: 200px;
  background: pink;
  position: relative;
  text-align: center;
  padding: 20px;
}
.inner{
  display: inline-block;
  width: 50px;
  height: 150px;
  background: #fff;
  text-align: center;
}
  1. 父元素使用弹性布局,主轴上的对齐方式设置为居中
.container{
  width: 250px;
  height: 200px;
  background: pink;
  display: flex;
  justify-content: center;
  padding: 20px;
}
.inner{
  background: #fff;
  width: 50px;
  height: 150px;
  margin-left: 10px;
}

5.2 垂直居中

  1. 父元素一定,子元素为单行内联文本: 设置父元素的height等于行高line-height
  2. 父元素一定,子元素为多行内联文本: 设置父元素的display:table-cellinline-block,再设置vertical-align:middle;
  3. 块状元素: 设置子元素position:fixed(absolute),然后设置margin:auto;
  4. 通用方案: flex布局,给父元素设置{display:flex; align-items:center;}

5.2.1 单行行内元素

子元素的行高等于高度

#container {
  height: 400px;
  background: pink;
}
#inner{
  display: inline-block;
  height: 200px;
  line-height: 200px;
}

5.2.2 多行行内元素

父元素的display: table-cellinline-block,再设置vertical-align: middle;

5.3 空间居中布局

空间居中布局指的是,不管容器的大小,项目总是占据中心点。

5.3.1 网格布局实现

//place-items: <align-items> <justify-items>;

.container {
    display: grid;
    place-items: center; // center center
}

5.3.2 弹性布局实现

父元素display: flex;,子元素margin: auto;

.father {
  width: 300px;
  height: 400px;
  background-color: blue;
  display: flex;
}

.son {
  width: 50px;
  height: 50px;
  background-color: burlywood;
  margin: auto;
}

六、经典布局

6.1 并列式布局

并列式布局就是多个项目并列。

6.1.1 弹性布局实现

.container {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
}

.item{
   flex: 0 1 150px;
   margin: 5px;
}

源码及效果展示

flex: <flex-grow> <flex-shrink> <flex-basis>;
  • flex-basis:项目的初始宽度。
  • flex-grow:指定如果有多余宽度,项目是否可以扩大。
  • flex-shrink:指定如果宽度不足,项目是否可以缩小。 flex: 0 1 150px;的意思就是,项目的初始宽度是150px,且不可以扩大,但是当容器宽度不足150px时,项目可以缩小。
    如果写成flex: 1 1 150px;,就表示项目始终会占满所有宽度。

6.2 两栏式布局

两栏式布局就是一个边栏(定宽),一个主栏(自适应)。边栏始终存在,主栏根据设备宽度,变宽或者变窄。

6.2.1 浮动布局实现


源码及效果展示

<div id="content">
  <div class="aside">aside</div>
  <div class="main">content</div>
</div>
<div id="footer">footer</div>

#content:after {
  content: "";
  display: block;
  clear: both;
}
.aside {
  float: left;
  width: 200px;
  height: 500px;
  background: yellow;
}
.main {
  height: 400px;
  margin-left: 210px;
  background: red;
}
#footer {
  background: #ccc;
}

6.2.2 网格布局实现

.container {
    display: grid;
    grid-template-columns: minmax(150px, 25%) 1fr;
    //第一列的宽度是minmax(150px, 25%),即最小宽度为150px,最大宽度为总宽度的25%;第二列为1fr,即所有剩余宽度。
}

源码及效果展示

6.3 三列布局

两侧两列固定宽度,中间列自适应宽度(auto)

6.3.1 使用float属性

使用左右两栏使用float属性,中间栏使用margin属性进行撑开,注意的是html的结果 源码及效果展示

<div id="content">
  <!-- 注意为什么不是 main 在前面 -->
  <div class="menu">aside</div>
  <div class="aside">aside</div>
  <div class="main">content</div>
</div>
<div id="footer">footer</div>

#content:after {
  content: "";
  display: block;
  clear: both;
}
.menu {
  float: left;
  width: 100px;
  height: 500px;
  background: pink;
}
.aside {
  float: right;
  width: 200px;
  height: 500px;
  background: yellow;
}
.main {
  height: 400px;
  margin-left: 110px; 
  
  /* 注意为什么要加 margin-left */

  margin-right: 210px;
  background: red;
}

#footer {
  background: #ccc;
}
  • 缺点:
  1. 当宽度小于左右两边宽度之和时,右侧栏会被挤下去;
  2. html的结构不正确

6.3.2 使用position定位

左右两栏使用position进行定位,中间栏使用margin进行定位

<div class="left">左栏</div>
<div class="middle">中间栏</div>
<div class="right">右栏</div>
.left{
    background: yellow;
    width: 200px;
    height: 300px;
    position: absolute;
    top: 0;
    left: 0;
}
.middle{
    height: 300px;
    margin: 0 220px;
    background: red;
}
.right{
    height: 300px;
    width: 200px;
    position: absolute;
    top: 0;
    right: 0;
    background: green;
}

缺点: 当父元素有内外边距时,会导致中间栏的位置出现偏差

6.3.3 flex布局

<div class="wrapper">
    <div class="left">左栏</div>
    <div class="middle">中间</div>
    <div class="right">右栏</div>
</div>
.wrapper{
    display: flex;
}
.left{
    width: 200px;
    height: 300px;
    background: green;
}
.middle{
    width: 100%;
    background: red;
    marign: 0 20px;
}
.right{
    width: 200px;
    height: 3000px;
    background: yellow;
}

6.4 三明治布局

页面在垂直方向上,分成三部分:页眉、内容区、页脚

6.4.1 网格布局实现

.container {
    display: grid;
    grid-template-rows: auto 1fr auto;
}

源码及效果展示

6.5 通栏

源码及效果展示

<div id="header">
  <div class="layout">头部</div>
</div>
<div id="content" class="layout">内容</div>
<div id="footer">
  <div class="layout">尾部</div>
</div>
.layout {
  width: 960px;
  margin: 0 auto;
}

body {
  min-width: 960px;
  /*
  ❗️❗️❗️对比加这个 min-width 和不加的区别,拉动屏幕大小,
  我们可以看见给 body 设置 min-width 可以去掉滚动背景色 bug。
   */

}

#header {
  height: 60px;
  background: red;
}
#content {
  height: 400px;
  background: blue;
}
#footer {
  height: 50px;
  background: yellow;
}

6.6 圣杯布局

将页面分成五个部分,除了页眉和页脚,内容区分成左边栏、主栏、右边栏。

6.6.1 浮动布局实现

1. 全部float:left

*{
  margin: 0;
  padding: 0;
}
.header,
.footer {
  height: 40px;
  width: 100%;
  background: red;
}

.footer {
  clear: both;
}

.container {
  padding-left: 200px;
  padding-right: 250px;
}

.container div {
  position: relative;
  float: left;
}

.middle {
  width: 100%;
  background: yellow;
}

.left {
  width: 200px;
  background: pink;
  margin-left: -100%;
  left: -200px;
}

.right {
  width: 250px;
  background: aqua;
  margin-left: -250px;
  left: 250px; 
}
<div class="header">这里是头部</div>
<div class="container">
  <div class="middle">中间部分</div>
  <div class="left">左边</div>
  <div class="right">右边</div>
</div>
<div class="footer">这里是底部</div>

2. 左边float: left, 右边float: right

*{
  margin: 0;
  padding: 0;
}
.header,
.footer {
  height: 40px;
  width: 100%;
  background: red;
}
.container{
  overflow: hidden;
}

.middle {
  background: yellow;
}

.left {
  float: left;
  width: 200px;
  background: pink;
}

.right {
  float: right;
  width: 250px;
  background: aqua;
}
<div class="header">这里是头部</div>
<div class="container">
  <div class="left">左边</div>
  <div class="right">右边</div>
  <div class="middle">中间部分</div>
</div>
<div class="footer">这里是底部</div>

6.6.2 flex布局实现

*{
  margin: 0;
  padding: 0;
}
.header,.footer{
    height:40px;
    width:100%;
    background:red;
}
.container{
    display: flex;
}
.middle{
    flex: 1;
    background:yellow;
}
.left{
    width:200px;
    background:pink;
}
.right{
    background: aqua;
    width:300px;
}
<div class="header">这里是头部</div>
<div class="container">
    <div class="left">左边</div>
    <div class="middle">中间部分</div>
    <div class="right">右边</div>
</div>
<div class="footer">这里是底部</div>

6.6.3 网格布局实现

<div class="container">
    <header/>
    <div/>
    <main/>
    <div/>
    <footer/>
</div>

.container {
    display: grid;
    grid-template: auto 1fr auto / auto 1fr auto;
}

源码及效果展示

6.6.4 绝对定位

*{
  margin: 0;
  padding: 0;
}
.header,
.footer {
  height: 40px;
  width: 100%;
  background: red;
}
.container{
  min-height: 1.2em;
  position: relative;
}

.container>div {
  position: absolute;
}

.middle {
  left: 200px;
  right: 250px;
  background: yellow;
}

.left {
  left: 0;
  width: 200px;
  background: pink;
}

.right {
  right: 0;
  width: 250px;
  background: aqua;
}
<div class="header">这里是头部</div>
<div class="container">
  <div class="left">左边</div>
  <div class="right">右边</div>
  <div class="middle">中间部分</div>
</div>
<div class="footer">这里是底部</div>

6.7 双飞翼布局

6.7.1 浮动布局实现

<div class="container">
  <div class="middle">测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试</div>
  <div class="left">left</div>
  <div class="right">right</div>
</div>
.container{
}
.container:after{
    content: '';
    display: block;
    clear: both;
}
.middle{
    box-sizing: border-box; //这个未加,布局便不成立
    width: 100%;
    padding: 0 200px;
    background: paleturquoise;
    height: 200px;
    float: left;
}
.left{
    background: palevioletred;
    width: 200px;
    height: 200px;
    float: left;
    font-size: 40px;
    color: #fff;
    margin-left:-100%;
}
.right{
    width: 200px;
    height: 200px;
    background: purple;
    font-size: 40px;
    float: left;
    color: #fff;
    margin-left:-200px;
}

七、移动端

媒体查询的css标识符@media,它的媒体类型可以分为:

  1. all:所有媒体
  2. braille:盲文触觉设备
  3. embossed:盲文打印机
  4. print:手持设备
  5. projection:打印预览
  6. screen:彩屏设备
  7. speech:‘听觉’类似的媒体类型
  8. tty:不适用像素的设备
  9. tv:电视

代码及示例

//手机端的尺寸在750px,而PC端则是大于750px的
//屏幕宽度小于750px,显示红色;反之,绿色
@media screen and (min-width: 750px){
  .media{
    height: 100px;
    background: red;
  }
}

@media (max-width: 750px){
  .media{
    height: 200px;
    background: green;
  }
}

各个分辨率范围在html上设置font-size

html{font-size:10px}
@media screen and (min-width:321px) and (max-width:375px){html{font-size:11px}}
@media screen and (min-width:376px) and (max-width:414px){html{font-size:12px}}
@media screen and (min-width:415px) and (max-width:639px){html{font-size:15px}}
@media screen and (min-width:640px) and (max-width:719px){html{font-size:20px}}
@media screen and (min-width:720px) and (max-width:749px){html{font-size:22.5px}}
@media screen and (min-width:750px) and (max-width:799px){html{font-size:23.5px}}
@media screen and (min-width:800px){html{font-size:25px}}

八、注意事项

8.1 行内元素排版


元素被当成行内元素排版的时候,元素之间的空白符(空格、回车换行等)都会被浏览器处理,根据CSS中white-space属性的处理方式(默认是normal,合并多余空白),原来HTML代码中的回车换行被转成一个空白符,在字体不为0的情况下,空白符占据一定宽度,所以inline-block的元素之间就出现了空隙

  1. 将子元素标签的结束符和下一个标签的开始符写在同一行或把所有子标签写在同一行
  2. 父元素中设置font-size: 0,在子元素上重置正确的font-size

参考文章

  1. 只要一行代码,实现五种 CSS 经典布局
  2. 把“可以动的盒子”更优雅地展示:③ 常用的“布局” | CSS
  3. CSS布局说——可能是最全的(zimo)
  4. 从网易与淘宝的font-size思考前端设计稿与工作流(流云诸葛)
  5. CSS 常见布局方式(很全面)
  6. 剖析一些经典的CSS布局问题,为前端开发+面试保驾护航

待看

  1. 【原】移动web资源整理