# 多终端响应式项目开发最佳实践

TIP

本节课,我们一起来学习响应式布局,首先我们需要了解什么是响应式布局。

什么是响应式布局 ?

响应式布局是一种网页设计方法,使网页能够自动适应不同设备(桌面电脑,平板,手机等)的屏幕尺寸,提供最佳的浏览体验。

我们前面学习的流体布局、 rem 布局 、 vw 布局 ,是专门用来实现移动端网页开发的。它们开发出来的网站在屏幕尺寸(320 ~ 480px)之间上显示,才能获得好的体验。 并不能适应 iPadPC 端

如果我们想只开发一套代码,且要求写出来网页能同时适应不同设备的屏幕尺寸,就必须用我们今天讲到响应式布局来实现。

接下来,我们会从以下几个方面来展开讲解响应式相关内容

  • 媒体查询的语法
  • 响应式断点和书写位置
  • 媒体查询的两种适配方案
  • 响应式栅格系统
  • 响应式后台管理系统项目开发

# 一、媒体查询的语法

TIP

响应式设计的核心 就是通过 媒体查询 来检测屏幕视口宽,针对不同视口宽做相应 CSS 处理,来展现不同布局 和 内容。所以媒体查询是响应式设计的核心内容。

关于媒体查询,我们需要学习那些内容:

  • 什么是媒体查询
  • 媒体类型
  • 媒体特性
  • 逻辑运算符

# 1、什么是媒体查询

TIP

  • 我们知道,一套 CSS 样式是很难适应不同大小的屏幕,所以我们需要针对不同的屏幕尺寸来书写不同的样式,这样我们写出来的页面就能在不同大小的屏幕上都正常显示。
  • 媒体查询就是用来解决这个问题的,他能帮助我们检测不同屏幕的尺寸,然后针对不同屏幕尺寸,显示不同的样式。

我们来看一个简单的媒体查询代码:

<style>
  /*
        @media 是关键字:媒体查询
        screen 媒体类型:屏幕设备
        and 逻辑运算符:与 (多个条件同时满足)
        min-width 媒体特性:设备宽>=800px
        以下整个媒体查询代码的含义:网页是在屏幕设备上显示,同时屏幕设备的宽>=800px时,背景颜色变为红色。
    */
  @media screen and (min-width: 800px) {
    body {
      background-color: red;
    }
  }
</style>

一个完整的媒体查询语句,包含以下四个部分:

  • @media 关键字
  • 媒体类型
  • 逻辑运算符
  • 媒体特性
@media 媒体类型 逻辑操作符 (媒体特性) {
  ...css样式....;
}

接下来我将针对以上 4 个部分,分别做详细的讲解

# 2、媒体类型

TIP

媒体类型(Media types) 就是用来描述 设备的一般类别,设备类别主要分为以下 4 种

媒体类型 说明
all (默认值)适用于所有的设备
screen 适用于屏幕设备(如电脑、手机、电视机等)
print 适用于在打印预览模式下在屏幕上查看的分页材料和文档
speech 适用于语音合成器

如果媒体查询语句,只指定媒体类型,可以简写成如下:

@media 媒体类型 { .... css样式..... };

案例演示

  • all 是默认值,在媒体类型不写的情况下,默认就是 all,适用于所有设备
@media {
  body {
    background-color: red;
  }
}

/* 上面代码等同于下面写法,但实际开发中,不会省略简写,如果是all还是加上最安全 */
@media all {
  body {
    background-color: red;
  }
}
  • screen 适用于屏幕设备
/* 在屏幕设备下,背景色为红色 */
@media screen {
  body {
    background-color: red;
  }
}
  • print 适用于打印预览模式
<style>
  /* 正常情况下应用的 css样式 */
  body {
    background-color: skyblue;
    color: red;
    font-size: 20px;
  }
  /* 在打印模式下应用的 css样式*/
  @media print {
    body {
      background-color: red;
      color: yellow;
      font-size: 50px;
    }
  }
</style>
<body>
  我就是我不一样的花朵
</body>
正常模式下预览效果 打印模式下预览效果
image-20220818192215762 image-20220818192236250

温馨提示:

要看到打印模式下效果,按以下步骤操作即可

在浏览器中右击 -> 打印(点击进入) -> 更多设置(点击)-> 背景图形(勾选上)就可以生效,看到效果了

image-20220818192504807

在实际的开发中,我们用到的最多也就是 all,screen

# 3、媒体特性

TIP

  • 媒体特性(Media features)描述了 user agent (用户代理-在网页中指浏览器)、输出设备或是浏览环境的具体特征。
  • 它负责测试这些特性或特征是否存在、值为多少。
  • 每条媒体特性表达式都必须用 括号() 括起来。
  • 媒体特性表达式是完全 可选的

常用的媒体特性

媒体特性 说明
width 设备屏幕的宽
min-width 设备屏幕的最小宽 (如min-width:400px;表示屏幕宽>=400px)
max-width 设备屏幕的最大 宽 (如max-width:1200px;表示屏幕宽<=1200px)
-webkit-device-pixel-ratio 设备像素比(dpr)的值(只有-webkit 内核的才支持)
-webkit-max-device-pixel-ratio 设备像素比(dpr)的最大值(只有-webkit 内核的才支持)
-webkit-min-device-pixel-ratio 设备像素比(dpr)的最小值(只有-webkit 内核的才支持)
resolution 值为2dppx时,表示设备像素比为 2 。目前现代浏览器都支持。
min-resolution 值为2dppx时,表示设备像素比>= 2
max-resolution 值为2dppx时,表示设备像素比<= 2
orientation 当前屏幕的方向,是横屏还竖屏
portrait: 表示竖屏 (orientation : portrait;)
landscape:表示横屏 (orientation:landscape;)
  • 如果只指定媒体特性,写法如下:
@media (媒体特性) {
  ...css样式...;
}
  • 如果同时指定媒体类型和媒体特性,中间需要有逻辑运算符,写法如下:
@media 媒体类型 逻辑运算符 (媒体特性) {
  .... css样式....;
}
  • 多个媒体特性中间也要有逻辑操运算符
@media 媒体类型 逻辑操运算符 ( 媒体特性) 逻辑操作符 (媒体特性) {
  .... css样式....;
}

案例演示

/* 所有设备的宽>=800px时,body的背景色为红色 */
@media (min-width: 800px) {
  body {
    background-color: red;
  }
}

/* 屏幕设备的宽>=800px时,body的背景色为红色 */
@media screen and (min-width: 800px) {
  body {
    background-color: red;
  }
}

/* 屏幕设备的宽>=800 同时<=1200px时,body的背景色为红色 */
@media screen and (min-width: 800px) and (max-width: 1200px) {
  body {
    background-color: red;
  }
}
  • 通过判断设备像素比 dpr,来设置对应样式

dpr = (在一个方向上)设备像素(物理像素) / 逻辑像素(CSS 像素)

/* dpr>=2时,body的背景色为红色 */
@media screen and (-webkit-min-device-pixel-ratio: 2) {
  body {
    background-color: red;
  }
}
/* dpr>=3时,body的背景色为蓝色 */
@media screen and (-webkit-min-device-pixel-ratio: 3) {
  body {
    background-color: blue;
  }
}

经典应用:移动端 1 像素问题,不清楚,可以看上一篇文章

  • resolution 用来检测当前设备的设备像素比
/*
当前设备为屏幕设备,同时设备像素比要 >=2时,才将背景色设为红色
*/
@media screen and (min-resolution: 2dppx) {
  body {
    background-color: red;
  }
}

完整的兼容性写法

/* 
-webkit-min-device-pixel-ratio 支持个版的 webkit内核浏览器
-moz-min-device-pixel-ratio  支持旧版的 firefox 浏览器
min-resolution  支持现在浏览器

*/
@media screen and (-webkit-min-device-pixel-ratio: 2),
  (-moz-min-device-pixel-ratio: 2),
  (min-resolution: 2dppx) {
  /* 所有环境下的高DPI设备 */
}
  • 通过判断用户是竖屏还是横屏观看,来设置对应样式
<style>
  /* 模屏观看时的CSS样式 */
  @media screen and (orientation: landscape) {
    .box {
      width: 100%;
      height: 200px;
      background-color: red;
    }
  }
  /* 竖屏观看时的 CSS样式 */
  @media screen and (orientation: portrait) {
    .box {
      width: 100%;
      height: 700px;
      background-color: blue;
    }
  }
