移动端布局基础概念指南

前言这篇文章主要讨论了移动端页面渲染与布局的一些基本概念例如 viewport 和 css 像素, 这些内容是了解移动端页面适配的基本前提. 在这篇文章中记录了这些基本的概念, 因为我并不从事移动端开发, 文章有误, 欢迎指正. 移动端渲染表现为了简单起见, 我们不从概念讲起, 我们先来看看一个固定宽度的元素被放置到移动端浏览器中会发生什么. 有如下代码: <!DOCTYPE html><html><head> <meta charset="UTF-8"> <title>Document</title> <style> .example{ width: 900px; background-color: aqua; } </style></head><body> <div class="example"> 我的宽度是 900px </div></body></html>当然桌面浏览器渲染效果肯定在我们意料之中啦✨: 图片: 1920px下chrome渲染的效果: 而下面展示了图片展示了几个移动端浏览器渲染的结果: 图片: 移动端浏览器渲染效果: 这里我们简单的介绍一下图片中浏览器的版本, 这些浏览器在后文的截图中版本都是不会发生变化的. 浏览器版本平台chrome75windows10chrome75android9edge42android9Samsung9.3android9仔细观察我们发现:900px 宽的 div 没有占满屏幕, 也就是说屏幕的宽度比 900px 还要大. 那么屏幕宽度到底是多大呢, 我们插入一行代码来获取HTML元素的宽度: <script> document.write(`html元素的宽度是${document.documentElement.clientWidth}`);</script>不同浏览器的显示结果为: 他们都输出了同样的数据那就是 980 在某种程度上我们知道了页面的宽度, 原来页面是 980px 的宽度所以 900px 的div无法铺满一行. 对于移动浏览器它感知到自己的视口的宽度是 980px, 此时它渲染的比例就和一个 横向分辨率为 980px 的桌面显示器渲染的一样. 只不过移动终端的屏幕是一个小号的显示器而已.在没有更改页面的设置的情况下或者说默认的情况下, 移动终端的浏览器会按照 980px 的宽度来渲染页面, 然后再将页面缩放到适合屏幕的大小. ...

October 13, 2019 · 4 min · jiezi

viewport&像素

