导航
px
, %
, em
, rem
, vw/vh
px
,结合 Media Query 进行阶梯式的适配%
,按百分比自适应布局em
,相对单位,相对于父元素的字体大小rem
,也是相对单位,相对于根元素 html
。使用rem
,结合 html
元素的 font-size
来根据屏幕宽度适配vw
、vh
,直接根据视口宽高适配。px
。比如 1px
线,4px
的圆角边框。rem
。em
。**em
会叠加计算。**在这个机制下太容易犯错了,因为你不知道这段 CSS 指定的字号具体是多少。
<!-- HTML -->
<span>
abc
<span>def</span>
abc
</span>
<!-- CSS -->
<style>
span { font-size: 1.5em; }
</style>
实际效果:
先要搞清楚 em
的计算原理,它是根据当前元素的字号按比例计算的。
外层 span
的字号是 16px
(浏览器默认值),所以 1.5em
之后是 24px
。由于字号是继承的,导致内层 span
的字号继承过来是 24px
,再经过 1.5em
之后就成了 36px
。
所以,就算要用 em
的话,尽量不要用在继承属性(font-size
)上,除非你真的清楚你在做什么!
如果从小到大判断,那么也从小到大书写
@media screen and (min-width: 640px) {}
@media screen and (min-width: 1024px) {}
@media screen and (min-width: 1280px) {}
如果从大到小判断,那么也从大到小书写
@media screen and (max-width: 1280px) {}
@media screen and (max-width: 1024px) {}
@media screen and (max-width: 640px) {}
媒体查询一般用在 PC 端,兼容移动端
那么就先考虑设计稿宽度,最后向下兼容:
.sw-conttainer {
padding-bottom: 120px;
@media (min-width: $sw-xs) {
padding-bottom: 40px;
}
@media (min-width: $sw-sm) {
padding-bottom: 60px;
}
@media (min-width: $sw-md) {
padding-bottom: 80px;
}
@media (min-width: $sw-lg) {
padding-bottom: 100px;
}
@media (min-width: $sw-xl) {
padding-bottom: 120px;
}
}
设备类型 | 断点范围(像素) | 适用场景 |
---|---|---|
手机(竖屏) | ≤ 576px |
小屏幕手机(默认移动端样式) |
手机(横屏) | 576px - 768px |
大屏手机或小尺寸平板 |
平板 | 768px - 992px |
iPad 等中等尺寸设备 |
桌面(小) | 992px - 1200px |
笔记本电脑或小尺寸显示器 |
桌面(大) | ≥ 1200px |
大屏显示器或电视 |
rem 是一个相对单位,相对的是根元素(html
)的字体大小(font-size
)。这样一来我们就可以通过 html 上的字体大小来控制页面上所有以 rem 为单位的元素尺寸。
思路:
window.innerWidth / 10
)rem份数 = 设计稿px / 每份有多少px值
例如在 vue 项目的 index.html 页中动态计算根元素字体大小
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,minimum-scale=1.0,user-scalable=no">
...
</head>
<body>
<noscript>
...
</noscript>
<div id="app"></div>
<script>
;(function(doc, win) {
const docEl = doc.documentElement
const resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize'
const recalc = () => {
let clientWidth = docEl.clientWidth;
clientWidth = clientWidth < 750 ? clientWidth : 750;
// 把屏幕宽度划分成10份,那么每一份的宽度就等于1rem,也就是 75px
docEl.style.fontSize = clientWidth / 10 + 'px'
}
if (!doc.addEventListener) return
win.addEventListener(resizeEvt, recalc, false)
doc.addEventListener('DOMContentLoaded', recalc, false)
recalc()
})(document, window)
</script>
</body>
</html>
然后利用 css 预处理器定义一个 mixin 函数(下方用的stylus),用来将设计稿上的 px 转为对应的 rem 值
计算公式为:
页面元素的 rem 值 = 设计稿元素值(px)/(屏幕宽度 / 划分的份数)
mixin.stylus
/* 把px转为rem */
/* 用设计稿px除以每一份rem的px,就能算出几个rem */
px2rem(designpx)
$rem = 750 / 10;
return (designpx / $rem)rem
最后在 css 中使用
某 vue 组件的 style 标签中
/* 375 设计稿上 100% 宽以及 50 高的导航条(iPhone6 的 dpr 为 2 ,所以 px 值得都乘以 2) */
header
width px2rem(750)
height px2rem(100)
思路:
html { font-size: 100px; }
,把100px当做因子1200px
宽,那么换算下来就是 { width: 12rem }
来源:https://juejin.cn/post/6844903923539509262
原理就是:把屏幕分成 100 份
举例:
假设设计稿尺寸是 750px,页面有一个按钮,按钮文字标注大小 28px,按钮高度标注为 48px,宽度为 120px,边框为 1px 不缩放。
<!DOCTYPE html>
<html
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
.button {
width: 16vw; /* 120/(750/100vw) */
font-size: 3.73vw; /* 28/(750/100vw) */
line-height: 6.4vw; /* 48/(750/100vw) */
border: 1px solid #000; /* 不需要缩放的部分用px */
text-align: center;
}
</style>
</head>
<body>
<div class="button">按钮</div>
</body>
</html>
在正式的项目里,我们也可以用SCSS,把换算交给预处理器
@function px2vw($px) {
@return $px * 100vw / 750;
/* 或者 */
@return $px / (750 / 100vw);
}
.button {
width: px2vw(120);
font-size: px2vw(28);
line-height: px2vw(48);
border: 1px solid #000;
text-align: center;
}