</style>
<body>
  <div class="box"></div>
</body>

GIF 2022-8-18 21-12-02

# 4、逻辑运算符

TIP

  • 逻辑运算符(logical operators) not,andonly可用于联合构造复杂的媒体查询
  • 您还可以通过用 ,(逗号) 分隔多个媒体查询,将它们组合为一个规则。
逻辑运算符 说明
and and 操作符用于将多个媒体查询规则组合成单条媒体查询
当每个查询规则都为真时则该条媒体查询为真
,逗号 逗号用于将多个媒体查询合并为一个规则
逗号分隔列表中的每个查询都与其他查询分开处理
如果列表中的任何查询为 true,则整个 media 语句均返回 true。换句话说,列表的行为类似于逻辑 或or运算符
not not运算符用于否定媒体查询
如果不满足这个条件则返回true,否则返回false
not关键字只能用于否定整个媒体查询
如果使用 not 运算符,则还必须指定媒体类型。
如果出现在以逗号分隔的查询列表中,它将仅否定应用了该查询的特定查询(因此,它不会应用于以逗号分隔的媒体查询列表中的每个媒体查询)
only only 关键字,主要是为了兼容一些老版本的浏览器时,防止出错而加上的。
现代浏览器都完全支持了 媒体查询,所以 only 关键字可以省略不需要了。

# 4.1、and 运算符

TIP

  • and 操作符用于将多个媒体查询规则组合成单条媒体查询
  • 当每个查询规则都为时,则该条媒体查询为
/* 
    需要满足以下3个条件,body背景颜色才为红色
    屏幕设备
    屏幕的宽>=500px
    竖屏观看时
*/
@media screen and (min-width: 500px) and (orientation: portrait) {
  body {
    background-color: red;
  }
}

# 4.2、逗号逻辑运算符

TIP

  • 逗号用于将多个媒体查询合并为一个规则
  • 每个逗号前为一个独立的查询规则,逗号后为一个独立的查询规则
  • 逗号分隔的每一个独立的查询规则中,只要有一个为true,则整个 media 语句返回true
  • 换句话说 , 逗号 类似于js中的逻辑 或or运算符
/*
	以下查询语句,有两个独立的查规则
	1、screen and (min-width:400px)  设备为屏幕设备,同时屏幕宽>=400px 时成立
	2、(max-width:375px)  任何设备,设备宽<=375px时成立
	以上两条规则中,只要有一条成立,整个media语句为真,body的背景颜色就会设为红色。
*/
@media screen and (min-width: 400px), (max-width: 375px) {
  body {
    background-color: red;
  }
}

/*
	当设备为屏幕设备,同时宽<=375px时   或  当设备为屏幕设备,同时横屏观看时,背景色为红色
*/
@media screen and (max-width: 375px), screen and (orientation: landscape) {
  body {
    background-color: red;
  }
}

# 4.3、not 运算符

TIP

  • not运算符会反转 单个媒体查询规则 的含义

    • 如果出现在以逗号分隔的查询列表中,它将仅否定应用了该查询的特定查询。因此,它不会应用于以逗号分隔的媒体查询列表中的每个媒体查询
  • 如果不满足这个条件则返回true,否则返回false

  • 如果使用not运算符,则还必须指定媒体类型

  • not只能用来否定 整个(单个媒体的整个)媒体查询,所以不能放在 screen 之后

错误写法

/* not运算符中,没有指定媒体类型 不会报错,但不推荐这样写   */
@media not (min-width: 500px) {
  body {
    background-color: red;
  }
}

/* not 只能用来否定整个媒体查询,所以不能放在screen之后 */
@media screen not (min-width: 500px) {
  body {
    background-color: red;
  }
}

正确写法

/* 
	not否定的是 screen and (min-width:500px) 整个查询,可以理解为除这个条件下不生效,其它都生效
	当设备是screen 并且宽<500px 或 设备为非屏幕设备时,body的背景设为红色
*/
@media not screen and (min-width: 500px) {
  body {
    background-color: red;
  }
}

not 出现在以逗号分隔的查询列表中

  • 如果出现在以逗号分隔的查询列表中,它将仅否定应用了该查询的特定查询
  • 因此,它不会应用于以逗号分隔的媒体查询列表中的每个媒体查询
/*
	以下代码中的not只针对逗号前的查询规则取反
	not 取反的是 screen and (min-width:1000px),
	并不会对后面的screen and (orientation: landscape)
	所以当
	设备为屏幕设备,同时宽<1000px时 ,或 
	设备为非屏幕设备时,或
	设备为屏幕设备,同横屏幕观看时
	body的背景色为红色
*/
@media not screen and (min-width: 1000px), screen and (orientation: landscape) {
  body {
    background-color: red;
  }
}

# 4.4、only 运算符

TIP

  • only 关键字,主要是为了兼容一些老版本的浏览器时,防止出错而加上的。
  • 现代浏览器都完全支持了 媒体查询,所以 only 关键字可以省略不需要了。

# 二、响应式断点和书写位置

TIP

当我们需要为不同的屏幕尺寸来设置不同的样式时,我们就需要知道在什么屏幕尺寸下需要做出响应。

那这些不同的屏幕尺寸,就称为响应式断点(阈值)。

# 1、响应式断点(阈值)的设定

TIP

在实际的开发中,响应式断点是由公司根据项目来定的。

不过行业也会有一个标准的参考断点(Breakpoint),这里我们以 Bootstrap (opens new window) 框架内部的断点来给大家做讲解

屏幕大小 栅格布局中 class 名区分 断点(阈值)
超小屏(Extra small ) <576px
小屏 (Small) -sm 576px ~ 768px (含等于)
中屏 (Medium) -md 768px ~ 992px (含等于)
大屏 (Large) -lg 992px ~ 1200px(含等于)
超大屏 (X-Large) -xl 1200px ~ 1400px(含等于)
超大大屏(XX-Large) -xxl >1400px

在实际开发中

断点并不是完全按上面列出的值来的。而是根据我们所写的项目,在对屏幕做调整时,如果觉得当前效果不符合我们的需求,需要通过设置新的断点来调整,就可以在此添加相应的断点。

以上断点是 Bootstrap (前端响应式框架)框架内部的断点,我们可以用来作为我们开发的标准来参考。

案例演示

根据上面提供的标准断点,设置不同断点(屏幕尺寸)下,显示不同背景色。

<style>
  /* 当屏幕宽小于576px时,以下代码生效 */
  body {
    background-color: red;
  }
  /* 当屏幕宽大于等于576px,小于768px时,以下代码生效 */
  @media screen and (min-width: 576px) {
    body {
      background-color: khaki;
    }
  }
  /* 当屏幕宽大于等于768px,小于992px时,以下代码生效 */
  @media screen and (min-width: 768px) {
    body {
      background-color: skyblue;
    }
  }
  /* 当屏幕宽大于等于992px,小于1200px时,以下代码生效 */
  @media screen and (min-width: 992px) {
    body {
      background-color: green;
    }
  }
  /* 当屏幕宽大于等于1200px时,以下代码生效 */
  @media screen and (min-width: 1200px) {
    body {
      background-color: turquoise;
    }
  }
</style>

注:

在书写断点时,要注意代码的书写位置。以上采取了min-width 属性 从小到大的顺序来书写。

  • 当浏览器窗口大小为 1000px 时,min-width:992px中的样式和min-width:768px中的样式都会生效
  • 因为 css 选择器的权重相同时,写在后面的会覆盖写在前面的。
  • 所以min-width:992px下的样式会覆盖掉min-width:768px下的样式,最终生效的是min-width:992px下的样式。

# 2、媒体查询的代码书写位置

TIP

  • 媒体查询的代码可以写在 style 标签中,也可以写在单独的 CSS 文件中
  • 不过所有媒体查询代码都要写在所有 CSS 样式的代码之后。
  • 这样才能保证断点生效时,写在媒体查询中的代码能生效,不会被正常的样式所覆盖。

写在 style 标签中

<style>
  /* .....正常情况下的css样式....  */

  /* .....媒体查询代码 ....; */
</style>

写在单独的 css 文件中,通过 link 标签引入

