HTML5+CSS3(黑马程序员)——第四篇
目录
四、移动端适配
1、less使用方法(拓展)
1.1、概念
- 含义:Less是一个CSS预处理器,赋予CSS一定的逻辑性、计算能力,当保存less文件后,vscode将自动生成CSS文件,然后css文件就可以引入html网页使用。
- Less文件后缀是
.less - less文件内容依然是css语法内容,只是支持变量、运算、css嵌套写法,相当于是针对css的增强处理
- 浏览器不识别Less代码,当保存less文件后,vscode会自动生成css代码,需要网页引入css代码才能使用
- Less文件后缀是
- 下载插件:在VS Code中,必须需要下载Easy LESS插件,该插件可以在保存less文件后自动生成对应的css文件
1.2、注释
- 用法:
- 单行注释:
- 语法:
// 注释内容 - VS Code快捷键:
Ctrl + /
- 语法:
- 块注释:
- 语法:
/* 注释内容 */ - VS Code快捷键:
Shift + Alt + A
- 语法:
- 单行注释:
- 特殊说明:
.css文件中仅仅支持块注释,所以less文件中编写的单行注释无法在css文件中生成- 如果运算中出现多个单位,最终单位以第一个出现的为准,例如 width: 100px / 2rem,最终的单位是px
1.3、运算
1.3.1、概念
- 加法、减法、乘法 直接书写计算表达式即可
- 除法:
- 可以使用
/,但是需要使用小括号包裹,例如 :(15 / 3) - 也可以直接使用
./,其中在VS Code中会出现语法错误,所以一般用上面的方式
- 可以使用
1.3.2、代码示例
.box {
// 加法
width: 100 + 200px;
// 减法
width: 100 - 200px;
// 乘法
width: 100 * 2px;
// 除法
width: (100 / 2px);
width: 100 ./ 2px; // 在VSCode中会报错,不建议使用
}
1.4、变量
1.4.1、概念
- 作用:存储数据,方便使用和修改
- 语法:
- 定义变量:
@变量名: 变量值; - 使用变量:
@变量名
- 定义变量:
1.4.2、代码示例
@rootSize: 37.5rem;
@subjectColor: pink;
.box {
width: (100 / @rootSize);
background-color: @subjectColor;
}
1.5、嵌套
1.5.1、概念
- 作用:快速生成后代选择器
- 用法:父元素的css设置放在大括号中,那么子元素的css设置整体都放在父元素的大括号中,以此类推
1.5.2、代码示例

1.6、导入、导出
1.6.1、概念
- 作用:
- 导入:导入公共样式的less文件到其他less文件中
- 导出:将保存less文件后生成的css文件以特定文件名称导出到特定目录中
- 语法:
- 导入:
@import './base.less';:将base.less文件的内容进行导入。其中base.less是基础css文件,需要将base.less导入到其他less文件中@import './base';:将base.less文件的内容进行导入,其中.less后缀可以省略
- 导出:
- 写法:在less文件中第一行添加
// out: 存储CSS文件的URL路径 // out: ./index.css:将当前less文件导出到同级目录下,名称改为index.css// out: ./css/:将当前less文件导出到css目录下,css文件名称和less文件名称一致// out: false:禁止将当前less文件导出成css文件,例如base.less是基础css文件,需要导入到其他less文件中,不需要导出css文件
- 写法:在less文件中第一行添加
- 导入:
1.6.2、代码示例
1、导入:将base.less导入到index.less中

2、导出:禁止导出成css文件

3、导出:将index.less导出到css目录下,并且css文件名称还是index

2、移动端适配-概念解读
-
屏幕分辨率:水平和垂直方向的像素点数,单位是px
-
物理分辨率、逻辑分辨率:分辨率可以分为物理分辨率和逻辑分辨率,比如我自己的分辨率是1920*1080的,这是物理分辨率。但是由于我的屏幕是14英寸,确实有点小了,所以我将屏幕显示内容进行了缩放150%,这是逻辑分辨率。所以对于我的电脑来说,这样设置之后,分辨率变小了。编写代码看的是逻辑分辨率
-
常见手机型号—屏幕分辨率:

-
视口:显示HTML网页的尺寸,使用逻辑分辨率,其中代码
<meta name="viewport" content="width=device-width, initial-scale=1.0">中,width=device-width表示视口宽度=设备逻辑分辨率宽度,initial-scale=1.0表示缩放1倍(不进行缩放),这行代码在VS Code中写代码时会自动生成,不需要改动

-
二倍图:手机尺寸大小不一,现阶段设计稿参考iPhone6/7/8尺寸,设备宽度375px产出设计稿,那么二倍图设计稿尺寸是750px。
- 使用二倍图原因:保证图片在各种设备中都清晰展示。
- 如果判断2倍图:如果设计图宽度是750px,那就是二倍图,这时候需要调整设计图像素设置,调成375px的图,这样我们才能编写代码使用

