HTML/CSS - 等比例布局 - em、rem、vh、vm、浏览器设备仿真默认宽度、fontSize计算

343 阅读4分钟

px em rem 分别是什么

问题痛点

对于响应式布局来说,其目的主要是希望能够一套代码同时兼容PC、移动端页面,但这样会有个问题,就是移动端的代码对于PC端来说就是冗余的,因此,响应式布局一般适合于企业管网等比较简单的网站。如果想设计一套专门只用于移动端的页面,使用px布局的话,就会很难适应于不同分辨率的页面,大一点的设备显示的就会跟小一点的设备显示的相差甚远,甚至界面混乱,那么如何解决这个问题,就可以使用em和rem布局。

概念解释

  • px:固定单位
  • em:相对单位,相对于父元素的字体大小,如果父元素为16px,1em就是16px
  • rem:相对单位,相对于根元素(HTML)的字体大小

代码示例

<!DOCTYPE html>
<html lang="zh-CN">
    <head>
        <meta charset="utf-8" />
        <title>em - CSS手册 - API参考文档</title>
        <style>
            body { font-size: 14px; }
            h1 { font-size: 16px; }
            .size1 p { font-size: 1em; }
            .size2 p { font-size: 2em; }
        </style>
    </head>
    <body>
        <h1>假定当前默认字体尺寸是14px,n em即为14px字体尺寸的n倍:</h1>
        <ul>
            <li class="size1">
                <strong>1em</strong>:
                <p>1em大小的文字</p>
            </li>
            <li class="size2">
                <strong>2em</strong>:
                <p>2em大小的文字</p>
            </li>
        </ul>
    </body>
</html>

image.png

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="utf-8" />
    <title>rem - CSS手册 - API参考文档</title>
    <style>
        html,
        h1 {
            font-size: 12px;
        }
        p {
            font-size: 2rem;
        }
    </style>
</head>
<body>
    <h1>下面的文字将是html定义的字体大小的2倍:</h1>
    <p>我是html定义的12px的2倍,字体大小为24px</p>
</body>
</html>

image.png

font-size 计算

需求场景

不同设备会有不同的页面宽度,如果使用固定的一个值,则只能适应一个页面,而不能在页面宽度变化的时候,灵活动态地填充页面,在移动端页面问题更为突出,例如,设计稿是基于iPhone6页面宽度设计的,通过ps量取出来750px,根据设备像素比换算为css为375px,此时如果width直接写为375px在iphone6上则完美显示,但若换成iPhone6plus,则页面就会因为屏幕变宽,出现一块空白

关键代码

  1. 基准device-width为375px;基准font-size设置为100px
html{ font-size:100px; }
section{ width:3.75rem; } /*width根据基准font-size而变化*/
/* 实现css一个width值,适配所有移动端界面宽度 */
document.documentElement.style.fontSize = 
document.documentElement.clientWidth / 375 * 100 + "px";
  1. 基准device-width为375px;基准font-size不设置(默认为16px)
section{ width:23.4375rem; } /*width根据基准font-size而变化*/
/* 实现css一个width值,适配所有移动端界面宽度 */
document.documentElement.style.fontSize = 
document.documentElement。clientWidth / 375 * 16 + "px";

示例代码(详细解释)

rem布局-移动端屏幕宽度自适应.gif

<!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">
    <title>Document</title>
    <style>
        html,body{
            height: 100%;
        }
        html{
            font-size: 100px; /* 基准fontsize */
        }
        section{
            width: 3.75rem; /* 3.75*100(基准font-size是375px,刚好能够适配iphone6等设备) */
            height: 20%;
            background-color: plum;
        }
        *{
            margin: 0;
            padding: 0;
        }
    </style>
    <script>
        /**
         * 上述css注释了如何适配iphone6等css宽度为375px的设备,
         * 但如果是其他分辨率不同的设备,比如iphone6plus的414px屏幕宽度,
         * 就需要把原有的width:3.75rem;换算成为4.14rem,而这样还是在手动计算,效率并不高,
         * 因此,可以借助下面的js属性换算,将iphone6的375px作为设备的基准css宽度和根元素的font-size:100px;作为基准font-size值,进行换算,得出html的font-size,这样一来就可以实现动态更改根元素的font-size值,而不用手动修改原有的width:3.75rem
         * 具体公式:
             font-size = 当前的设备的CSS布局宽度 / 基准CSS布局宽度 * 基准font-size值 + "px"
         */
        document.documentElement.style.fontSize = document.documentElement.clientWidth / 375 * 100 + "px";
    </script>