/*
	media.css中写的是媒体查询的css代码
	link标签的引入位置,要放在所有css样式的最后面。
*/
<link rel="stylesheet" href="../css/media.css">

不同断点代码写入不同 css 文件中(不推荐 )

  • media 属性中的内容,和正常的写法一样
  • 通过 link 来引用,在 media 中来设置对应断点
<link rel="stylesheet" href="a.css" media="screen and (min-width:600px)" />
<link rel="stylesheet" href="b.css" media="screen and (min-width:1000px)" />
/* a.css文件内容 */
body {
  background-color: skyblue;
}
/* b.css文件内这从 */
body {
  background-color: red;
}

# 三、响应式两种适配方案

在实际的响应式开发中,我们会有两种通用的适配方案

  • PC 端优先(先考虑 PC 端,最后再考虑移动端)
  • 移动端优先(先考虑移动端,最后再考虑 PC 端)

# 1、PC 端优先

在 @media 查询时,我们会先以 PC 端为主,适配方案代码顺序为

/* ....这里的css样式,会在屏幕宽大于1400px时生效.... */
.....css样式.....

/* 当屏幕宽度大于1200px ,但小于等于1400px时,显示如下样式 */
@media screen and (max-width: 1400px) {
}

/* 当屏幕宽度大于992px ,但小于等于1200px时,显示如下样式 */
@media screen and (max-width: 1200px) {
}

/* 当屏幕宽度大于768px ,但小于等于992px时,显示如下样式 */
@media screen and (max-width: 992px) {
}

/* 当屏幕宽度大于576px ,但小于等于768px时,显示如下样式 */
@media screen and (max-width: 768px) {
}

/* 当屏幕宽度小于等于576px时,显示如下样式 */
@media screen and (max-width: 576px) {
}

/* 如果还想匹配更小的尺寸,可以在后面写,如小于等 480px时,要显示的样式  */

/* 当屏幕宽度小于等于576px时,显示如下样式, */
@media screen and (max-width: 480px) {
}

# 1.1、实战应用:不同屏幕尺寸下,显示不同的列数

屏幕宽 一行显示个数 每列(个)的宽
>1200px 6 100% / 6 = 16.16.66666667%
<=1200px 且 > 992px 5 100% / 5 = 20%
<=992px 且 > 768px 4 100% / 4 = 25%
<=768px 且 > 576px 3 100% / 3= 33.3333334%
<=576px 且 > 480px 2 100% / 2 = 50%
<=480px 1 100% / 1 = 100%

GIF 2022-8-19 15-59-19

<style>
  html,
  body {
    margin: 0;
  }
  .container {
    display: flex;
    flex-wrap: wrap;
  }
  .item {
    box-sizing: border-box;
    padding: 5px;
    /* 当屏幕宽度>1200px时,显示的宽  - 一排显示  */
    width: 16.66666667%;
  }
  .item img {
    width: 100%;
  }
  /* 当屏幕宽度大于992px ,但小于等于1200px时,显示如下样式 */
  @media screen and (max-width: 1200px) {
    .item {
      width: 20%;
    }
  }
  /* 当屏幕宽度大于768px ,但小于等于992px时,显示如下样式 */
  @media screen and (max-width: 992px) {
    .item {
      width: 25%;
    }
  }
  /* 当屏幕宽度大于576px ,但小于等于768px时,显示如下样式 */
  @media screen and (max-width: 768px) {
    .item {
      width: 33.333333%;
    }
  }
  /* 当屏幕宽度小于等于576px时,显示如下样式 */
  @media screen and (max-width: 576px) {
    .item {
      width: 50%;
    }
  }
  /* 当屏幕宽度小于等于480px时,显示如下样式 */
  @media screen and (max-width: 480px) {
    .item {
      width: 100%;
    }
  }
</style>
<body>
  <div class="container">
    <div class="item"><img src="images/img1.png" alt="" /></div>
    <div class="item"><img src="images/img1.png" alt="" /></div>
    <div class="item"><img src="images/img1.png" alt="" /></div>
    <div class="item"><img src="images/img1.png" alt="" /></div>
    <div class="item"><img src="images/img1.png" alt="" /></div>
    <div class="item"><img src="images/img1.png" alt="" /></div>
    <div class="item"><img src="images/img1.png" alt="" /></div>
    <div class="item"><img src="images/img1.png" alt="" /></div>
    <div class="item"><img src="images/img1.png" alt="" /></div>
    <div class="item"><img src="images/img1.png" alt="" /></div>
    <div class="item"><img src="images/img1.png" alt="" /></div>
    <div class="item"><img src="images/img1.png" alt="" /></div>
  </div>
</body>

# 2、移动端优先

TIP

在 @media 查询时,我们会先以移端为主,适配方案代码顺序为

/* 当屏幕宽度小于480px,显示以下样式 */
...css样式....

/* 如果还要设置更小尺寸,显示的样式,则可以写在这里,如 >=480p 但小 576px 时 */
@media screen and (min-width: 480px) {
}

/* 以下为行业标准参考的断点 */

/* 当屏幕宽度大于等于576px, 同时小于768px时,显示以下样式 */
@media screen and (min-width: 576px) {
}

/* 当屏幕宽度大于等于768px, 同时小于992px时,显示以下样式 */
@media screen and (min-width: 768px) {
}

/* 当屏幕宽度大于等于992px, 同时小于1200px时,显示以下样式 */
@media screen and (min-width: 992px) {
}

/* 当屏幕宽度大于等于1200px,同时小于 1400px时,显示以下样式 */
@media screen and (min-width: 1200px) {
}

/* 当屏幕宽度>=1400px ,显示如下样式 */
@media screen and (min-width: 1400px) {
}

# 2.1、实战应用:不同屏幕尺寸下,显示不同的列数

屏幕宽 一行显示个数 每列(个)的宽
<480px 1 100% / 1= 100%
>=480px 且 < 576px 2 100% / 2= 50%
>=576px 且 <768px 3 100% / 3=33.3333334%
>=768px 且 <992px 4 100% / 4 = 25%
>=992px 且 <1200px 5 100% / 5 = 20%
>=1200px 6 100% / 6 = 16.6666667%
<style>
  html,
  body {
    margin: 0;
  }
  .container {
    /* 弹性布局 */
    display: flex;
    /* 放不下时,换行 */
    flex-wrap: wrap;
  }
  .item {
    /* 怪异盒子模型 */
    box-sizing: border-box;
    padding: 5px;
    /* 当屏幕宽度<481px时,显示宽度*/
    width: 100%;
  }
  .item img {
    width: 100%;
  }
  /* 当屏幕宽度大于等于480px, 同时小于576px时,显示以下样式 */
  @media screen and (min-width: 480px) {
    .item {
      width: 50%;
    }
  }
  /* 当屏幕宽度大于等于576px, 同时小于768px时,显示以下样式 */
  @media screen and (min-width: 576px) {
    .item {
      width: 33.33333333%;
    }
  }
  /* 当屏幕宽度大于等于768px, 同时小于992px时,显示以下样式 */
  @media screen and (min-width: 768px) {
    .item {
      width: 25%;
    }
  }
  /* 当屏幕宽度大于等于992px, 同时小于1200px时,显示以下样式 */
  @media screen and (min-width: 992px) {
    .item {
      width: 20%;
    }
  }
  /* 当屏幕宽度大于等于1200px,显示以下样式 */
  @media screen and (min-width: 1200px) {
    .item {
      width: 16.6666667%;
    }
  }
</style>
<body>
  <div class="container">
    <div class="item"><img src="images/img1.png" alt="" /></div>
    <div class="item"><img src="images/img1.png" alt="" /></div>
    <div class="item"><img src="images/img1.png" alt="" /></div>
    <div class="item"><img src="images/img1.png" alt="" /></div>
    <div class="item"><img src="images/img1.png" alt="" /></div>
    <div class="item"><img src="images/img1.png" alt="" /></div>
    <div class="item"><img src="images/img1.png" alt="" /></div>
    <div class="item"><img src="images/img1.png" alt="" /></div>
    <div class="item"><img src="images/img1.png" alt="" /></div>
    <div class="item"><img src="images/img1.png" alt="" /></div>
    <div class="item"><img src="images/img1.png" alt="" /></div>
    <div class="item"><img src="images/img1.png" alt="" /></div>
  </div>
</body>

# 四、栅格布局