3、移动端-适配方案
3.1、概念
- 适配方案:
- PC端:只支持宽度自适应,实现方式包括:百分比布局、Flex布局
- 移动端:宽高等比例缩放,实现方式包括:rem、vm
3.2、适配方式—rem
3.2.1、概念
- 原理:rem单位是相对单位,以HTML标签设置的字号大小(font-size属性值)为相对依据,然后计算得出结果,例如2rem等于2 * HTML标签的font-size属性值
3.2.2、如何设置HTML标签字号(font-size属性值)
3.2.2.1、概念
- 原理:根据设备逻辑分辨率大小进行设置,在rem目前的布局方案中,一般将网页分成10等份,HTML标签字号是视口宽度的十分之一。下图是根据视口宽度设置html标签字号的代码,但是这些写法很难兼容所有设备,因此我们需要借助阿里手机淘宝团队给出的一个js文件来统一设置html标签字号

3.2.2.2、如何使用手机淘宝的js文件设置html标签行号
作用: flexible.js是手机淘宝团队开发出来的一个用来适配移动端的js库。该js文件会设置html根节点标签设置font-size为设备逻辑分辨率的1/10,这样所有的子元素都会继承这个font-size,进而让每一个设置rem的地方都可以根据设备逻辑分辨率进行等比例缩放

使用方法:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>极速问诊页</title>
</head>
<body>
……
<!-- 该js为阿里手淘出品,根据逻辑分辨率设置html标签的font-size属性值,为设置rem提供依据 -->
<script src="./js/flexible.js"></script>
</body>
</html>
flexible.js:
(function flexible (window, document) {
var docEl = document.documentElement
var dpr = window.devicePixelRatio || 1
// adjust body font size
function setBodyFontSize () {
if (document.body) {
document.body.style.fontSize = (12 * dpr) + 'px'
}
else {
document.addEventListener('DOMContentLoaded', setBodyFontSize)
}
}
setBodyFontSize();
// set 1rem = viewWidth / 10
function setRemUnit () {
var rem = docEl.clientWidth / 10
docEl.style.fontSize = rem + 'px'
}
setRemUnit()
// reset rem unit on page resize
window.addEventListener('resize', setRemUnit)
window.addEventListener('pageshow', function (e) {
if (e.persisted) {
setRemUnit()
}
})
// detect 0.5px supports
if (dpr >= 2) {
var fakeBody = document.createElement('body')
var testElement = document.createElement('div')
testElement.style.border = '.5px solid transparent'
fakeBody.appendChild(testElement)
docEl.appendChild(fakeBody)
if (testElement.offsetHeight === 1) {
docEl.classList.add('hairlines')
}
docEl.removeChild(fakeBody)
}
}(window, document))
3.2.3、代码示例(功能演示代码,无法真正运行)
index.less:
// out: ../css/
@import './base.less';
// 定义变量
@rootSize: 37.5rem;
// 头部区域
.header {
display: flex;
justify-content: space-between;
align-items: center;
height: (44 / @rootSize);
padding: 0 (15 / @rootSize);
.back {
// 解决父级带来的幽灵字符问题
font-size: 0;
.icon-left {
font-size: (22 / @rootSize);
vertical-align: middle;
}
}
h3 {
font-size: (17 / @rootSize);
}
.record {
font-size: (15/ @rootSize);
color: #2CB5A5;
}
}
// 中间信息
.banner {
margin-top: (30.5 / @rootSize);
margin-bottom: (33.5 / @rootSize);
text-align: center;
img {
width: (240 / @rootSize);
height: (206 / @rootSize);
margin-bottom: (18 / @rootSize);
}
p {
font-size: (16 / @rootSize);
line-height: (25 / @rootSize);
strong {
color: #16C2A3;
}
}
}
// 底部信息
.bottom {
padding: 0 (15 / @rootSize);
li {
height: (78 / @rootSize);
margin-bottom: (15 / @rootSize);
padding: 0 (15 / @rootSize);
border: (0.5 /@rootSize) solid #EDEDED;
border-radius: (4 / @rootSize);
a {
display: flex;
align-items: center;
height: 100%;
.left img {
width: (40 / @rootSize);
height: (40 / @rootSize);
margin-right: (14 / @rootSize);
}
.middle {
flex: 1;
h4 {
color: #3C3E42;
font-size: (16 / @rootSize);
line-height: (24 / @rootSize);
margin-bottom: (4 / @rootSize);
}
p {
color: #848484;
font-size: (13 / @rootSize);
line-height: (20 / @rootSize);
}
}
.icon-right {
font-size: (22 / @rootSize);
color: #848484;
}
}
}
}
代码截图:

3.2.4、页面效果