</head>
<body>
    <section></section>
</body>
</html>

浏览器设备仿真(Toggle Device Bar)默认宽度

问题痛点

在移动端开发过程中,浏览器会设置一个默认的页面宽度为980px,这一属性书通过meta标签中的name=viewport设置的,因此,如果你不指定 viewport 的宽度,浏览器移动设备仿真的宽短就会默认按980px处理,在这种情况下,就算选的移动端设备宽度是375px,显示结果也会是980px 请添加图片描述

关键代码

<meta name="viewport" content="width=device-width">

请添加图片描述

补充说明

width=device-width:表示宽度是设备屏幕的宽度 initial-scale=1.0:表示初始的缩放比例 minimum-scale=0.5:表示最小的缩放比例 maximum-scale=2.0:表示最大的缩放比例 user-scalable=yes:表示用户是否可以调整缩放比例,默认值是yes,可选值no

VScode px rem 转换插件

VScode px rem 转换插件.png

默认基准font-size为16px.png

视口与 vh vw

基本概念

  • 视口:在web浏览器中或移动端界面可见的部分,视口可分为布局视口(整个文档)、视觉视口(可见文档)、理想视口(整个文档显示宽度与可见文档宽度一致)
  • vw/vh:view-width 视口宽度/view-height 视口高度,vw/vh是一个动态值,相当于百分比值,1vw/1vh相当于屏幕宽度/高度的1%,100vw和100vh就是界面宽度和高度的100%,根据这个特性,vw一定程度上可以替换js动态适配移动端屏幕宽度

100vw自适应移动端不同设备界面.gif

<!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">
    <title>Document</title>
    <style>
        body{
            margin: 0;
            padding: 0;
        }
        section{
            height: 100vh;
            background-color: #D6D6D6;
            display: flex;
            flex-flow: row wrap;
            justify-content: space-between;
            align-content: flex-start;
        }
        section>div{
            width: 49vw;
            height: 20vh;
            background-color: #FAFAFA;
            font: normal normal 2vh/16px Aria;
            margin: 0.5vw;
            display: flex;
            justify-content: center;
            align-items: center;
        }        
    </style>
</head>
<body>
    <section>
        <div>49vw 20vh</div>
        <div>49vw 20vh</div>
        <div>49vw 20vh</div>
        <div>49vw 20vh</div>
        <div>49vw 20vh</div>
        <div>49vw 20vh</div>
        <div>49vw 20vh</div>
    </section>
</body>
</html>

单位转换

设备100vw100vh1vw1vhfont-size
5vw
iPhone4320px480px3.20px4.80px16px
iPhone6/7/8375px667px3.75px6.67px18.75px
iPhone6/7/8 Plus414px736px4.14px7.36px20.7px
iPad/iPad Mini768px1024px7.68px10.24px38.4px
iPad Pro1024px1366px10.24px13.66px51.2px

由表可知,如果设置font-size为vw或vh,则相同的vw或vh值,在不同屏幕尺寸上会自动等比例缩放,最终实现自适应

100vw/vh和100%的异同

  • 没有滚动条:相同
  • 有滚动条:100vw 包含滚动条,相当于窗口大小(滚动条也是窗口的一部分);100% 不包含滚动条,本质是占满剩余空间

100vw与100%异同.gif

<!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">
    <title>Document</title>
    <style>
        body{
            margin: 0;
            padding: 0;
        }
        div{
            display: flex;
            height: 55vh;
            justify-content: center;
            align-items: center;
            font-size: 5vw;
        }
        div:first-of-type{
            background-color: beige;
            width: 100vw;
        }
        div:last-of-type{
            background-color:bisque;
            width: 100%; /* 不设置width也是100% */
        }
    </style>
</head>
<body>
    <div>100vw 包含滚动条</div>
    <div>100% 不包含滚动条</div>
</body>
</html>

敬请指正,Thanks♪(・ω・)ノ。