TIP

  • 所谓的栅格布局,你可以简单理解为,要把一个页面容器(如 div),分成多少份
  • 然后设置其 页面容器 子元素占对应的份数
  • 通常一个页面或容器会被分成:12 份,16 份,24 份
  • 如果将网页(100%)分成 12 份,那对应不同份数所占的比例如下:
份数 占总份数的百分比%
1 8.33333333%
2 16.6666667%
3 25%
4 33.33333333%
5 41.66666667%
6 50%
7 58.33333333%
8 66.6666667%
9 75%
10 83.33333333%
11 91.66666667%
12 100%

# 1、百分比实现栅格布局

将页面分成 12 分,每份所占的比例

/* 以下 css 保存在 response.css 中*/
/* 不同份数,所占的宽 */
.col-1 {
  width: 8.33333333%;
}
.col-2 {
  width: 16.66666667%;
}
.col-3 {
  width: 25%;
}
.col-4 {
  width: 33.33333333%;
}
.col-5 {
  width: 41.66666667%;
}
.col-6 {
  width: 50%;
}
.col-7 {
  width: 58.33333333%;
}
.col-8 {
  width: 66.6666667%;
}
.col-9 {
  width: 75%;
}
.col-10 {
  width: 83.33333333%;
}
.col-11 {
  width: 91.66666667%;
}
.col-12 {
  width: 100%;
}

# 1.1、栅格布局应用

利用栅格布局,实现一行 4 列,3 列,2 列,1 列的布局

<style>
  html,
  body {
    margin: 0;
  }
  .row {
    width: 100%;
    display: flex; /* 弹性布局 */
    flex-wrap: wrap; /* 放不下时换行 */
  }
  .col {
    box-sizing: border-box;
    height: 100px;
    border: 1px solid red;
    margin-top: 10px;
  }
</style>
<!-- 引用 栅格布局样式 -->
<link rel="stylesheet" href="./response.css" />
<body>
  <div class="row">
    <!-- 一行4列 -->
    <div class="col col-3"></div>
    <div class="col col-3"></div>
    <div class="col col-3"></div>
    <div class="col col-3"></div>
    <!-- 一行3列 -->
    <div class="col col-4"></div>
    <div class="col col-4"></div>
    <div class="col col-4"></div>
    <!-- 一行2列 -->
    <div class="col col-6"></div>
    <div class="col col-6"></div>
    <!-- 一行1列 -->
    <div class="col col-12"></div>
  </div>
</body>

screencapture-127-0-0-1-5500-rem-html-2022-08-23-23_19_23(1)

# 2、grid 网格实现栅格布局

利用 grid 网格布局,将容器分成 12 分,每份所占的列数

/* 以下代码保存在 grid.css 文件中 */
.grid-12 {
  /* 网格布局 */
  display: grid;
  /* 将容器等分成12列 */
  grid-template-columns: repeat(12, 1fr);
}

.col-1 {
  /* 起始行网格线  起始列网格线  结束行网格线  结束列网格线(或跨几列) */
  grid-area: auto/auto/auto/span 1;
}
.col-2 {
  grid-area: auto/auto/auto/span 2;
}
.col-3 {
  grid-area: auto/auto/auto/span 3;
}
.col-4 {
  grid-area: auto/auto/auto/span 4;
}
.col-5 {
  grid-area: auto/auto/auto/span 5;
}
.col-6 {
  grid-area: auto/auto/auto/span 6;
}
.col-7 {
  grid-area: auto/auto/auto/span 7;
}
.col-8 {
  grid-area: auto/auto/auto/span 8;
}
.col-9 {
  grid-area: auto/auto/auto/span 9;
}
.col-10 {
  grid-area: auto/auto/auto/span 10;
}
.col-11 {
  grid-area: auto/auto/auto/span 11;
}
.col-12 {
  grid-area: auto/auto/auto/span 12;
}

# 2.1、栅格布局实战应用

利用栅格布局,实现一行 4 列,3 列,2 列,1 列的布局

<style>
  .container {
    height: 100px;
    margin: 10px 0;
  }
  .grid-item {
    padding: 10px;
    font-size: 20px;
    color: red;
  }
  /* 奇数项背景颜色 */
  .grid-item:nth-child(2n + 1) {
    background-color: skyblue;
  }
  /* 偶数项背景颜色 */
  .grid-item:nth-child(2n) {
    background-color: tomato;
  }
</style>
<!-- 引用 栅格布局样式 -->
<link rel="stylesheet" href="./grid.css" />
<body>
  <div class="container grid-12">
    <div class="grid-item col-3">1</div>
    <div class="grid-item col-3">2</div>
    <div class="grid-item col-3">3</div>
    <div class="grid-item col-3">3</div>
  </div>
  <div class="container grid-12">
    <div class="grid-item col-4">1</div>
    <div class="grid-item col-4">2</div>
    <div class="grid-item col-4">3</div>
  </div>
  <div class="container grid-12">
    <div class="grid-item col-6">1</div>
    <div class="grid-item col-6">2</div>
  </div>
  <div class="container grid-12">
    <div class="grid-item col-6">1</div>
    <div class="grid-item col-3">2</div>
    <div class="grid-item col-3">2</div>
  </div>
</body>

image-20220823233102055

注:

可以去 Bootstrap 官网 (opens new window),下载对应的源码,查看 Bootstrap 的栅格系统,Bootstrap 底层是将页面分成 12 份。

# 五、响应式栅格系统

在实际开发中

  • 要完美的实现响应式系统或网站的开发,就需要利用响应式栅格系统来帮助我们实现。
  • BootStrap 框架实现响应式布局的本质就是他的响应式栅格系统。
  • 响应式栅格系统是:栅格布局 + 响应断点 +响应式适配方案 3 者结合实现的一套响应式解决方案

# 1、响应式栅格系统实现步骤

TIP

我们可以按以下 4 步骤来实现响应式栅格系统

  • 你打算将页面分成多少份 ?
  • 确定响应断点有哪些 ?(通常参考行业标准来 )
  • 确定响应式适配方案(PC 端优先 或 移动端优先)
  • 在对应的响应断点下,书写对应的栅格布局样式。(这一步,实现响应式栅格系统)

# 2、你打算将页面分成多少份?

假设

我们将页面分成 12 份,那对应不同份数占总份数的比例

份数 占总份数的百分比%
1 8.33333333%
2 16.6666667%
3 25%
4 33.33333333%
5 41.66666667%
6 50%
7 58.33333333%
8 66.6666667%
9 75%
10 83.33333333%
11 91.66666667%
12 100%

# 2、确定响应断点有哪些?

假设整个响应式效果,对应的断点如下:

  • < 576px
  • 576px ~ 768px (含等于)
  • 768px ~ 992px (含等于)
  • 992px ~ 1200px(含等于)
  • 1200px ~ 1400px (含等于)
  • 大于 1400px
屏幕大小 栅格布局中 class 名区分 断点(阈值)
超小屏(Extra small ) <576px
小屏 (Small) -sm 576px ~ 768px (含等于)
中屏 (Medium) -md 768px ~ 992px (含等于)
大屏 (Large) -lg 992px ~ 1200px(含等于)
超大屏 (X-Large) -xl 1200px ~ 1400px(含等于)
超大大屏(XX-Large) -xxl >1400px

# 3、确定响应式适配方案

响应式适配方案有两种:PC 端优先 和 移动端优先

  • 这里我们选择 PC 端优先
  • PC 端优先适配方案与断点结合,得到如下代码 !
<style>
  /* 大于1400px的样式写在这里 */
  /* ....css样式.... */

  /* 当屏幕宽>1200 px 同时<=1400px ,显示如下样式 */
  @media screen and (max-width: 1400px) {
  }
  /* 屏幕宽>992px,同时<=1200px时,样式写在这里 */
  @media screen and (max-width: 1200px) {
  }
  /* 屏幕宽>768px,同时<=992px时,样式写在这里 */
  @media screen and (max-width: 992px) {
  }
  /* 屏幕宽>766px,同时<=768px时,样式写在这里 */
  @media screen and (max-width: 768px) {
  }
  /* 屏幕宽<=576px样式写在这里 */
  @media screen and (max-width: 576px) {
  }
</style>

# 4、在对应的响应断点下,书写对应的栅格布局样式

TIP

以下 css 样式放在 media.css 中,后面引入的 media.css 就是这里的代码

