导航
px, %, em, rem, vw/vh
px
,结合 Media Query 进行阶梯式的适配;%
,按百分比自适应布局;em
,相对单位,相对于父元素的字体大小。rem
,也是相对单位,相对于根元素html。使用rem
,结合html
元素的font-size
来根据屏幕宽度适配;vw
、vh
,直接根据视口宽高适配。(viewport height / viewport width
).img { width: 60vw; height: 40vh }
px
。比如1px
线,4px
的圆角边框。rem
。em
。em
**会叠加计算。**在这个机制下太容易犯错了,因为你不知道这段css
指定的字号具体是多少。<!-- HTML -->
<span>
abc
<span>def</span>
abc
</span>
// CSS
span {font-size: 1.5em;}
实际效果:
先要搞清楚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;
}
}
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;
}
来源:https://zhuanlan.zhihu.com/p/340299974
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0"/>
<title></title>
<style type="text/css">
* {
margin: 0;
padding: 0;
}
#test {
width: 100%;
height:1px ;
margin-top: 50px;
background: black;
}
@media only screen and (-webkit-device-pixel-ratio:2) {
#test {
transform: scaleY(.5);
}
}
@media only screen and (-webkit-device-pixel-ratio:3) {
#test {
transform: scaleY(.333333333333333333);
}
}
</style>
</head>
<body>
<div id="test"></div>
</body>
</html>
/* 给 dpr 1.5 的设备设置 0.7 的缩放 */
@media (-webkit-min-device-pixel-ratio: 1.5), (min-device-pixel-ratio: 1.5)
.border1px
&::after
-webkit-transform: scaleY(.7)
transform: scaleY(.7)
/* 给 dpr 2.0 的设备设置 0.5 的缩放 */
@media (-webkit-min-device-pixel-ratio: 2), (min-device-pixel-ratio: 2)
.border1px
&::after
-webkit-transform: scaleY(.5)
transform: scaleY(.5)
/* 给需要1px下边框的元素添加一个伪元素,
使其宽100%;高为用户自定义 */
border1px($color)
position: relative
&:after
display: block
position: absolute
left: 0
bottom: 0
width: 100%
border-top: 1px solid $color
content: ' '
<!-- 1. 给需要添加1像素边框的元素设置一个类作为标识,让媒体查询能够识别 -->
<header class="border1px"></header>
<style lang="stylus" scoped>
header
width px2rem(750)
height px2rem(100)
border1px(black) /* 2. 通过border1px设置边框 */
background-color transparentify
</style>
来源:https://vue3js.cn/interview/css/less_12px.html
Chrome 中文版浏览器会默认设定页面的最小字号是12px,英文版没有限制
原由 Chrome 团队认为汉字小于12px就会增加识别难度
与网页语言无关,取决于用户在Chrome的设置里(chrome://settings/languages)把哪种语言设置为默认显示语言
浏览器默认设定页面的最小字号,用户可以前往 chrome://settings/fonts 根据需求更改
而我们在实际项目中,不能奢求用户更改浏览器设置
对于文本需要以更小的字号来显示,就需要用到一些小技巧
常见的解决方案有:
zoom
webkit-transform: scale()
webkit-text-size-adjust: none
zoom 的字面意思是“变焦”,可以改变页面上元素的尺寸,属于真实尺寸
其支持的值类型有:
使用 zoom 来”支持“ 12px 以下的字体
代码如下:
<style type="text/css">
.small-text1 {
font-size: 12px;
display: inline-block;
zoom: 0.8;
}
.small-text2 {
display: inline-block;
font-size: 12px;
}
</style>
<body>
<span class="small-text1">测试10px</span>
<span class="small-text2">测试12px</span>
</body>
效果如下:
需要注意的是,Zoom 并不是标准属性,需要考虑其兼容性
优点:
缺点:
针对 chrome 浏览器,加 webkit 前缀,用 transform:scale() 这个属性进行放缩
注意的是,使用 scale 属性只对可以定义宽高的元素生效,所以,下面代码中将 span 元素转为行内块元素
实现代码如下:
<style type="text/css">
.small-text1 {
font-size: 12px;
display: inline-block;
-webkit-transform:scale(0.8);
}
.small-text2 {
display: inline-block;
font-size: 12px;
}
</style>
<body>
<span class="small-text1">测试10px</span>
<span class="small-text2">测试12px</span>
</body>
效果如下:
优点:
缺点: