文章目录
- 像素
- 设备像素(物理像素)
- 设备独立像素(逻辑像素)
- CSS像素
- 像素之间的关系
- 分辨率
- 设备分辨率
- 逻辑分辨率
- 移动端开发分类
- 自适应
- 响应式
- 视口
- 布局视口(layout viewport)
- 视觉视口(visual layout)
- 理想视口(ideal layout)
- 移动端适配方案
- 百分比设置
- rem单位+动态html的font-size
- vw单位
- flex的弹性布局
像素
设备像素(物理像素)
设备像素(device pixels)也叫物理像素,指的是显示器上的真实像素,每个像素的大小是屏幕固有的属性,屏幕出厂以后就不会再改变。
我们可以这么理解,屏幕是由N多个小方块构成的,每个小方块都只能显示一个颜色,而一个小方块,就是一个设备像素。而在不同的设备上,这个格子的大小是不同的,所以物理像素并不是一个固定大小的单位,它只代表一个显示器上的小格子,格子到底多大,在显示器出厂前已经确定好了。
设备独立像素(逻辑像素)
设备独立像素(device independent pixels)也叫逻辑像素,是操作系统定义的一种像素单位,应用程序将设备独立像素告诉操作系统,操作系统再将设备独立像素转化为设备像素(物理像素),从而控制屏幕上真正的物理像素点。
我们可以这么理解,物理像素是硬件开发相关的单位,是基于一个一个的硬件小方块,其大小由硬件厂家设定。而逻辑像素,则更像是软件开发相关的单位,软件相关的工作人员通过逻辑像素来表达软件相关的尺寸。前端css代码、浏览器显示给开发者的尺寸、UI设计师给出的UI稿,其尺寸单位都是逻辑像素。
举个栗子:比如如下代码,其中标注的14px、26px等值,px就是我们所说的逻辑像素。
那么为什么需要在应用程序和设备像素之间定义这么一种单位呢?为什么应用程序不直接使用设备像素?
例如原先在 1280×720 设备分辨率的显示屏中,显示高度为 12 个设备像素的字体,现在放到设备分辨率为 2560 ×1440 的显示屏中,如果要想得到原先的大小,则需要 24 个设备像素,如果应用程序直接使用设备像素,那么编写应用程序则将变得非常困难,需要编写应用程序逻辑:字体在一些屏幕上高度为 12 个设备像素,在另一些屏幕上却需要 24 个设备像素。
- 因此操作系统定义了一个单位:设备独立像素。
- 操作系统保证:用设备独立像素定义的尺寸,不管屏幕的参数如何,都能以合适的大小显示。
- 操作系统是如何做到的呢?对于那些像素密度高的屏幕,将多个设备像素划分为一个设备独立像素。至于将多少设备像素划分为一个逻辑像素,这由操作系统决定。
对于上面的例子:“原本高度为 12 个设备像素的字体,现在高度为 24 个设备像素才能得到相同的大小”,操作系统会将一个逻辑像素定义为 2*2个 真实像素,从而设备独立像素尺寸不需要改变,而且不管在新、旧设备上,显示的尺寸大致相同。
CSS像素
在 CSS 中使用的 px 都是指 css 像素,比如 width: 128px。css 像素的大小是很容易变化的,当我们缩放页面的时候,元素的 css 像素数量不会改变,改变的只是每个 css 像素的大小。也就是说 width: 128px 的元素在缩放200% 以后,宽度依然是 128 个 css 像素,只不过每个 css 像素的宽度和高度变为原来的两倍。如果原本元素宽度为 128 个设备独立像素,那么缩放 200% 以后元素宽度为 256 个设备独立像素。
像素之间的关系
- CSS像素和设备独立像素的关系
- 缩放比例:css像素边长/设备独立像素边长
- 缩放比例100%:1个css像素大小等于1个设备独立像素
- 缩放比例200%:1个css像素大小等于(2*2)个设备独立像素
- CSS像素和设备像素的关系
- 设备像素比(DPR):设备像素的数量/CSS像素的数量。即当前设备将通过几个物理像素点来绘制一个逻辑像素点。
- 设备像素比 = CSS像素边长/设备像素边长
- pc端一个css像素对应一个物理像素
因为屏幕足够大,pc端默认情况下一个css像素就对应着一个物理像素,但是有没有发现你把分辨率调小以后,显示的内容变大了,但是显示器的物理像素肯定不会变啊,这时候其实就是一个css像素对应着若干个物理像素了,这个是与用户设置有关。
- m端一个css像素对应多个物理像素
移动设备大小是有限的,而且分辨率不低,甚至比pc端更高,也就是可以显示的物理像素更多,如果和pc端一样,一个css的px和物理像素一一对应,可以想象,显示的内容有多小。这样肯定是不行的,解决这个问题,我们可以很自然的想到,那在移动设备上就别一一对应了,一个css的px对应多个物理像素吧,这样就不至于显示的内容过小了,实际上移动设备也是这么做的,你在开发时写的px和最终渲染显示的物理像素数不是一比一的,可能1个px对应2个物理像素,可能3个物理像素,设备显示的物理像素数和你css的px数的比值就叫做设备像素比,简称dpr。好了,这样显示内容过小的问题就解决了。
- dpr越高越好,需要2倍图,3倍图等等来更高清
有了dpr之后,有一个问题就是同样的一张图片,我设了宽高的px数,那么在dpr为1的设备上,和dpr为2的设备上显示的效果是一样的,1个px在dpr为1的设备上会用1个物理像素来显示,在dpr为2的设备上会用2*2个物理像素来显示,这样dpr高的优势就体现不出来了,我设备比他的好,你给我的体验是一样的,可能有些用户不爽,我们可以区分对待,对于高dpr的设备,用物理像素更多的高清图片来替代,也就是2x图,3x图等等。
分辨率
设备分辨率
设备分辨率:描述的就是这个显示器的宽和高分别是多少个设备像素,即设备像素点的总数即为设备分辨率,例如常见的显示器分辨率为1920*1080。
逻辑分辨率
逻辑分辨率用屏幕的宽高来表示(单位:设备独立像素),即设备独立像素点的总数,我们通过操作系统的分辨率设置来改变设备独立像素的大小。
例如屏幕的设备分辨率是1920 * 1200(单位:设备像素),我们可以在当前的分辨率下设置逻辑分辨率是1280 * 800(单位:设备独立像素)。那么横、纵方向的设备像素数量恰好是设备独立像素的1.5倍。这也意味着,设备独立像素的边长是设备像素边长的1.5倍。
移动端开发分类
- 原生App开发
- 小程序开发
- Web页面
自适应
根据不同的设备屏幕大小来自动调整尺寸、大小
响应式
会随着屏幕的实时变动而自动调整,是一种自适应
视口
-
在一个浏览器中,我们可以看到的区域就是视口(viewport)
-
fixed就是相对于视口来进行定位的
-
在PC端的页面中,我们不需要对视口进行区分,因为我们的布局视口和视觉视口是同一个
-
但是在移动端中,布局视口是大于视觉视口的。这是因为移动端的网页窗口比较小,我们可能会希望一个大的网页在移动端可以完整的显示。
布局视口(layout viewport)
布局视口的默认宽度是980px
默认情况下,一个PC端的网页在移动端会如何显示
- 首先它会按照宽度为980px来布局一个页面的盒子和内容
- 为了显示可以完整的显示在页面中,对整个页面进行缩小
视觉视口(visual layout)
如果默认情况下,我们按照980px显示内容,那么右侧就会有一部分区域就会无法显示,所以手机端浏览器会默认对页面进行缩放以显示到用户的可见区域中,那么显示在可见区域的这个视口,就是视觉视口。
理想视口(ideal layout)
如果我们希望设置的是100px,显示的就是100px,就需要通过理想视口。
这时候可以通过设置meta中的viewport
移动端适配方案
百分比设置
rem单位+动态html的font-size
px = rem * font-size
1rem = 视口宽度 / 10
rem单位是相对于html元素的font-size来设置的,那么如果我们需要在不同的屏幕下有不同的尺寸,可以动态的修改html的font-size尺寸
举个栗子:
- 设置一个盒子党的宽度是1rem
- 设置不同的屏幕上html的font-size不同
这样我们在开发中,我们只需要考虑两个问题:
- 针对不同的屏幕,设置html不同的font-size
- 媒体查询
可以通过媒体查询来设置不同尺寸范围内的屏幕html的font-size尺寸
@media screen and (min-width: 320px) { html { font-size: 20px } }
缺点:
- 我们需要针对不同的屏幕编写大量的媒体查询
- 如果动态改变尺寸,不会实时的进行更新
- JS动态计算
如果我们希望实时改变屏幕尺寸时,font-size也可以实时更改,可以通过js代码。
方法:
- 根据html的宽度计算出font-size的大小,并且设置到html上
- 监听页面的实时改变,并且重新设置font-size的大小到html上
// 获取html的元素 const htmlEl = document.documentElement function setRemUnit(){ // 获取html的宽度(视口的宽度) const htmlWidth = htmlEl.clientWidth // 根据宽度计算一个html的font-size的大小 const htmlFontSize = htmlWidth / 10 // 将font-size设置到html上 htmlEl.style.fontSize = htmlFontSize + "px" } // 保证第一次进来时,可以设置一次font-size setRemUnit() // 当屏幕尺寸发生变化时,实时来修改html的font-size window.addEventListener("resize",setRemUnit)
- lib-flexible库
lib-flexible库做的事情是相同的,你也可以直接引入它
- 将原来要设置的尺寸,转化成rem单位
- 手动换算
比如在一个375px屏幕上,100px宽度和高度的盒子
我们需要将100px转成对应的rem值
计算如下:
375px => font-size: 375/10px = 37.5px
100px/37.5px=2.6667
-
less/scss函数
-
postcss-pxtorem插件
目前在前端的工程化开发中,我们可以借助webpack的工具来完成自动的转化
- VSCode插件
px to rem 的插件,在编写时自动转化
vw单位
1vw = 1% * 视口宽度,即 1vw = 视口宽度 / 100
- 手动计算
- less/scss函数
- postcss-px-to-viewport-8-plugin
- VSCode插件
flex的弹性布局
不管移动设备的分辨率怎么变, 关键元素高宽和位置都不变,只有容器元素在做伸缩变换。百分比布局,无需计算百分比,可以很好的适配到所有屏幕
特点:文字流式,控件弹性,图片等比缩放
为什么要使用flex布局
float布局有副作用,如果子元素设置了浮动,会引起父元素的塌陷 /不能动态实现自适应布局/设置padding margin不能正确表达 /之前的元素浮动了,后面的元素可能异位,所以页面越来越复杂,不利于管理
float布局对于移动端布局很不友好,所以出现了弹性布局flex
采用 Flex 布局的元素,称为 Flex 容器。它的所有子元素自动成为容器成员
flex容器属性
- flex-direction
- flex-wrap
- flex-flow
- justify-content
- align-items
- align-content
- flex-direction属性
flex-direction属性决定主轴的方向(即项目的排列方向)。
.box {
flex-direction: row | row-reverse | column | column-reverse;
}
//依次表示主轴为水平方向,起点在左端。(默认)
//主轴为水平方向,起点在右端。
//主轴为垂直方向,起点在上沿。
//主轴为垂直方向,起点在下沿。
- flex-wrap属性
默认情况下,项目都排在一条线(又称"轴线")上。flex-wrap属性定义,如果一条轴线排不下,如何换行。
.box{
flex-wrap: nowrap | wrap | wrap-reverse;
//依次是不换行
//换行,第一行在上方。
//换行,第一行在下方。
}
- flex-flow属性
flex-flow属性是flex-direction属性和flex-wrap属性的简写形式,默认值为row nowrap。
.box {
flex-flow: <flex-direction> || <flex-wrap>;
}
- justify-content属性(这个很重要,经常用)
justify-content属性定义了项目在主轴上的对齐方式。
.box {
justify-content: flex-start | flex-end | center | space-between | space-around;
//依次是左对齐(默认值)
//右对齐
//居中
//两端对齐,项目之间的间隔都相等。
//每个项目两侧的间隔相等。所以,项目之间的间隔比项目与边框的间隔大一倍。
}
- align-items属性(这个也很重要。也常用)
align-items属性定义项目在交叉轴上如何对齐。
.box {
align-items: flex-start | flex-end | center | baseline | stretch;
//依次是交叉轴的起点对齐。
//交叉轴的终点对齐。
//交叉轴的中点对齐。
//项目的第一行文字的基线对齐。
//如果项目未设置高度或设为auto,将占满整个容器的高度(默认值)
}
- align-content属性
align-content属性定义了多根轴线的对齐方式。如果项目只有一根轴线,该属性不起作用。
.box {
align-content: flex-start | flex-end | center | space-between | space-around | stretch;
//依次是与交叉轴的起点对齐。
//与交叉轴的终点对齐。
//与交叉轴的中点对齐。
//与交叉轴两端对齐,轴线之间的间隔平均分布。
//每根轴线两侧的间隔都相等。所以,轴线之间的间隔比轴线与边框的间隔大一倍。
//轴线占满整个交叉轴。(默认值)
}
项目的属性
- order
- flex-grow
- flex-shrink
- flex-basis
- flex
- align-self
- order属性
order属性定义项目的排列顺序。数值越小,排列越靠前,默认为0。
css复制代码.item {
order: <integer>;
}
- flex-grow属性(很重要)
flex-grow属性定义项目的放大比例,默认为0,即如果存在剩余空间,也不放大。
如果所有项目的flex-grow属性都为1,则它们将等分剩余空间(如果有的话)。如果一个项目的flex-grow属性为2,其他项目都为1,则前者占据的剩余空间将比其他项多一倍。
css复制代码.item {
flex-grow: <number>; /* default 0 */
}
- flex-shrink属性
flex-shrink属性定义了项目的缩小比例,默认为1,即如果空间不足,该项目将缩小。
如果所有项目的flex-shrink属性都为1,当空间不足时,都将等比例缩小。如果一个项目的flex-shrink属性为0,其他项目都为1,则空间不足时,前者不缩小。
注意:负值对该属性无效。
css复制代码.item {
flex-shrink: <number>; /* default 1 */
}
- flex-basis属性(这个是重点,常用)
flex-basis属性定义了在分配多余空间之前,项目占据的主轴空间(main size)。浏览器根据这个属性,计算主轴是否有多余空间。它的默认值为auto,即项目的本来大小。
它可以设为跟width或height属性一样的值(比如350px),则项目将占据固定空间。
- flex属性(这个最重要)
flex属性是flex-grow, flex-shrink 和 flex-basis的简写,默认值为0 1 auto。后两个属性可选。
css复制代码.item {
//该属性有两个快捷值:auto (1 1 auto) 和 none (0 0 auto)。
//建议优先使用这个属性,而不是单独写三个分离的属性,因为浏览器会推算相关值。
flex: none | [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'> ]
}
- align-self属性
align-self属性允许单个项目有与其他项目不一样的对齐方式,可覆盖align-items属性。默认值为auto,表示继承父元素的align-items属性,如果没有父元素,则等同于stretch。
arduino复制代码.item {
align-self: auto | flex-start | flex-end | center | baseline | stretch;
//这个其实就是在项目里用align-items 注:auto为默认值
}
flex实际应用
常用的flex 1
flex 是 flex-grow、flex-shrink、flex-basis的缩写
当 flex 取值为 none,则计算值为 0 0 auto
.div {
flex-grow: 0;
flex-shrink: 0;
flex-basis: auto;
}
当 flex 取值为 auto,则计算值为 1 1 auto
.div {
flex-grow: 1;
flex-shrink: 1;
flex-basis: auto;}
当 flex 取值为一个非负数字则 flex-grow 数字,flex-shrink 取 1,flex-basis 取 0%(最常用)
.div {
flex-grow: 1;//要取的值
flex-shrink: 1;//默认
flex-basis: 0%;//默认
}
当 flex 取值为一个长度或百分比,则视为 flex-basis 值,flex-grow 取 1,flex-shrink 取 1
.div {
flex-grow: 1;//默认
flex-shrink: 1;//默认
flex-basis: 0%;//要取得值
}
当 flex 取值为两个非负数字,则分别视为 flex-grow 和 flex-shrink 的值,flex-basis 取 0%
.div {
flex-grow: 1;//要取的第一个值
flex-shrink: 1;//要取的第二个值
flex-basis: 0%;//默认
}
当 flex 取值为一个非负数字和一个长度或百分比,则分别视为 flex-grow 和 flex-basis 的值,flex-shrink 取 1
.div {
flex-grow: 1;//要取的第一个值
flex-shrink: 1;//默认
flex-basis: 0%;//要取的第二个值
}
flex常见布局
flex实现等分布局
.box{
height: 500px;
display: flex;
}
.box div{
height: 300px;
border: 1px solid #000000;
flex: 1;//这就是flex:1的妙用
}
div class="box">
<div>等分效果</div>
<div>等分效果</div>
</div>
左边固定右边自适应
.box {
height: 500px;
display: flex;
}
.box div {
height: 300px;
text-align: center;
}
.box div.right {
flex: 1;//右边自适应
border: 1px solid #000000;
}
.box div.left {
border: 1px solid #000000;
flex-basis: 100px;//左边固定,优先级最高
}
//html
<div class="box">
<div class="left">左边固定效果</div>
<div class="right">右边自适应效果</div>
</div>
边自适应的内容如果超过范围,自适应的地方添加min-width:0,若 min-width 未设置就默认为 auto,在这里就等于这个自适应的的宽度
垂直水平居中对齐
.box {
width: 100%;
height: 300px;
border: 1px solid purple;
display: flex;
justify-content: center;
align-items: center;
}
//html
<div class="box"><p>居中</p></div>