以下 css 代码,我们就称之为 响应式栅格系统

点击查看完整源代码
/* 
第一:我们将页面分成12分
第二:我们选择的断点是行业标准断点
第三:我们选择的适配方案,是PC端优先
*/

/* ....这里的css样式,会在屏幕宽大于1400px时生效.... */

.col-xxl-1 {
  width: 8.333333%;
}
.col-xxl-2 {
  width: 16.6666667%;
}
.col-xxl-3 {
  width: 25%;
}

.col-xxl-4 {
  width: 33.33333333%;
}
.col-xxl-5 {
  width: 41.66666667%;
}
.col-xxl-6 {
  width: 50%;
}
.col-xxl-7 {
  width: 58.33333333%;
}
.col-xxl-8 {
  width: 66.6666667%;
}
.col-xxl-9 {
  width: 75%;
}
.col-xxl-10 {
  width: 83.33333333%;
}
.col-xxl-11 {
  width: 91.66666667%;
}
.col-xxl-12 {
  width: 100%;
}

/* 当屏幕宽度大于1200px ,但小于等于1400px时,显示如下样式 */
@media screen and (max-width: 1400px) {
  .col-xl-1 {
    width: 8.333333%;
  }
  .col-xl-2 {
    width: 16.6666667%;
  }
  .col-xl-3 {
    width: 25%;
  }

  .col-xl-4 {
    width: 33.33333333%;
  }
  .col-xl-5 {
    width: 41.66666667%;
  }
  .col-xl-6 {
    width: 50%;
  }
  .col-xl-7 {
    width: 58.33333333%;
  }
  .col-xl-8 {
    width: 66.6666667%;
  }
  .col-xl-9 {
    width: 75%;
  }
  .col-xl-10 {
    width: 83.33333333%;
  }
  .col-xl-11 {
    width: 91.66666667%;
  }
  .col-xl-12 {
    width: 100%;
  }
}

/* 当屏幕宽度大于992px ,但小于等于1200px时,显示如下样式 */
@media screen and (max-width: 1200px) {
  .col-lg-1 {
    width: 8.333333%;
  }
  .col-lg-2 {
    width: 16.6666667%;
  }
  .col-lg-3 {
    width: 25%;
  }

  .col-lg-4 {
    width: 33.33333333%;
  }
  .col-lg-5 {
    width: 41.66666667%;
  }
  .col-lg-6 {
    width: 50%;
  }
  .col-lg-7 {
    width: 58.33333333%;
  }
  .col-lg-8 {
    width: 66.6666667%;
  }
  .col-lg-9 {
    width: 75%;
  }
  .col-lg-10 {
    width: 83.33333333%;
  }
  .col-lg-11 {
    width: 91.66666667%;
  }
  .col-lg-12 {
    width: 100%;
  }
}

/* 当屏幕宽度大于768px ,但小于等于992px时,显示如下样式 */
@media screen and (max-width: 992px) {
  .col-md-1 {
    width: 8.333333%;
  }
  .col-md-2 {
    width: 16.6666667%;
  }
  .col-md-3 {
    width: 25%;
  }

  .col-md-4 {
    width: 33.33333333%;
  }
  .col-md-5 {
    width: 41.66666667%;
  }
  .col-md-6 {
    width: 50%;
  }
  .col-md-7 {
    width: 58.33333333%;
  }
  .col-md-8 {
    width: 66.6666667%;
  }
  .col-md-9 {
    width: 75%;
  }
  .col-md-10 {
    width: 83.33333333%;
  }
  .col-md-11 {
    width: 91.66666667%;
  }
  .col-md-12 {
    width: 100%;
  }
}

/* 当屏幕宽度大于576px ,但小于等于768px时,显示如下样式 */
@media screen and (max-width: 768px) {
  .col-sm-1 {
    width: 8.333333%;
  }
  .col-sm-2 {
    width: 16.6666667%;
  }
  .col-sm-3 {
    width: 25%;
  }

  .col-sm-4 {
    width: 33.33333333%;
  }
  .col-sm-5 {
    width: 41.66666667%;
  }
  .col-sm-6 {
    width: 50%;
  }
  .col-sm-7 {
    width: 58.33333333%;
  }
  .col-sm-8 {
    width: 66.6666667%;
  }
  .col-sm-9 {
    width: 75%;
  }
  .col-sm-10 {
    width: 83.33333333%;
  }
  .col-sm-11 {
    width: 91.66666667%;
  }
  .col-sm-12 {
    width: 100%;
  }
}

/* 当屏幕宽度小于等于576px时,显示如下样式 */
@media screen and (max-width: 576px) {
  .col-1 {
    width: 8.333333%;
  }
  .col-2 {
    width: 16.6666667%;
  }
  .col-3 {
    width: 25%;
  }

  .col-4 {
    width: 33.33333333%;
  }
  .col-5 {
    width: 41.66666667%;
  }
  .col-6 {
    width: 50%;
  }
  .col-7 {
    width: 58.33333333%;
  }
  .col-8 {
    width: 66.6666667%;
  }
  .col-9 {
    width: 75%;
  }
  .col-10 {
    width: 83.33333333%;
  }
  .col-11 {
    width: 91.66666667%;
  }
  .col-12 {
    width: 100%;
  }
}

# 六、实现响应式效果

TIP

利用上面写的 响应式栅格系统,来实现如下图所示的响应效果, 1 行四列,变 2 列, 变 1 列

实现步骤如下

  • 如果是以移动端优先,则对着移动端设计稿来开发,然后再确定不同断点下要实现的效果,通过适配慢慢过渡到 PC 端。
  • 如果是 PC 端优先,则对着 PC 端设计稿来开发,然后再确定不同断点下要实现的效果,通过适配慢慢过渡到移动端。

GIF 2022-8-19 19-17-22

以下适配采用的是 PC 端优先,从 PC 端慢慢过渡到移动端开发。对应断点和效果如下

屏幕宽 (断点) 一行显示个数
>1200px 3 列
<= 1200px 2 列
<= 992px 1 列
<!-- 栅格系统的代码样式在media.css文件中 ,具体代码,就是步骤4种的代码 -->
<link rel="stylesheet" href="./css/media.css" />
<style>
  html,
  body {
    margin: 0;
  }
  .row {
    display: flex;
    flex-wrap: wrap;
    margin-top: 20px;
  }
  .col {
    box-sizing: border-box;
    border: 1px solid red;
    margin: 10px 0;
    min-height: 100px;
  }
</style>
<body>
  <div class="row">
    <!--
		大于 1200px 显示  3列 
		<= 1200px 显示 2列
		<= 992px 显示 1列
	-->
    <div class="col col-xl-3 col-lg-6 col-sm-12">1</div>
    <div class="col col-xl-3 col-lg-6 col-sm-12">2</div>
    <div class="col col-xl-3 col-lg-6 col-sm-12">3</div>
    <div class="col col-xl-3 col-lg-6 col-sm-12">4</div>
  </div>
</body>

# 七、实战应用

利用响应式栅格系统实现如下所示的响应式布局

GIF2025-1-1123-16-04

TIP

不同响应式断点下的的效果

  • 当视口宽 >1200px 时,以正常效果显示
  • 当视口宽 <= 1200px 时,上面一行 4 列,变成 1 行 2 列
  • 当视口宽 <= 992px 时,第二和第三行的一行 2 列变 1 列,最下面的一行 3 列变成 1 行 2 列和 1 行 1 列
  • 当视口宽 <= 768px 时,全部一行一列显示 ,同时上面的导航变成点击下拉菜单形式

确定适配方案以 PC 端优先,所以我们按 PC 的设计稿来开发,然后慢慢过渡到移动端

点击查看完整源代码
<style>
  body {
    margin: 0;
    background-color: #ddd;
  }
  .row {
    display: flex;
    flex-wrap: wrap;
  }
  .col {
    min-height: 100px;
    /* width:25%; */
    box-sizing: border-box;
    padding: 10px;
  }
  .col-content {
    background-color: #fff;
    border-radius: 10px;
    height: 100%;
  }

  .main {
    margin: 20px;
    max-width: 1400px;
    margin: 0px auto;
  }