3.3、适配方式—vw
3.3.1、概念
- vw也是一个相对单位,相对于视口的尺寸。支持使用vw(英文全称viewport width,其中1vw = 1 / 100视口宽度)或者vh(英文全称 viewport height,其中1vh = 1 / 100 视口高度)。
- 使用vw:在绘制页面的时候,UI设计工程师提供的都是iPhone6/7/8的设计图,所以我们调整设计图宽度为375px(如果是二倍图(750px),那就需要设置像素),假设使用vw单位,那么16 / 3.75vw(iphone6/7/8的宽度是375px,那么1 / 100 是3.75)代表16px,然后这个宽度就可以根据页面进行等比例改变了
- 拓展:在计算方面,可以这么理解,16 / 3.75vw相当于 ( 16 / 3.75 ) * ( 375px / 100 ),其中最终结果就是16px
- 使用vh:在绘制页面的时候,UI设计工程师提供的都是iPhone6/7/8的设计图,所以我们调整设计图宽度为375px(如果是二倍图(750px),那就需要设置像素),假设使用vh单位,那么16 / 6.67vh(iphone6/7/8的高度是667px,那么1 / 100 是6.67)代表16px,然后这个宽度就可以根据页面进行等比例改变了
- 综上所述:vw和vh不能一起使用,要么使用vw,要么使用vh,不然图片在等比例变化时会脱离原设计图的样子,一般使用vw就可以了
- 使用vw:在绘制页面的时候,UI设计工程师提供的都是iPhone6/7/8的设计图,所以我们调整设计图宽度为375px(如果是二倍图(750px),那就需要设置像素),假设使用vw单位,那么16 / 3.75vw(iphone6/7/8的宽度是375px,那么1 / 100 是3.75)代表16px,然后这个宽度就可以根据页面进行等比例改变了
- 对比rem实现方案:vw实现方案直接相对于视口宽度,更加简单好用。而rem方案相对于标签字号,并且需要使用手淘js文件计算html标签的根字号,感觉还是麻烦一点
3.3.2、代码示例(功能演示代码,无法真正运行)
index.less:
// out: ../css/
@import url(./base.less);
@vw: 3.75vw;
body {
background-color: #f9fafb;
font-size: (14 / @vw);
}
// 头部
.header {
display: flex;
justify-content: space-between;
align-items: center;
position: fixed;
left: 0;
top: 0;
z-index: 9999;
width: 100%;
height: (50 / @vw);
background-color: #fff;
.logo {
width: (235 / @vw);
height: 100%;
background: url(../assets/head.png) no-repeat left center / contain;
}
a {
padding: 0 (15 / @vw);
height: (30 / @vw);
margin-right: (15 / @vw);
text-align: center;
line-height: (30 / @vw);
font-size: (13 / @vw);
border-radius: (15 / @vw);
background-color: #ffe31b;
}
}
// 搜索栏
.search {
height: (32 / @vw);
margin: (60 / @vw) (15 / @vw) (10 / @vw) (15 / @vw);
border-radius: (16 / @vw);
background-color: #f2f4f5;
text-align: center;
line-height: (32 / @vw);
font-size: (14 / @vw);
color: #a1a4b3;
span {
font-size: (16 / @vw);
}
}
// 轮播图
.banner {
width: (345 / @vw);
height: (108 / @vw);
margin: 0 auto;
ul {
display: flex;
a {
display: block;
width: (345 / @vw);
height: (108 / @vw);
img {
width: 100%;
height: 100%;
object-fit: cover;
border-radius: (5 / @vw);
}
}
}
}
// 排行榜
.list {
margin: (20 / @vw) (15 / @vw) 0 (15 / @vw);
.content {
li {
display: flex;
align-items: top;
height: (105 / @vw);
margin-bottom: (16 / @vw);
.pic {
margin-right: (20 / @vw);
img {
width: (105 / @vw);
height: (105 / @vw);
border-radius: (10 / @vw);
object-fit: cover;
}
}
.txt {
dt a {
color: #333;
line-height: 1.8;
span {
vertical-align: (-1.5 / @vw);
}
}
dd a {
font-size: (12 / @vw);
color: #a1a4b3;
line-height: 1.8;
}
}
}
}
}
.title {
margin-bottom: (16 / @vw);
height: (26 / @vw);
display: flex;
justify-content: space-between;
align-items: center;
h4 {
font-size: (20 / @vw);
}
a {
font-size: (12 / @vw);
color: #a1a4b3;
line-height: 1;
span {
font-size: (16 / @vw);
vertical-align: (-1 / @vw);
}
}
}
// 推荐歌单
.recommand {
margin: 0 (15 / @vw);
.content ul {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
li {
margin-bottom: (16 / @vw);
a {
display: block;
width: (105 / @vw);
height: (143 / @vw);
.pic {
position: relative;
border-radius: (16 / @vw);
overflow: hidden;
img {
width: (105 / @vw);
height: (105 / @vw);
object-fit: cover;
}
.hotNum {
position: absolute;
left: 0;
bottom: 0;
width: (70 / @vw);
height: (28 / @vw);
background-color: rgba(0, 0, 0, 0.8);
color: #fff;
text-align: center;
line-height: (28 / @vw);
border-top-right-radius: (16 / @vw);
}
}
}
}
}
}
// 下载
.download {
display: flex;
align-items: center;
position: fixed;
bottom: (30 / @vw);
z-index: 9999;
width: (345 / @vw);
height: (45 / @vw);
margin: 0 (15 / @vw);
background-color: #fff;
border-radius: (22.5 / @vw);
padding: 0 (10 / @vw);
img {
width: (36 / @vw);
height: (36 / @vw);
margin-right: (10 / @vw);
}
p {
flex: 1;
}
span {
width: (27 / @vw);
height: (27 / @vw);
background-color: #f2f3f5;
border-radius: 50%;
font-size: (16 / @vw);
text-align: center;
line-height: (27 / @vw);
vertical-align: middle;
}
}
// 版权
.copyright {
display: flex;
flex-direction: column;
align-items: center;
margin: (40 / @vw) 0 (108 / @vw);
.name {
display: flex;
align-items: flex-end;
margin-bottom: (10 / @vw);
img {
width: (22 / @vw);
height: (22 / @vw);
vertical-align: middle;
}
}
.agreement, .version, .comInto {
color: #a1a4b3;
font-size: (11 / @vw);
line-height: 1.8;
}
.comInto span {
font-size: (11 / @vw);
vertical-align: middle;
}
}
代码截图:

