本文分享不使用第三方类库,html前端原生就支持的自适应屏幕方法。首先要知道开发常用和自适应要用到的可视化大小单位和属性
| 单位 | 类型 | 含义 |
|---|---|---|
| px | 数值单位 | 像素,这是最基础的静态页面常用的单位 |
| % | 数值单位 | 百分比,使得元素宽高都可以基于父元素大小去自适应,但只适用于统一排版等布局类大元素,无法做的灵活控制页面上所有的所有元素 |
| vw / vh | 数值单位 | 可视化百分比,也就是浏览器当前可视化的窗口大小,它比 % 好一点,但也好不到哪里去,通常用来撑开元素初始状态的宽高 |
| max-width / min-width | css属性 | 最大宽和最大高,它只是一个上限,不会去主动撑开元素的占位 |
| rem / em | 数值单位 | r 本意是超元素,在页面中指的是 html 这个标签,em 是父元素的字号大小,同理 rem 就是在当前页面任何地方获取到html标签的字号大小 |
| clamp(最小值,首选值,最大值) | css函数 | 在同一类型数据的三个值中返回一个结果,最小值必须小于等于最大值,首选值应在最值范围内 |
| calc(表达式) | css函数 | 提供一个数学公式计算出对应的大小,但是它和clamp一样,参与公式计算的数据有同种类的要求 |
要强调一点,calc 函数它支持 加减乘除,四种计算表达式,但是有要求。加减法时,如果符号两边是同单位、同类型数据,则正常返回同单位、同类型的结果,例如 calc(100px - 50px) = 150px ;如果符号两边是不同单位、同类型数据,则返回统一基准单位的结果,比如 calc(100vw - 50px) = vw为200px时返回150px,其他同类型数据需要各位读者自己测一下 ;如果符号两边是不同类型的数据,则表达式失效,不同浏览器的处理方式会不一样,多数是元素崩塌或者是默认100%。乘除法时,要求符号两边至少有一个是纯数字,且除法时纯数字需要做被除数,如果不满足和加减法时一样表达式失效,返回值的单位同表达式中有单位数值,如果两个数值都是无单位的,则同样返回纯数字。如果你要写二个数值以上的表达式,一定要注意这些,灵活用括号分割。clamp函数 三个参数必须是同类型数据,可以不是同单位。这里说的同类型是指要不都是长度(vw、px、em、%等),要不就都是时间(s、ms等),同单位是指要不都是 px ,要不都是 vw
还要知道弹性盒子的用法,因为在自适应页面开发中基本都是用弹性盒子来占位,前端常常会看到如下的样式
css
.container {
display: flex;
flex-wrap: wrap; /* 允许换行!需要合理的配合宽高去实现 */
}
.item {
flex: 0 0 280px; /* 每个卡片不想缩小,也不想长大,固定 280px 宽 */
}
flex属性它的三个参数,从左到右依次是 flex-grow 表示剩余空间弹性盒子的子元素是否参与均分默认 0 不参与均分 ; flex-shrink 表示弹性盒子空间不够时子元素是否参与缩小自己让大家能够放的下,默认 1 表示会缩小 ; flex-basis 表示子元素基准大小。
flex: 1 等价于 flex: 1 1 0% 意思是 "有多少剩的分多少,不够了一起缩小贡献出需要的空间"
flex: none 等价于 flex: 0 0 auto 意思是 "我就按我自己内部元素撑起来的宽高来,别动我"
flex: 0 0 300px 意思是 "给我固定 300px,不增不减"
有了上面的铺垫,就可以看懂自适应页面的开发原理了。首先是自适应最普遍,也是最常用的方法,将前端开发时的设计稿它的宽高和可视窗口相除,得到一个矢量缩放比例的 css 变量
css
:root {
/*基于宽为1920px,高为1080px的设计稿,计算一个宽度的缩放倍率。正常来讲宽、高、文字都有对应的一个比例,具体的计算逻辑按照实际需求来即可 */
--scale-wi: calc(100vw / 1920);
--scale-he: calc(100vh / 1080);
}
#card {
/*让一个元素从设计稿中的,320px 宽、200px 高 自适应变化。使用的原则遵循 x 轴上的属性用高的缩放比例,y 轴上的用宽的缩放比例*/
width: calc(320 * var(--scale-wi) );
height : calc(200 * var(--scale-he) );
background-color: aquamarine;
}
对于页面上的文字来讲,通常不会有超过20px的自适应变化需求,因此通常是采用超元素字号的倍率
css
html{
font-size: 15px;
}
h1 {
/* 让一级标题,最小1.5倍 html 字号大小,最大 3 倍 rem,中间根据视口宽度动态变化 */
font-size: clamp(1.5rem, 1rem + 2vw, 3rem);
}
当然要是不满足需求,字号也可以定义一个缩放比例,不过效果和 rem 差不多,毕竟字号的 px 值一般情况下跨度很小的
css
:root {
--scale-fs: calc(20px / 15);
}
h1 {
font-size: clamp( calc( 15 * var( --scale-fs ) ) , calc( 20 * var( --scale-fs ) ), calc( 25 * var( --scale-fs ) ) );
}
也可以让元素参考自身的宽高等比例去控制,不过通常只在特定场景使用
css
.hero-image {
width: 100%;
aspect-ratio: 16 / 9; /* 高度自动根据宽度计算,始终 16 :9 */
object-fit: cover; /* 图片不变形,多余部分裁剪 */
}