</style>
<body>
  <main class="main">
    <div class="row">
      <div class="col col-xxl-3 col-lg-6 col-sm-12">
        <div class="col-content"></div>
      </div>
      <div class="col col-xxl-3 col-lg-6 col-sm-12">
        <div class="col-content"></div>
      </div>
      <div class="col col-xxl-3 col-lg-6 col-sm-12">
        <div class="col-content"></div>
      </div>
      <div class="col col-xxl-3 col-lg-6 col-sm-12">
        <div class="col-content"></div>
      </div>
    </div>
    <div class="row">
      <div class="col col-xxl-8 col-md-12">
        <div class="col-content"></div>
      </div>
      <div class="col col-xxl-4 col-md-12">
        <div class="col-content"></div>
      </div>
    </div>
    <div class="row">
      <div class="col col-xxl-4 col-md-12">
        <div class="col-content"></div>
      </div>
      <div class="col col-xxl-8 col-md-12">
        <div class="col-content"></div>
      </div>
    </div>
    <div class="row">
      <div class="col col-xxl-4 col-md-6 col-sm-12">
        <div class="col-content"></div>
      </div>
      <div class="col col-xxl-4 col-md-6 col-sm-12">
        <div class="col-content"></div>
      </div>
      <div class="col col-xxl-4 col-md-12 col-sm-12">
        <div class="col-content"></div>
      </div>
    </div>
  </main>
</body>

# 八、项目开发准备工作

TIP

利用响应式栅格系统实现以下响应式后台管理界面开发,PSD 设计稿已上传至钉钉群,可以找助理老师获取。

image-20220508004130308.95d7aebe

ipad-iphone.3c8d4a8d

# 1、整个项目的开发流程

TIP

系统了解响应式项目开发的完整流程

# 2 、搭建项目文件夹结构

TIP

  • 新建文件夹 WebApp
  • 在 WebApp 中新建 cssjsimagesiconfont 等文件夹,分别用来放 css、js、图片、阿里图标内容。
  • 新建 global.cssreset.cssindex.cssmedia.css,分别用来存放全局样式、重置样式、首页样式、通用响应式样式。
  • 新建 index.html 文件,然后按以下顺序引用 CSS 文件
/* 重置样式 */
css代码...

/* 网站通用布局 */
css代码...

/* 通用模块 */
css代码...

/* 通用元件 */
css代码...

/* 通用响应式系统 */
css代码...
<link rel="stylesheet" href="./css/reset.css" />
<link rel="stylesheet" href="./css/global.css" />
<link rel="stylesheet" href="./css/index.css" />
<link rel="stylesheet" href="./css/media.css" />

# 3、确定栅格系统样式(media.css 样式)

TIP

按以下 3 个步骤,确定 media.css 样式

  • 将页面分成 12 份,确定栅格布局不同份数所点比例
  • 确定项目对应的断点,采用行业标准断点
屏幕大小 栅格布局中 class 名区分 断点(阈值)
超小屏(Extra small ) <576px
小屏 (Small) -sm 576px ~ 768px (含等于)
中屏 (Medium) -md 768px ~ 992px (含等于)
大屏 (Large) -lg 992px ~ 1200px(含等于)
超大屏 (X-Large) -xl 1200px ~ 1400px(含等于)
超大大屏(XX-Large) -xxl >1400px
  • 确定适配方案,以 PC 端优先

最终确定 media.css 文件的代码如下

.row {
  display: flex;
  flex-wrap: wrap;
}

.col-xxl-1 {
  width: 8.33333333%;
}
.col-xxl-2 {
  width: 16.66666667%;
}
.col-xxl-3 {
  width: 25%;
}
.col-xxl-4 {
  width: 33.33333333%;
}
.col-xxl-5 {
  width: 41.66666667%;
}
.col-xxl-6 {
  width: 50%;
}
.col-xxl-7 {
  width: 58.33333333%;
}
.col-xxl-8 {
  width: 66.6666667%;
}
.col-xxl-9 {
  width: 75%;
}
.col-xxl-10 {
  width: 83.33333333%;
}
.col-xxl-11 {
  width: 91.66666667%;
}
.col-xxl-12 {
  width: 100%;
}

/* 当屏幕宽>1200 px 同时<=1400px ,显示如下样式 */
@media screen and (max-width: 1400px) {
  .col-xl-1 {
    width: 8.33333333%;
  }
  .col-xl-2 {
    width: 16.66666667%;
  }
  .col-xl-3 {
    width: 25%;
  }
  .col-xl-4 {
    width: 33.33333333%;
  }
  .col-xl-5 {
    width: 41.66666667%;
  }
  .col-xl-6 {
    width: 50%;
  }
  .col-xl-7 {
    width: 58.33333333%;
  }
  .col-xl-8 {
    width: 66.6666667%;
  }
  .col-xl-9 {
    width: 75%;
  }
  .col-xl-10 {
    width: 83.33333333%;
  }
  .col-xl-11 {
    width: 91.66666667%;
  }
  .col-xl-12 {
    width: 100%;
  }
}
/* 屏幕宽>992px,同时<=1200px时,样式写在这里 */
@media screen and (max-width: 1200px) {
  .col-lg-1 {
    width: 8.33333333%;
  }
  .col-lg-2 {
    width: 16.66666667%;
  }
  .col-lg-3 {
    width: 25%;
  }
  .col-lg-4 {
    width: 33.33333333%;
  }
  .col-lg-5 {
    width: 41.66666667%;
  }
  .col-lg-6 {
    width: 50%;
  }
  .col-lg-7 {
    width: 58.33333333%;
  }
  .col-lg-8 {
    width: 66.6666667%;
  }
  .col-lg-9 {
    width: 75%;
  }
  .col-lg-10 {
    width: 83.33333333%;
  }
  .col-lg-11 {
    width: 91.66666667%;
  }
  .col-lg-12 {
    width: 100%;
  }
}
/* 屏幕宽>768px,同时<=992px时,样式写在这里 */
@media screen and (max-width: 992px) {
  .col-md-1 {
    width: 8.33333333%;
  }
  .col-md-2 {
    width: 16.66666667%;
  }
  .col-md-3 {
    width: 25%;
  }
  .col-md-4 {
    width: 33.33333333%;
  }
  .col-md-5 {
    width: 41.66666667%;
  }
  .col-md-6 {
    width: 50%;
  }
  .col-md-7 {
    width: 58.33333333%;
  }
  .col-md-8 {
    width: 66.6666667%;
  }
  .col-md-9 {
    width: 75%;
  }
  .col-md-10 {
    width: 83.33333333%;
  }
  .col-md-11 {
    width: 91.66666667%;
  }
  .col-md-12 {
    width: 100%;
  }
}
/* 屏幕宽>576px,同时<=768px时,样式写在这里 */
@media screen and (max-width: 768px) {
  .col-sm-1 {
    width: 8.33333333%;
  }
  .col-sm-2 {
    width: 16.66666667%;
  }
  .col-sm-3 {
    width: 25%;
  }
  .col-sm-4 {
    width: 33.33333333%;
  }
  .col-sm-5 {
    width: 41.66666667%;
  }
  .col-sm-6 {
    width: 50%;
  }
  .col-sm-7 {
    width: 58.33333333%;
  }
  .col-sm-8 {
    width: 66.6666667%;
  }
  .col-sm-9 {
    width: 75%;
  }
  .col-sm-10 {
    width: 83.33333333%;
  }
  .col-sm-11 {
    width: 91.66666667%;
  }
  .col-sm-12 {
    width: 100%;
  }
}
/* 屏幕宽<=576px样式写在这里 */
@media screen and (max-width: 576px) {
  .col-1 {
    width: 8.33333333%;
  }
  .col-2 {
    width: 16.66666667%;
  }
  .col-3 {
    width: 25%;
  }
  .col-4 {
    width: 33.33333333%;
  }
  .col-5 {
    width: 41.66666667%;
  }
  .col-6 {
    width: 50%;
  }
  .col-7 {
    width: 58.33333333%;
  }
  .col-8 {
    width: 66.6666667%;
  }
  .col-9 {
    width: 75%;
  }
  .col-10 {
    width: 83.33333333%;
  }
  .col-11 {
    width: 91.66666667%;
  }
  .col-12 {
    width: 100%;
  }
}

# 4、 正式开发流程

TIP

因为确定适配方案以 PC 端优先,所以我们先按 PC 的设计稿来开发,然后开发完再通过断点的适配,一步步过渡到移动。

# 九、实现整体响应式架构布局