3.3.3、页面效果

五、响应式网页
1、媒体查询
1.1、概念
-
含义:根据视口宽高不同,让不同的CSS生效
-
完整写法:
1、语法 @media 逻辑操作符 媒体类型 逻辑操作符 (媒体特性) { css语法 } 2、逻辑操作符(非必填) and、only、not 3、媒体类型(默认值:all,非必填) 作用:用了区分设备类型,如屏幕设备(screen)、打印设备(print)、阅读器(speech)、不区分类型(all,包括以上三种,这也是默认值) 3、媒体特性 作用:描述媒体类型的具体特征,例如当前屏幕的宽高、分辨率、横屏或者竖屏等,详细属性值请看下图
-
常用写法:
@media (媒体特性) { css语法 } // 例如:当屏幕尺寸小于等于1200px的情况才生效 @media (max-width: 1200px) { css语法 } -
优先级说明:如果多个媒体查询
@media都符合要求,当出现css语法重复的时候,以最后一个媒体查询中配置的css效果为准 -
使用注意事项:按照上面的优先级说明可知,当需要设置多个媒体查询效果时,,如果从小尺寸往大尺寸写css效果,那就使用
min-width。反之使用max-width,示例如下:

-
编写css代码支持情况:不仅支持直接使用@media,然后在里面直接编写css代码。也支持引入css文件的方式,如下图所示

1.2、@media属性直接设置css—效果示例
1.2.1、代码示例
<!DOCTYPE html>
<html lang="en">
<head>
<!-- 表头 -->
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>你好,春天~</title>
<style>
/* 当不符合媒体查询情况时生效 */
body {
background-color: gray;
}
/* 当屏幕宽度 >= 768px时生效 */
@media (min-width: 768px) {
body {
background-color: goldenrod;
}
}
/* 当屏幕宽度 >= 992px时生效 */
@media (min-width: 992px) {
body {
background-color: orangered;
}
}
/* 当屏幕宽度 >= 1200px时生效 */
@media (min-width: 1200px) {
body {
background-color: pink;
}
}
</style>
</head>
<body>
</body>
</html>
1.2.2、页面效果

1.3、link标签引入css文件支持媒体查询——效果示例
1.3.1、代码示例
index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<!-- 表头 -->
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>你好,春天~</title>
<link rel="stylesheet" href="./css/default.css">
<link rel="stylesheet" media="(min-width: 768px)" href="./css/768-valid.css">
<link rel="stylesheet" media="(min-width: 992px)" href="./css/992-valid.css">
<link rel="stylesheet" media="(min-width: 1200px)" href="./css/1200-valid.css">
</head>
<body>
</body>
</html>
default.css:
body {
background-color: gray;
}
768-valid.css:
body {
background-color: goldenrod;
}
992-valid.css:
body {
background-color: orangered;
}
1200-valid.css:
body {
background-color: pink;
}
1.3.2、页面效果