viewport是什么移动端中,分为两个视口:layout viewport 布局视口: 视口的分辨率接近于PC显示器,也就是html的宽度接近于pc端的宽度。visual viewport 视觉视口: 手机的物理可视窗口,不借助滚动条所看到的内容。移动设备的viewport默认是layout viewport可以这两理解,有一个图片(layout viewport),宽度是:1090 1090,有一个画框(visual viewport),宽度是:320 460,用户通过画框来看画。当layout viewport与visual viewport完全一致时,用户通过画框看到的就是整个画。如果layout viewport较大,用户需要通过移动画框来查看画面内容。meta中的viewportviewport是meta中的一个值,通过设置viewport,可以控制浏览器如何规范的渲染Web页面<meta name=“viewport” content=“width=device-width, initial-scale=1, maximum-scale=1”>要把当前的viewport宽度设为ideal viewport的宽度,既可以设置 width=device-width,也可以设置 initial-scale=1,如果initial-scale和viewport有冲突,浏览器会取比较大的值。viewport值:namevalueDescriptionwidth正整数或device-width定义视口(layout viewport)的宽度,单位为像素,height正整数或device-height定义视口的高度,单位为像素initial-scale[0.0-10.0]定义初始缩放值minimum-scale[0.0-10.0]定义缩小最小比例,它必须小于或等于maximum-scale设置maximum-scale[0.0-10.0]定义放大最大比例,它必须大于或等于minimum-scale设置user-scalableyes/no允许用户手动缩放页面,默认是yes分辨率&像素以上所说的宽度,其实是分辨率什么是分辨率像素:每张图片都是由色点组成的,每个色点称为一个像素。屏幕分辨率:是指一块屏幕中画面水平方向的像素值 * 画面垂直方向的像素值。图像分辨率: 是指每英寸图像内的像素点数。图像分辨率是有单位的,叫 像素每英寸。设备像素:device pixel屏幕上的像素。是物理像素。 设备像素可能不相同物理像素不会改变,单位是pt。1pt = 1/72(inch),inch及英寸,而1英寸等于2.54厘米 举个???? : iphone5的像素:6401136px, 表示:屏幕由640行,1136列像素组成。CSS像素:(css pixel)CSS像素是Web编程的概念,指的是CSS样式代码中使用的像素。举个???? :iphone5的像素:320px。 设置:zoom 100%的情况下,1个CSS像素才会等于1个设备像素如何计算css像素对于低分辨率设备(绝大部分显示器,手机屏幕),1个css像素相当于最接近参考像素的整数个设备像素。对于高分辨率设备(打印机)来说,1个css像素就是96分之一英寸。设备像素比:DPRDPR = 设备像素/CSS像素。理解:1px由多少个设备像素组成;如何获取:在移动端浏览器中以及某些桌面浏览器中,window对象有一个devicePixelRatio属性(有兼容问题),它的官方的定义为:设备物理像素和设备独立像素的比例,也就是 devicePixelRatio = 物理像素 / 独立像素。CSS像素就可以看做是设备的独立像素,所以通过devicePixelRatio,我们可以知道该设备上一个css像素代表多少个物理像素。设备独立像素:DIPCSS像素 =设备独立像素 = 逻辑像素每英寸像素密度:PPI一英寸中,像素个数计算:var 斜边尺寸 = V(1920^2+1080^2) V代表开根号 var ppi = 斜边尺寸/5.5 ppi = 401ppi单位px定义:css中的单位,是一个抽象概念(抽象概念一定要清楚上下问)。浏览器中都是按照px来设置尺寸。为视频显示的基本单位(来源:wiki)ps: px是一个相对单位,相对设备像素的。(css的像素是根据设备的分辨率计算出来的)。如何感受这个相对值呢?当我们缩放网页大小的时候,并没有改变css像素,但是页面中内容变大了,这是因为css像素是相对的,其他因素的改变,影响了css像素的大小。计算: 为了让相同的1px在不同的设备上,视觉上看起来差不多,css像素是根据设备像素大小换算出来的。css中,根据参考像素进行换算em计算:使用em单位的元素的字体大小乘以em值,父元素大小会影响em,是因为继承的原因,如果出现层级em嵌套,会影响比较大。rem计算:取决于页面根元素大小,根据根元素字体大小乘以rem值。retina视网屏幕:Retina显示器指的是在人体正常使用距离下,无法看到屏幕的像素。1px问题为什么会有这种问题?设计师的px指的是物理像素,我们设置的是css像素,物理像素和css像素不是完全一致的。如何解决小数.border { border: 1px solid #999 } @media screen and (-webkit-min-device-pixel-ratio: 2) { .border { border: 0.5px solid #999 } } @media screen and (-webkit-min-device-pixel-ratio: 3) { .border { border: 0.333333px solid #999 } }问题:兼容性不是很好tranform加伪类标签<span class=“border-1px”>1像素边框问题</span>// less.border-1px{position: relative;&::before{ content: “”; position: absolute; left: 0; top: 0; width: 200%; border:1px solid red; color: red; height: 200%; -webkit-transform-origin: left top; transform-origin: left top; -webkit-transform: scale(0.5); transform: scale(0.5); pointer-events: none; / 防止点击触发 */ box-sizing: border-box; @media screen and (min-device-pixel-ratio:3),(-webkit-min-device-pixel-ratio:3){ width: 300%; height: 300%; -webkit-transform: scale(0.33); transform: scale(0.33); }}}优点: 其实不止是圆角, 其他的边框也可以这样做出来缺点: 代码量也很大, 占据了伪元素, 容易引起冲突阴影.border-1px{box-shadow: 0px 0px 1px 0px red inset;} ...

March 20, 2019 · 1 min · jiezi

开发一个psotcss插件

git地址:开发一个psotcss插件节点类型postcss会将我们的css生成ast,然后会去遍历它,在遍历的过程中会传给我们一些不同类型的节点对象,我们主要需要了解的几个类型:css ast主要有3种父类型AtRule: @xxx的这种类型,如@screenComment: 注释Rule: 普通的css规则还有几个个比较重要的子类型:decl: 指的是每条具体的css规则rule:作用于某个选择器上的css规则集合这是test的地方的,不熟悉ast的可以先了解一下:css ast结构postCss操作方法postCss为我们提供了一些方便的操作方法遍历walk: 遍历所有节点信息,无论是atRule、rule、comment的父类型,还是rule、 decl的子类型walkAtRules:遍历所有的atRulewalkComments:遍历所有的注释节点walkDecls:遍历所以的属性walkRules:遍历所有的css代码块root.walkDecls(decl => { decl.prop = decl.prop.split(’’).reverse().join(’’);});postcss在遍历的过程中,会将当前遍历的对象的cell传给回调函数,该参数是对应的rule,decl或者comment等Constructor等构造函数的实例,根据遍历的节点不同,该实例可能会有如下属性:nodes: css规则的节点信息集合decl: 每条css规则的节点信息prop: 样式名,如widthvalue: 样式值, 如10pxtype: 类型source: 包括start和end的位置信息,start和end里都有line和* column表示行和列selector: type为rule时的选择器name: type为atRule时@紧接rule名,譬如@import ‘xxx.css’中的importparams: type为atRule时@紧接rule名后的值,譬如@import ‘xxx.css’中的xxx.csstext: type为comment时的注释内容同样还有继承的一些方法,给我操作css的, 比如操作每条具体css属性的declaration:afterbeforecleanRawsclonecloneAftercloneBeforeerrornextprevrawremovereplaceWithroottoStringwarnpostcss pluginpostcss插件如同babel插件一样,有固定的格式export default postcss.plugin(‘postcss-plugin-name’, function (opts) { opts = opts || {}; return function (root, result) { // 处理逻辑 };});注册个插件名,并获取插件配置参数opts返回值是个函数,这个函数主体是你的处理逻辑,有2个参数,一个是root,css ast的根节点。另一个是result,返回结果对象,譬如result.css,获得处理结果的css字符串,result.message包含组件里创建的warnings和自定义信息,result.warn()创造一个warning实例并将其加入到result.message中,result.warnings()获得所有创建过的warning。注意组件的异常信息处理,不要直接console,因为一些 postcss 处理器会过滤掉console的输出导致异常信息丢失,用node.warn或者node.error创造CssSyntaxError 实例,会自动带上源码中的位置信息帮助debug,加到异常信息队列里。直接调用postcss下的方法可以用postcss.parse来处理一段css文本,拿到css ast,然后进行处理,再通过调用toResult().css拿到处理后的css输出,在一些简单的处理中可以用这种方法。写在最后:想写一下的可以按照这里的指引,很详细https://github.com/postcss/postcss-plugin-boilerplate这是我写的一个将px转为vw的插件vw-by-px参考:http://api.postcss.orgpostcss-pixel-to-viewport

March 18, 2019 · 1 min · jiezi

移动端适配之二:visual viewport、layout viewport和ideal viewport介绍

上一篇博文,可算把像素这个东西讲清楚了。在这篇博文里面,将继续介绍viewport相关的内容。很多博客都会提到PPK所讲的三个viewport,有的讲的比较复杂,看的云里雾里,我这里也大概介绍一下,三个viewport主要是相对于移动端而言的。visual viewport这个是浏览器给我们用的、能真正用来显示网页内容的区域,可以通过下面的js命令获取:window.innerWidthwindow.innerHeight正如上篇博客所说的,前端里面能获取到的像素基本上都是CSS像素,所以这个的单位也是CSS像素。对于iPhone X,浏览器全屏状态下,其window.innerWidth的值为375。上篇博客中还提到screen.width和screen.height,主要是用来获取整个屏幕的大小的,而window.innerWidth和window.innerHeight只是获取浏览器可用显示区域的大小,也就是浏览器中间负责显示的部分。当浏览器全屏时,要去掉状态栏、标签栏、任务栏等区域,当浏览器非全屏时,其值更小。由于在移动端,浏览器一般都是全屏的,所以大多数情况下screen.width与window.innerWidth的值相等,也有的博客中说用screen.width和screen.height来获取visual viewport的大小,就是这个原因。visual viewport是我们可以直观看到的,不严谨的说,就是差不多等于手机屏幕的大小,偏向于一个物理概念。layout viewport网页最早是出现在电脑上的,上一篇博客中提到,电脑的物理像素可能比手机还要低,但是电脑的设备无关像素(或者说是分辨率吧,更严谨一些)是明显大于手机的设备无关像素的,毕竟电脑的屏幕尺寸远比手机大啊。那些在电脑上的网页,如果没有经过专门的优化,直接搬到手机上看,那么问题就来了,网页会被挤得变形,相信这种问题大家都遇到过。所以呢,手机厂商为了解决这个问题,设置了一个layout viewport。这是一个虚拟的窗口,其大小比手机屏幕大,加载网页时,直接把HTML渲染在这个虚拟的窗口中,这样就不会样式错乱了。在查看的时候,毕竟手机的visual viewport小啊,那就只能通过滚动条来看了。做个比喻,layout viewport就是一张大白纸,HTML的内容就写在这个大白纸上,visual viewport就是一个放大镜,上下左右移动,可以显示其中的一部分。Layout viewport的大小可以通过document.documentElement.clientWidth和document.document.clientHeight,实际使用中可能会有一些兼容问题,这跟DOCTYPE声明有关。不同浏览器的layout viewport大小不同,常见的有980px、1024px。ideal viewportLayout viewport是为了能将电脑上的网页正确的显示到手机上。当浏览器拿到一个网页时,首先会渲染到这个layout viewport里面。可是现在有很多网页会针对手机做专门的设计,比如现在的一些H5活动页,设计的尺寸就是在手机上看的。此时如果还是把网页渲染到这个大的layout viewport上,实在是有点不合适了。所以,还应该有个ideal viewport,这个ideal viewport应该与手机屏幕大小的相同,确切来说,等于visual viewport的大小。把页面渲染到这个ideal viewport里面,就能在visual viewport中完美显示。小结根据我的理解小结一下:layout viewport和ideal viewport都是用来渲染页面,layout viewport较大,用来渲染电脑上的页面,ideal viewport较小,用来渲染专门针对手机设计的页面;而visual viewport是用来查看layout viewport和ideal viewport的,是用来查看渲染的结果的。visual viewport是很具体的,而layout viewport和ideal viewport是比较抽象的。某种程度来说,layout viewport和ideal viewport可以理解成是两种尺寸,承载页面渲染的盒子,可以设置成layout viewport的尺寸,也可以设置成ideal viewport的尺寸,而且在默认情况下是layout viewport的尺寸。如果我们设置HTML中body为width:100%,那么这个body的实际宽度,将由这个盒子的宽度决定。在下一篇博文中,将介绍如何用meta标签来设置viewport,也就是设置这个承载HTML页面渲染的盒子的尺寸,从而达到最佳的显示效果。

December 27, 2018 · 1 min · jiezi