GIF2025-7-1917-24-52

完整源码

<!-- header start -->
<header class="header">
  <div class="header-content"></div>
</header>
<!-- end header -->

<!-- sidebar-menu start -->
<nav class="sidebar-menu"></nav>
<!-- end sidebar-menu -->

<!-- main start -->
<main class="main"></main>
<!-- end main -->
<style>
  body {
    background-color: #f3f4f7;
    /* height: 2000px; 这个高度后面要去掉 ,只为测试效果用的 */
  }
  .header {
    position: fixed;
    top: 0px;
    left: 20px;
    right: 20px;
    height: 115px;
    background-color: #f3f4f7;
    /* border: 1px solid red; */
    padding-top: 20px;
  }
  .header-content {
    height: 75px;
    background-color: #fff;
    border-radius: 10px;
  }
  .sidebar-menu {
    width: 260px;
    position: fixed;
    top: 115px;
    bottom: 20px;
    left: 20px;
    background-color: #fff;
    border-radius: 10px;
  }

  .main {
    margin: 115px 20px 0px 300px;
    min-height: 1500px; /*这个高度是为了看效果,后面要去掉 */
    border: 2px solid red;
  }
</style>
<link rel="stylesheet" href="./css/media.css" />
<style>
  /* 以下代码,最后会保存到 response.css 文件中 */
  @media screen and (max-width: 1400px) {
    .sidebar-menu {
      width: 75px;
      overflow: hidden;
    }
    .main {
      margin-left: 115px;
    }
  }

  @media screen and (max-width: 1300px) {
    .sidebar-menu {
      display: none;
    }
    .main {
      margin-left: 20px;
    }
  }
</style>

以下为具体实现步骤

# 1、设置背景颜色

body {
  background-color: #f3f4f7;
}

# 2、头部开发

image-20250719161714957

<!-- header start -->
<header class="header">
  <div class="header-content"></div>
</header>
<!-- end header -->

头部采用固定定位,定位在页面最顶部

.header {
  position: fixed;
  top: 0px;
  left: 20px;
  right: 20px;
  height: 115px;
  background-color: #f3f4f7;
  border: 1px solid red; /* 查看效果,后面去掉 */
  padding-top: 20px; /* header 是怪异盒子模型,所以添加内容距,不会添加其可视区高 */
}

.header-content {
  height: 75px;
  background-color: #fff;
  border-radius: 10px;
}

你可以,给 body 添加 一个很大的高度,用来测试有滚动条情况下,头部是否一直固定在页面最顶部

body {
  height: 2000px; /* 这个高度后面要去掉 ,只为测试效果用的 */
}

# 3、左侧侧边栏菜单

image-20250719162644253

左侧侧边栏菜单也是采用固定定位,一直定位在页面的最右侧

<!-- sidebar-menu start -->
<nav class="sidebar-menu"></nav>
<!-- end sidebar-menu -->
.sidebar-menu {
  width: 260px;
  position: fixed;
  top: 115px;
  bottom: 20px;
  left: 20px;
  background-color: #fff;
  border-radius: 10px;
}

# 4、右侧主体布局

GIF2025-7-1916-43-53

<!-- main start -->
<main class="main"></main>
<!-- end main -->
body {
  /* 去掉 body 中的高度来看效果 */
  /*  height: 2000px; 这个高度后面要去掉 ,只为测试效果用的 */
}
.main {
  margin: 115px 20px 0px 300px;
  min-height: 1500px; /* 这个高度是为了看效果,后面要去掉 */
  border: 2px solid red;
}

# 5、左侧侧边栏与主体 - 响应式适配

GIF2025-7-1917-24-52

屏幕尺寸 左侧侧边栏效果 右侧主体效果
> 1400px 正常显示( width:260px ) 正常显示
<=1400px 宽度缩小到 75px ( width:75px ) 主体宽占满剩余空间 ( margin-left:115px )
<=1300px 侧边栏隐藏不可见 ( display:none ) 主体宽占满剩余空间 (margin-left:20px )
/* 宽 <=1400px */
@media screen and (max-width: 1400px) {
  .sidebar-menu {
    width: 75px; /* 修改宽度 */
    overflow: hidden; /* 超出部分隐藏 */
  }
  .main {
    margin-left: 115px; /* 调整左外边距来调整主体的宽 */
  }
}

/* 宽 <=1300px */
@media screen and (max-width: 1300px) {
  .sidebar-menu {
    display: none; /* 隐藏侧边栏 */
  }
  .main {
    margin-left: 20px; /* 调整左外边距来调整主体的宽 */
  }
}

# 十、主体内容响应式布局

TIP

本项目采用适配方案为 PC 端优先(栅格系统适配也要采用 PC 端优先)),则先考虑大屏,然后再慢慢过渡到小屏幕。

# 1、主体内容 - 第一块响应式布局

image-20250719180542321

首先实现 PC 端大屏幕布局,一排显示 4 个,同时每个之间有相同的间隔,两端对齐布局。实现本效果需要采用一些技巧来实现,具体实现步骤如下:

实现步骤如下

  • 创建一个与主体部分一样宽的长方形

image-20250719175535905

  • 在黄色长方形内,创建一个宽=100% + 20px(每列间隙的大小)

image-20250719175812852

  • 在蓝色长方形内创建 4 个一样大小的长方形 ( 利用栅格布局,将页面分成 12 份,每列占 3 份)

image-20250719180109089

  • 给每个长方形添加向右的内边距,内边距大小 = 长方形之间间隙大小

image-20250719180304562

白色的长方形为红色长方形内的直接子元素,用来放具体内容的。

  • 将黄色背景盒子设置 overflow:hidden

image-20250719180503235

  • 去掉所有相关的辅助边框线和背景色,最终效果如下

image-20250719180542321

完整源码

<!-- main start -->
<main class="main">
  <!-- main-part1 start -->
  <section class="main-part1">
    <div class="common-width row">
      <div class="col col-xxl-3">
        <div class="col-content"></div>
      </div>
      <div class="col col-xxl-3">
        <div class="col-content"></div>
      </div>
      <div class="col col-xxl-3">
        <div class="col-content"></div>
      </div>
      <div class="col col-xxl-3">
        <div class="col-content"></div>
      </div>
    </div>
  </section>
  <!-- end main-part1 -->
</main>
<!-- end main -->
.main-part1 {
  /* min-height: 200px; 后面要去掉 */
  /* background-color: khaki; */
  overflow: hidden;
}
.common-width {
  /* min-height: 200px; 后面要去掉 */
  width: calc(100% + 20px);
  /* border: 2px solid blue; */
}
.common-width .col {
  /* border: 1px solid red; */
  padding-right: 20px;
}
.col .col-content {
  background-color: #fff;
  min-height: 150px;
  border-radius: 10px;
}

# 1.1、响应式适配

从大屏过渡到小屏适配

屏幕尺寸 一排显示列数
>1200px 4 列 (每列占 3 份 ,上面已完成)
<=1200px 2 列 (每列占 6 份)
<=768px 1 列(每列占 12 份)
<!-- main-part1 start -->
<section class="main-part1">
  <div class="common-width row">
    <div class="col col-xxl-3 col-lg-6 col-sm-12">
      <div class="col-content"></div>
    </div>
    <div class="col col-xxl-3 col-lg-6 col-sm-12">
      <div class="col-content"></div>
    </div>
    <div class="col col-xxl-3 col-lg-6 col-sm-12">
      <div class="col-content"></div>
    </div>
    <div class="col col-xxl-3 col-lg-6 col-sm-12">
      <div class="col-content"></div>
    </div>
  </div>
</section>
<!-- end main-part1 -->

# 2、主体内容 - 第二块响应式布局+适配

屏幕尺寸 一排显示列数
>992px 2 列 (第一列占 8 份,第 2 列占 4 份)
<=992px 1 列 (每列占 12 份)
<!-- end main-part1 -->
<section class="main-part2">
  <div class="common-width row">
    <div class="col col-xxl-8 col-md-12">
      <div class="col-content">1</div>
    </div>
    <div class="col col-xxl-4 col-md-12">
      <div class="col-content">2</div>
    </div>
  </div>
</section>

# 3、主体内容 - 第三块响应式布局+适配