六、教程案例
1、淘宝轮播图-html+css版本
1.1、代码示例
<!DOCTYPE html>
<html lang="en">
<head>
<!-- 表头 -->
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>你好,春天~</title>
<link rel="stylesheet" href="./iconfont/iconfont.css">
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
/* 清除 a 标签所有默认样式 */
a {
/* 1. 去除下划线(核心) */
text-decoration: none;
/* 2. 清除默认颜色(继承父元素颜色) */
color: inherit;
/* 3. 清除点击后的高亮边框(部分浏览器) */
outline: none;
/* 4. 清除点击时的背景高亮(移动端) */
-webkit-tap-highlight-color: transparent;
}
/* 可选:清除 visited(访问后)状态的默认紫色 */
a:visited {
color: inherit;
}
li {
list-style: none;
}
.banner {
position: relative;
width: 556px;
height: 276px;
margin: 50px auto;
overflow: hidden;
}
.banner ul {
display: flex;
}
.banner ul li img {
width: 556px;
border-radius: 10px;
vertical-align: middle;
}
.banner .prev,
.banner .next {
display: none;
position: absolute;
width: 20px;
height: 30px;
top: 50%;
transform: translateY(-50%);
background-color: rgba(0, 0, 0, 0.3);
border-radius: 0 15px 15px 0;
color: #fff;
font-size: 10px;
line-height: 30px;
text-align: center;
vertical-align: middle;
}
.banner .next {
right: 0;
border-radius: 15px 0 0 15px;
}
.banner:hover .prev,
.banner:hover .next {
display: block;
}
.banner ol {
position: absolute;
left: 50%;
bottom: 20px;
transform: translateX(-50%);
display: flex;
height: 13px;
align-items: center;
border-radius: 10px;
background-color: rgba(0, 0, 0, 0.1);
}
.banner ol li {
width: 8px;
height: 8px;
background-color: #fff;
border-radius: 4px;
margin: 3px;
cursor: pointer;
}
.banner ol li.active {
background-color: #ff5000;
}
</style>
</head>
<body>
<div class="banner">
<!-- 轮播图 -->
<ul>
<li>
<a href="#">
<img src="https://cdn.pinduoduo.com/upload/official_website/c90fe04a-27dd-4e66-9a41-4de27e5c19f6.png" alt="">
</a>
</li>
<li>
<a href="#">
<img src="https://cdn.pinduoduo.com/upload/official_website/c90fe04a-27dd-4e66-9a41-4de27e5c19f6.png" alt="">
</a>
</li>
<li>
<a href="#">
<img src="https://cdn.pinduoduo.com/upload/official_website/c90fe04a-27dd-4e66-9a41-4de27e5c19f6.png" alt="">
</a>
</li>
</ul>
<!-- 箭头 -->
<a href="#" class="prev">
<span><</span>
</a>
<a href="#" class="next">
<span>></span>
</a>
<!-- 圆点 -->
<ol>
<li></li>
<li class="active"></li>
<li></li>
</ol>
</div>
</body>
</html>
1.2、页面效果

七、VS Code用法
1、Emmet缩写
说明: 当缩写编写完毕后,点击回车按键,即可生成完整结构
1.1、HTML
- 类选择器
- 写法:标签名.类名
- 示例:
div.box - 效果:
<div class="box"></div>
- id选择器
- 写法:标签名#id名
- 示例:
div#box - 效果:
<div id="box"></div>
- 同级标签:
- 写法:标签名1+标签名2
- 示例:
div+p - 效果:
<div></div><p></p>
- 父子级标签:
- 写法:标签名>子标签名
- 示例:div>p
- 效果:
<div><p></p></div>
- 多个相同标签:
- 写法:标签名*数量
- 示例:
div*2 - 效果:
<div></div><div></div>
- 携带内容的标签:
- 写法:标签名{标签内容}
- 示例:
div{你好} - 效果:
<div>你好</div>
1.2、CSS
- 说明:大多数简写方式为属性单词的首字母
- 示例1:
w100,代表:width: 100px; - 示例2:
bgc,代表:background-color: #ffff; - 示例3:
w100+h100,代表:width:100px; height:100px;
2、快捷键
- Ctrl + Enter:在光标下方插入新行,无论光标是否在行尾
- 复制行:按下 Shift + Alt + 下箭头(向下复制)或 Shift + Alt + 上箭头(向上复制)
- 删除当前行:Ctrl+Shift+K
- 代码格式化:Shift+Alt+F
八、CSS单位使用介绍
1、绝对单位(Absolute Units)
绝对单位是固定的物理长度,不会因设备、字体、视口大小而改变。但在屏幕上,由于设备像素密度不同,实际显示的物理尺寸可能略有差异。
| 单位 | 名称 | 定义 | 换算关系 | 使用场景 | 注意事项 |
|---|---|---|---|---|---|
px | 像素 | 设备屏幕上的一个点。CSS 规范规定 1px 为 1/96 英寸。 | 1in = 96px | 屏幕显示首选:边框、阴影、小图标、定位偏移 | 在高分辨率屏幕(Retina)上,1px 可能对应多个物理像素,但布局逻辑不变 |
pt | 点 | 传统印刷单位,1pt = 1/72 英寸 | 1pt = 1/72in ≈ 0.3528mm | 打印样式:字体大小、上下边距 | 屏幕显示时,不同系统映射不同,通常 1pt = 1.333px(基于 96dpi) |
pc | 派卡 | 印刷单位 | 1pc = 12pt = 1/6in | 极少使用,传统排版 | 可简单视为 12pt |
cm | 厘米 | 物理厘米 | 1cm = 1/2.54in | 打印样式,控制实际尺寸 | 屏幕显示误差大,不推荐 |
mm | 毫米 | 物理毫米 | 1mm = 0.1cm | 打印样式 | 同 cm |
in | 英寸 | 物理英寸 | 1in = 2.54cm = 96px(参考值) | 打印样式 | 同 cm |
📌 总结:屏幕用
px,打印用pt或cm。绝对单位在响应式设计中基本不用于布局。
2、相对单位(Relative Units)
相对单位依赖于另一个基准值,分为三类:字体相对单位(相对于字号的)、视口相对单位(相对于视口尺寸的)、百分比(相对于父元素或自身属性的)。
2.1、字体相对单位(Font-relative Units)
它们基于 字体度量 或 基准字号 计算。
| 单位 | 定义 | 参照基准 | 计算示例 | 特点 / 注意事项 | 典型应用 |
|---|---|---|---|---|---|
em | 相对单位,相对于当前元素的 font-size | 当前元素的 font-size | 父元素 font-size: 20px,子元素 font-size: 0.8em → 子元素字号 16px;子元素 width: 10em → 宽度 160px | 嵌套传递:子元素再用 em 会继续相对于新字号;属性如 margin 使用 em 时,参照的是当前元素的字号 | 组件内与字号相关的间距(按钮内边距、图标尺寸) |
rem | root em,相对于根元素的 font-size | 根元素 <html> 的 font-size | 根字号 16px,1.5rem = 24px;根字号改为 20px → 自动变为 30px | 不受父元素影响,适合全局控制; 媒体查询时只需修改根字号即可实现整体缩放 | 大多数元素的尺寸、间距(最推荐用于响应式) |
ex | 相对于当前字体的 x-height(小写字母 x 的高度) | 当前字体的 x-height | 一般约等于 0.5em,但依赖于字体 | 不同字体差异大,难以预判;很少单独使用 | 某些垂直对齐微调,例如让图标与文字基线对齐 |
ch | 相对于当前字体中 数字 0 的宽度(即字符“0”的 advance measure) | 当前字体的“0”宽度 | 等宽字体中:20ch 大约是 20 个英文字符的宽度;非等宽字体,每个字符宽度不同 | 对于等宽字体(如 monospace)预测性好;对于比例字体,实际宽度仍可变 | 控制文本列宽(如密码框、代码块),使其大约容纳一定数量的字符 |
ic | 相对单位(较新)。相对于当前字体中 表意文字(CJK 水字) 的 advance measure | 中日韩字体中“水”字(或全角字符)的宽度 | 一个全角字符宽度 = 1ic;常用于亚洲文字排版 | 与 ch 类似,但针对全角字符;兼容性较低 | 中文、日文、韩文内容容器宽度 |
🔍 em 和 rem 深度对比:
-
em嵌套陷阱:/* 根字号 16px */ .parent { font-size: 1.5em; } /* =24px */ .child { font-size: 1.5em; } /* =36px(相对于父节点 24px) */解决方案:全局用
rem,仅在需要相对自身字号时用em(如按钮 padding)。 -
font-size中使用em/rem的区别:html { font-size: 16px; } .box { font-size: 1.25rem; } /* 20px,固定 */ .box span { font-size: 0.8em; } /* 16px,相对于 .box 的 20px */
2.2、视口相对单位(Viewport-relative Units)
视口指浏览器可视区域(不包括工具栏、滚动条)。这些单位适合全屏布局、响应式字体。
| 单位 | 定义 | 基准 | 计算方式 | 场景 | 注意事项 |
|---|---|---|---|---|---|
vw | 视口宽度的 1% | 浏览器视口宽度 | 若视口宽 1000px,1vw = 10px | 全宽容器 (width: 100vw);响应式标题 (font-size: 5vw) | 包含滚动条宽度,可能导致水平溢出(100vw 比父容器宽) |
vh | 视口高度的 1% | 浏览器视口高度 | 视口高 800px,1vh = 8px | 全高容器 (height: 100vh);弹窗 | 移动端地址栏出现/消失时会改变 100vh 的实际高度 |
vmin | vw 和 vh 中较小的那个 | 取 min(vw, vh) | 竖屏手机:100vmin = 100vw(因为宽较小) | 保持元素在横竖屏下比例一致(例如始终正方形) | 需要稳定的比例时好用 |
vmax | vw 和 vh 中较大的那个 | 取 max(vw, vh) | 横屏时 100vmax = 100vh | 装饰元素,全屏背景 | 使用较少 |
⚠️ 移动端 vh 问题及新解决方案:
- 传统
100vh在移动浏览器中,地址栏和工具栏会导致可视区域高度变化,100vh始终等于最大可能高度(地址栏收起时),而非当前可见高度。这会导致元素被遮挡或底部留白。 - 新视口单位(兼容性逐渐提升):
svh(Small Viewport Height):小视口高度——地址栏展开时的最小可视高度。lvh(Large Viewport Height):大视口高度——地址栏收起时的最大可视高度。dvh(Dynamic Viewport Height):动态视口高度——随地址栏变化而变化(适合弹窗)。- 同样有
svw/lvw/dvw对应宽度。
- 建议:对关键全屏元素,可以使用
min-height: 100svh或height: 100dvh。
💡 视口单位与 rem 结合:响应式字体
html {
font-size: clamp(16px, 4vw, 24px);
}
可实现字号在 16px~24px 之间随视口宽度变化。
2.3、百分比单位(%)
百分比的行为高度依赖于具体 CSS 属性,必须分情况记忆。
2.3.1、盒模型尺寸属性
| 属性 | 参照基准 | 详细说明 | 示例 |
|---|---|---|---|
width、max-width、min-width | 父元素的 内容宽度(content width) | 百分比相对于父元素的 width(不包括 padding/border) | 父元素 width: 800px; padding: 20px;子元素 width: 50% → 400px |
height、max-height、min-height | 父元素的 内容高度 | 父元素必须有明确的高度,否则百分比无效 ( height: auto 时,子元素 height: 50% 不生效) | 解决方法:父元素 height: 100vh 或固定像素 |
padding(上下左右) | 父元素的宽度 | 即使 padding-top 也参照父元素宽度,不是高度 | 常用于实现固定宽高比(如正方形:padding: 50% 0) |
margin(上下左右) | 父元素的宽度 | 同样是参照父元素宽度(经典设计) | 有时会让垂直边距意外很大 |
🔍 宽度百分比的特殊场景:
- 如果父元素是
inline-block或浮动,它的宽度可能由内容撑开,此时子元素百分比参照父元素的实际宽度。 - 绝对定位元素:
width: 50%参照最近的非static定位祖先的内容宽度。如果祖先没有设置宽度,则参照祖先的父级直到视口。
🔍 高度百分比的生效条件:
- 父元素有固定的
height(如100vh、500px、10em) - 父元素使用绝对定位且高度由其他方式确定
- 父元素的
height为百分比,那么它的父级也必须有一个明确的链直到视口(例如html, body { height: 100%; })
2.3.2、字体与行高
| 属性 | 参照基准 | 计算方式 | 注意 |
|---|---|---|---|
font-size: 150% | 父元素的 font-size | 父字号 20px → 子字号 30px | 效果等同于 1.5em |
line-height: 150% | 当前元素的 font-size | 当前字号 20px → 行高 30px | 继承时:子元素继承计算后的值(如 30px),如果子元素字号不同,行高可能偏离预期。最好用无单位的 line-height: 1.5(相对于当前字号) |
2.3.3、定位偏移(top、right、bottom、left)
| 定位模式 | 参照基准 | 示例 |
|---|---|---|
position: relative | 元素自身的尺寸(高度/宽度) | 自身高度 100px,top: 20% → 向下移动 20px |
position: absolute | 最近的非 static 定位祖先(relative/absolute/fixed/sticky)的对应尺寸 | 祖先高度 500px,top: 10% → 50px |
position: fixed | 视口的尺寸 | left: 10% → 视口宽度的 10% |
position: sticky | 同 relative(在偏移前) | 很少用百分比 |
2.3.4、背景位置 background-position
- 参照:背景图片区域大小减去背景图片自身大小的差值。
- 例如:
background-position: 25% 50%表示图片左边距与区域左边距的差值为区域宽度减去图片宽度的 25%。 - 通常理解:
0% 0%左上角,100% 100%右下角。
2.3.5、变换 transform: translate() / scale() / transform-origin
translateX(50%):相对于元素自身的宽度(包括 border-box?实际是边界盒尺寸)。translateY(50%):相对于自身高度。transform-origin: 50% 50%:相对于元素自身的宽/高(默认是中心)。
经典居中技巧:
.center {
position: absolute;
top: 50%; /* 父容器高度的 50% */
left: 50%; /* 父容器宽度的 50% */
transform: translate(-50%, -50%); /* 自身宽高的一半 */
}
2.3.6、边框圆角 border-radius
- 水平方向百分比:参照元素盒子的宽度。
- 垂直方向百分比:参照元素盒子的高度。
- 例如
border-radius: 50%→ 椭圆,若盒子是正方形就是圆。
2.3.7、Flex 和 Grid 布局
Flex 容器中:
flex-basis: 50%:参照父容器主轴方向的尺寸(若主轴为 row,则参照父容器宽度)。- 子项的
width/height百分比仍然参照父容器内容区。
Grid 布局中:
grid-template-columns: 50% 25% 25%:参照网格容器的内容宽度。- 网格项内部的百分比参照该网格项自己的所在网格区域尺寸(由网格轨道决定)。
2.3.8、其他属性的百分比
| 属性 | 参照基准 | 说明 |
|---|---|---|
text-indent | 父元素的宽度 | 首行缩进相比父元素宽度 |
vertical-align | 当前元素的 line-height | 例如 vertical-align: 20% 按行高比例上移/下移 |
object-position | 类似 background-position | 用于 <video>、<img> 的裁切定位 |
clip-path 中的百分比 | 参考元素自身的边框盒 | 例如 clip-path: polygon(50% 0, ...) |
2.4、其他较新的相对单位
cqw、cqh、cqi、cqb、cqmin、cqmax:容器查询单位(Container Query Units)。参照查询容器的尺寸(而非视口或父元素)。cqi:内联轴尺寸的 1%(通常是宽度)cqb:块轴尺寸的 1%(通常是高度)- 适用于组件层级响应式(容器尺寸改变时自动适配)。
lvh/dvh等:已在前文视口单位说明。
3、单位选择完整指南
3.1、框架性原则
- 字体大小:根字号固定用
px或%(兼容性),然后用rem定义各级标题和正文。移动端可用clamp()配合vw实现 fluid typography。 - 盒模型尺寸:宽高用
rem(固定比例)或%(父容器占比);边距(margin/padding):- 与字体相关的内边距用
em(如按钮)。 - 与父容器比例相关的用
%。 - 全局间距用
rem。
- 与字体相关的内边距用
- 全屏/视口填充:
100vh/100dvh/100svh根据兼容性选择。100vw注意滚动条。 - 边框与细节:
px保持不变。 - 居中与变形:定位偏移用
%配合transform: translate(%)。
3.2、典型场景示例
/* 基础设置 */
html {
font-size: 16px;
/* 配合视口缩放(可选) */
/* font-size: clamp(14px, 2vw, 24px); */
}
/* 组件:卡片 */
.card {
width: 80%; /* 相对于父容器宽度 */
max-width: 1200px;
margin: 2rem auto; /* 全局间距,不影响内部字号 */
padding: 1.5rem; /* rem 保持统一 */
border: 1px solid #ccc;
}
.card h2 {
font-size: 1.5rem; /* 相对根字号 */
margin-bottom: 0.5em; /* 相对当前字号 */
}
/* 全屏弹窗 */
.modal {
position: fixed;
top: 10vh; /* 相对视口高度 */
left: 5vw;
width: 90vw; /* 相对视口宽度 */
max-height: 80dvh; /* 动态视口高度(现代浏览器) */
overflow-y: auto;
}
/* 正方形占位(图片占位) */
.square {
width: 100%;
padding-top: 100%; /* 参照父宽度,形成正方形 */
background: #eee;
}
4、重点知识对比表
| 对比项目 | em | rem | % (宽度) | vw | vh |
|---|---|---|---|---|---|
| 参照对象 | 当前元素字号 | 根元素字号 | 父元素宽度 | 视口宽度 | 视口高度 |
| 级联影响 | 会(嵌套放大) | 不会 | 会(继承父的宽%可能失效) | 不会 | 不会 |
| 典型用途 | 组件内间距 | 全局布局 | 响应式比例 | 全宽/流体字 | 全高容器 |
| 移动端问题 | 无 | 无 | 无 | 滚动条溢出 | 地址栏改变 |
| 对比项目 | line-height: 150% | line-height: 1.5 |
|---|---|---|
| 计算时机 | 计算当前元素的具体像素值并继承 | 继承时重新计算(基于继承元素的字体) |
| 子元素影响 | 子元素继承父级计算后的固定值 | 子元素继承 1.5,并基于自己的字号重新计算 |
| 推荐性 | 不推荐 | ✅ 推荐 |
5、常见问题与排查
5.1、height: 100% 不生效怎么办?
- 确认父元素高度是否设置(
px、vh、%但需要一直追溯到html)。 - 给
html, body { height: 100%; }。 - 使用
min-height: 100vh或min-height: 100dvh。 - 使用绝对定位,然后
top: 0; bottom: 0;(不依赖百分比高度)。
5.2、width: 100% 和 width: 100vw 有何区别?
100%相对于父元素内容宽度,受父元素padding、border影响(如果父元素是box-sizing: content-box)。100vw相对于视口宽度,通常包含滚动条宽度(如果有纵向滚动条)因而可能超出html宽度,导致水平溢出。
5.3、transform: translate(-50%, -50%) 为什么能居中?
因为 top: 50% 参照父元素高度,把元素左上角放在父中心;translate(-50%, -50%) 将元素向左向上移动自身宽高的一半,使得中心点对齐。
5.4、margin 和 padding 的百分比为什么参照宽度而不是高度?
CSS 规范设计如此,主要保证水平和垂直方向的相对一致性,以及实现固定宽高比的技巧。
更多推荐
所有评论(0)