屏幕尺寸 一排显示列数
>768px 2 列 (第一列占 4 份,第 2 列占 8 份)
<=768px 1 列 (每列占 12 份)
<section class="main-part3">
  <div class="common-width row">
    <div class="col col-xxl-4 col-sm-12">
      <div class="col-content">1</div>
    </div>
    <div class="col col-xxl-8 col-sm-12">
      <div class="col-content">2</div>
    </div>
  </div>
</section>

# 4、主体内容 - 第四块响应式布局+适配

屏幕尺寸 一排显示列数
>992 3 列 ( 每列占 4 份)
<=992px 第一排显示 2 列 (每列占 6 份) 第二排显示 1 列(占 12 份)
<=768px 1 列 ( 每列占 12 份 )
<section class="main-part4">
  <div class="common-width row">
    <div class="col col-xxl-4 col-md-6 col-sm-12">
      <div class="col-content">1</div>
    </div>
    <div class="col col-xxl-4 col-md-6 col-sm-12">
      <div class="col-content">2</div>
    </div>
    <div class="col col-xxl-4 col-md-12">
      <div class="col-content">2</div>
    </div>
  </div>
</section>

# 十一、左侧响应式伸缩二级菜单开发

TIP

深入浅出左侧响应式伸缩二级菜单开发完整开发步骤

# 1、第一步:一级菜单布局

image-20250722163858045

<nav class="sidebar-menu">
  <div class="menu-item">
    <div class="menu-item-title">
      <span class="iconfont icon-jiaoxuepingjia"></span>
      教学管理
    </div>
  </div>
  <div class="menu-item">
    <div class="menu-item-title">
      <span class="iconfont icon-ren"></span>
      助学管理
    </div>
  </div>
  <div class="menu-item">
    <div class="menu-item-title">
      <span class="iconfont icon-yingxiao"></span>
      营销管理
    </div>
  </div>
</nav>
.sidebar-menu {
  padding: 20px;
}
.sidebar-menu .menu-item {
  border: 1px solid red;
}
.sidebar-menu .menu-item .menu-item-title {
  height: 40px;
  display: flex;
  align-items: center;
  font-size: 16px;
  background-image: url(./images/r-jiantou.svg);
  background-repeat: no-repeat;
  background-position: 200px center;
}
.sidebar-menu .menu-item .menu-item-title .iconfont {
  font-size: 16px;
  color: #000;
  margin-right: 12px;
  margin-left: 7px;
}

# 2、第二步:菜单间添加间距

image-20250722164104754

.sidebar-menu .menu-item {
  margin-bottom: 10px;
}

# 3、第三步:激活效果

image-20250722164455012

<div class="menu-item active">
  <div class="menu-item-title">
    <span class="iconfont icon-jiaoxuepingjia"></span>
    教学管理
  </div>
</div>
/* 当前菜单项被激活 */
.sidebar-menu .menu-item.active .menu-item-title {
  background-color: #f77080;
  background-image: url(./images/r-jiantou2.svg);
  color: #fff;
}
.sidebar-menu .menu-item.active .menu-item-title .iconfont {
  color: #fff;
}

# 4、第四步:创建二级菜单

image-20250722164939245

.sidebar-menu .menu-item.active .menu-item-title {
  background-color: #f77080;
  background-image: url(./images/r-jiantou2.svg);
  color: #fff;
}
.sidebar-menu .menu-item.active .menu-item-title .iconfont {
  color: #fff;
}
<div class="menu-item active">
  <div class="menu-item-title">
    <span class="iconfont icon-jiaoxuepingjia"></span>
    教学管理
  </div>
  <ul>
    <li><a href="#">班级管理</a></li>
    <li><a href="#">直播管理</a></li>
    <li><a href="#">课程管理</a></li>
    <li><a href="#">题库管理</a></li>
    <li><a href="#">分类标签</a></li>
  </ul>
</div>

# 5、第五步:二级菜单激活与未激活样式

image-20250722164925589

.sidebar-menu .menu-item {
  height: 40px;
  overflow: hidden;
}

.sidebar-menu .menu-item.active {
  height: 280px; /* 后面通过JS来计算 */
}

# 6、第六步:将所有菜单收缩

image-20250722165107641

去掉第一个 menu-item 元素身上的 class 属性值 acitve

# 7、第七步:JS 实现伸缩菜单

GIF2025-7-2217-10-38

  • 获取所有的 menu-item-title,然后绑定点击事件
  • 点击后,将其直接父元素添加 class="active" ,再点击则去掉 class='active'
  • 点击后,获取其兄弟元素 ul 的高度,然后来改变menu-item的高度,实现动画。
  • menu-item-title对应添加一个属性 flag 来记录,当前菜单的状态。 值为off为关闭,值为on为打开
  • 根据当前菜单的状态,来决定menu-item 的高度
const menuItemTitles = document.querySelectorAll(
  ".sidebar-menu .menu-item-title"
);

for (let i = 0; i < menuItemTitles.length; i++) {
  // 4.在当前元素身上添加一个属性,用来记录前当菜单的状态
  menuItemTitles[i].flag = "off"; // 默认刚开始菜单是关闭的
  menuItemTitles[i].addEventListener("click", function () {
    // 1、找到直接父元素,添加 class='acitve'
    this.parentNode.classList.toggle("active");
    // 5.判断,根据状态来做出改变
    if (this.flag == "off") {
      // 2、动态获取对应兄弟元素 ul的占位高
      const _height = this.nextElementSibling.offsetHeight;
      // 3、动态修改当前 menu-item的高度
      this.parentNode.style.height = _height + "px";
      this.flag = "on";
    } else {
      this.parentNode.style.height = 40 + "px";
      this.flag = "off";
    }
  });
}

# 8、第八步:实现窄屏幕响应式适配

如果在宽屏幕时,菜单是展开的,则小屏时,菜单也是要全部关闭的。

屏幕尺寸 效果
<=1400px 菜单只显示图标部分,并且所有菜单全部默认为收缩状态

需要通过 JS 来操作

  • 获取当前屏幕的尺寸(视口大小),如果视口宽度 <=1300,
    • 则将所有菜单 menu-item 的高度设为 30px ,
    • 同时将menu-item 身上的 class='active' 移除
    • 所有菜单的状态要记录为 off
// 获取当前屏幕的尺寸(视口大小),如果视口宽度 <=1300,
// 则将所有菜单 `menu-item` 的高度设为 30px ,
// 同时移除 `class='active'`

window.addEventListener("resize", function () {
  const clientWidth = window.innerWidth;
  if (clientWidth <= 1400) {
    // 遍历所有的 menu-item,将高度设为 30px,同时移除 `class='active'`
    for (let i = 0; i < menuItems.length; i++) {
      menuItems[i].style.height = "40px";
      menuItems[i].classList.remove("active");
      // 所有菜单的状态都要是off
      menuItems[i].children[0].flag = "off";
    }
  }
});

# 9、第九步:点击菜单图标后展开菜单效果

  • 在前面 menu-item-title的点击事件中,添加将菜单sidebar-menu宽度设为 260px,以实现点击对应菜单,展开整个侧边栏。
for (let i = 0; i < menuItemTitles.length; i++) {
    // 4.在当前元素身上添加一个属性,用来记录前当菜单的状态
    menuItemTitles[i].flag = "off"; // 默认刚开始菜单是关闭的
    menuItemTitles[i].addEventListener("click",
                                       function () {
        // 1、找到直接父元素,添加 class='acitve'
        this.parentNode.classList.toggle("active");

        // -----------------------------------
        // 将6、sidebar-menu的宽度改为以260px
        sidebarMenu.style.width = "260px";

  		// -----------------------------------
        // 以下省略部分css

    });
  • resize事件中,当屏宽小于 1400px 时,则还需要将 sidebar-menu 宽改为 75px 其它情况下 宽度为 260px
window.addEventListener("resize", function () {
  const clientWidth = window.innerWidth;
  if (clientWidth <= 1400) {
    // 省略部分代码,具体见前面..........
    //-------------------------------------
    // 将侧边栏宽改为 75px
    sidebarMenu.style.width = "75px";
  } else {
    //-------------------------------------
    // 将侧边栏宽改为 260px
    sidebarMenu.style.width = "260px";
  }
});
上次更新时间: 8/12/2025, 9:19:14 PM

大厂最新技术学习分享群

大厂最新技术学习分享群

微信扫一扫进群,获取资料

X