Home > Web Front-end > H5 Tutorial > body text

How to operate mobile page layout

PHP中文网
Release: 2017-06-20 13:50:26
Original
3108 people have browsed it

Things about mobile page layout

##1. viewport

  1. What is a viewport

    To put it simply, the viewport is the area on the browser used to display web pages. In other words, the actual width of the browser is different from the width of our mobile phone. Whether the width of your mobile phone is 320px or 640px, the width inside the mobile browser will always be the viewport of the browser itself. Today's browsers will provide themselves with a default viewport value, which may be 980px, or other values. Let's take mobile phones as an example. Currently, most of the new versions of mobile browsers use 980px as the default viewport value. I have tested the new version of browsers on different platforms. After testing, the default viewport under iPhone is 980px. For browsers under Android, the latest mainstream browsers (such as chrome, and many domestic ones like qq , uc) the viewport is also 980px.

  2. What is viewport used for?

    The default value of viewport is generally larger than the mobile phone screen. In this way, when we browse the desktop web page, the desktop web page can be displayed normally (when we design the normal page, the main area of ​​the page is generally made of 960px, so the value of 980px can be to the normal display of desktop web pages). However, in fact, the screen width of our mobile phone is not 960px, so a horizontal scroll bar will appear in the browser. At the same time, even if it is based on the 980 viewport, our experience of browsing our desktop page on the mobile terminal is actually not good. Therefore, generally, we will design a mobile page specifically for the browser.

  3. Control of viewport

    Nowadays, most browsers (that is, mainstream Android browsers and ios) support a viewport Controlled. Normally, we would write like this.

    Viewport has 6 attributes by default

    We put this tag in the head, like this

    <meta name="viewport" content="initial-scale=1">
    Copy after login
    This way we can control the viewport

  • width: Set the width of the viewport (as mentioned before, the width of the browser is detailed), which can be an integer or the string "width-device"

  • initial-scale: The initial zoom value of the page, which is a number and can be a decimal number

  • minimum-scale: the minimum zoom value allowed by the user, It is a number, it can be a decimal number

  • maximum-scale: The maximum zoom value allowed by the user, it is a number, it can be a decimal number

  • height: Setting The height of the viewport (which we generally cannot use)

  • user-scalable: whether the user is allowed to zoom, 'no' means not allowed, 'yes' means allowed

2. About our equipment

  1. Three concepts you need to understand:

  • PPI: It can be understood as the display density of the screen

  • DPR: The corresponding relationship between the physical pixels and logical pixels of the device, that is, physical pixels/logical pixels

  • Resolution: This is what we often call resolution

  • Physical pixels and logical pixels

    After reading the first point of our content above, some people may have some questions. My Android phone, or iphone6plus (it should be limited to this model at the moment), is 1920x1080 or other. It is higher and larger than the default 980px of the viewport I called before.

    Such a problem is what I mentioned before about the relationship between physical pixels and logical pixels (ie DPR). Taking 1920x1080 as an example, 1080 is a physical pixel, and what we get in the viewport, such as "width-device", is a logical pixel. Therefore, the size compared with the default value of the previous viewport is actually the size of logical pixels, not the size of physical pixels.

    Taking iphone6 ​​as an example, without any scaling, the 'width-device' obtained by iphone6 ​​is 375px, which is the logical pixel of the screen. The 750px we know at the time of purchase is the physical pixels of the screen.

  • CSS problem

    有了上面第二点的一些基础,还是以iphone6为例,我们可以知道,其实我们所写的1px,在iphone6上为2px的物理像素。所以,最后的,给出一个结论。就是我们写的1px,在移动端,是逻辑像素的1px,而非物理像素的1px。

  • 三. 使用rem布局

    1. 简单说下rem

      rem是根据页面的根元素的font-size的一个相对的单位,即

      html{
      	font-size: 16px;
      }	
      Copy after login

      比如当我们在一个div中,如此写

      div{
      	width: 2rem;
      }
      Copy after login

      那么我们的width,是16*2 = 32px

    2. rem做到适配不同分辨率

      这个是现在手机淘宝的移动端的解决方案,即使用rem的特性,来对页面进行布局。

      下面举一个例子

      假定设计稿的大小为750,那么我们则将整个图分成100份来看(下面的题外话会说明为什么会分成100份来看)

      那么,我们现在就让根部元素的font-size为75px

      html{
      	font-size: 75px;
      }
      Copy after login

      那么,我们现在就可以比对设计稿,比如设计稿中,有一个div元素,宽度,高度都为75px,那么我们这样写即可

      div{
      	height: 1rem;
      	width: 1rem;
      }
      Copy after login

      可能看到这里,一些人还是不明白怎么用rem做到适配不同的分辨率,那么我们再来

      现在,我们换设备了,不用这个设备是一个width为640的手机

      那么这个时候,我们的rem单位就起到作用了。

      我们的rem全是根据html的font-size来改变的,所以说,这个时候,我们只需要把html下的font-size改成64px。那么,我们之前的div,因为是根据html下的font-size动态变化的,那么。此时也就变成了宽度和高度都为64px的东西了。这样,就可以做到适配不同的屏幕分辨率了。(其实就是个等比缩放)

      总结一下,我们的解决方案,其实就是 设计稿的像素/html的font-size = 用来代替px的rem。

      这一个步骤,我们需要通过JS来进行操作。

      对于js的操作在下面会提到。

    3. DPR的问题

      视觉姐姐给了我们设计稿,并交由我们实现,那么,我们应该去认真的实现:-)(试想你做了一张图,而前端很多地方并没有按照你所想的,你所给的去做,而是私自改变了很多东西,你肯定会不高兴的)

      那么1px会出现什么问题呢。

      还记得我们第二大点讲的,我们的设备,是有物理像素和逻辑像素的。而假设我们的设计稿是750的,同时还是以iphone6为例,此时如果我们的viewport是这样的

      <meta name="viewport" content="initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
      Copy after login

      之前说过,在不做任何缩放的条件下,iphone6获取到的viewport为375px。

      然后我们的页面中有个div,他有一个边框值,如下

      div{
      	height: 5rem;
      	widht:5rem;
      	border: 1px solid #000
      }
      Copy after login

      此时我们写的1px,实际上是逻辑像素,而我们在iphone6上看到的是物理像素,于是这个时候,我们眼睛所看到的其实是2px(参考第二点第三个问题)

      所以此时我们需要在viewport上做文章了,此时先明确,如果要获取到真正的1px,那么我们需要这么做,将viewport改为

      <meta name="viewport" content="initial-scale=0.5, maximum-scale=0.5, minimum-scale=0.5, user-scalable=no">
      Copy after login

      即对屏幕做0.5倍的缩放。这样,我们就能得到实际的1px。

      所以到这里,我们还要明确一点,viewport的meta标签,我们这里也只能通过js来动态生成。

      同时,这样写,据说还可以避免比如inline的SVG等元素按照逻辑像素的渲染。避免了整个页面清晰度的打折(其实我并不能看出来)

    4. 文字适配问题
      Copy after login

      最近深深纠结与rem与px做字体单位的问题,还是先分别谈下二者吧。

      rem与px的特点:

      字体大小引发的系列问题:

      文字适配的解决方案:

      上面说了这么多,我们总要有一套解决方案吧

      对于一些标题性的文字,我们依然可以用rem。让他随着屏幕来进行缩放,因为标题性文字一般较大,而较大的文字,点阵对其影响就越小。这样,即使出现奇怪的尺寸,也能够让字体得到很好的渲染。

      对于一些正文内容的文字(即站在使用者的角度,你不希望他进行缩放的文字)。我们采用px来进行处理。

    • 倘若一个字体,只提供了12px,14px,16px的点阵。那么当你写13px,15px,17px的时候。就并没有其字体大小所对应的点阵。那么这样就造成了一个问题。他们会使用其相邻的点阵,比如对应使用了12px,14px,16px的点阵,而导致一个问题,文字占用的大小确实改变,但点阵却并没有改变。

    • 字体大小:我们平时也看过,很多网站,是不以奇数作为字体大小的。我稍微查了些东西,在知乎上的现在网页设计中的为什么少有人用 11px、13px、15px 等奇数的字体?问题下,有一些比较好的解答,我就不再多说(我也并不能比这个问题说的更多),总的来说,其实就是偶数宽度的字体能够显得均衡,以及一个点阵的问题。不过因为要谈及点阵,所以我拿上面回答中的一个内容举例。

    • 以rem作为字体单位:我们可以让页面整体的文字,也跟随着html的font-size来进行改变,这样,在不同的屏幕下,可以做到文字相对屏幕的比例是一样的。

    • 以px作为字体单位: 这个是目前很多网站还是依然采用的方法。因为以上面所写的,以rem作为字体单位。无论在任何屏幕下面,我们的文字都会根据屏幕做一个适应。试想这样一个场景。你买了一个大屏手机(5.7寸的),而别人用的是4寸的手机。以rem作为字体单位的话,那大屏手机看到的文字多少和小屏手机确实一样的了。这样来做,其实并不符合我们买大屏手机的期待。同时,以rem作为字体单位,可能会导致出现很多奇怪的字体大小(毕竟是根据html的font-size动态变化的嘛),同时这其中还涉及到了一个点阵尺寸的概念,这个在下面来讲。

    四.安卓与ios不得不说的问题(解决篇)

    1. 在 三.使用rem布局 里面,我们给出了各种情况的解决方案,并且,在我举例的时候,热衷于使用iphone来举例,但其实,上面的所有问题,不是仅仅iphone会出现的问题,安卓也是一样。但是,如果你已经看完了上面,那么这里,才是真正给出我们解决方案的地方,并且,这个解决方案并不完善。

    2. 谈谈iphone的r屏与安卓的各种屏

      rem布局也好,用viewport进行缩放也罢,文字的适配问题也是,都是基于我们想对各个不同的设备所进行的匹配。这套方案很好,然而也有其兼顾不到的地方。即安卓和ios的屏幕的一些问题,当然,细的东西我们不谈,我们只谈dpr。

    • 安卓并没有对自己的屏幕叫做r屏,但是其原理和iphone的r屏可以说是一样。r屏做的是什么,把两个(三个)物理像素,丢到了一个逻辑像素里面,让屏幕展现的更清晰(当然,这是我片面的理解,不过我觉得大体来说并没有错,我们也不用去深入探讨r屏还有什么东西,我也并不懂)。而安卓也是一样,他也同样把n个物理像素丢到了一个逻辑像素里面。而这里的n,也就是dpr值(所以当我看到好多人问安卓为什么不采用r屏的时候,我真的也是……醉了?)。而安卓的dpr值,并不像iphone那样,就只有两个值。安卓的dpr是千奇百怪的,可能是1.5,2,3,4,2.5等等的都有。(甚至我还看到了1.7之类的,安卓的各个设备商,玩的真尼玛high啊。怎么高兴怎么来。)

      所以,对安卓的屏幕的dpr的处理,其实是很头疼的,因为,他和我们对字体的处理,有了很大的冲突。这个在下面提及

    • 其实iphone为开发者考虑到了很多东西,为了让开发者便于开发,在6plus出现之前,iphone的dpr始终也就是2(即前面所谈的物理像素/逻辑像素=2),即使是6plus出现了,iphone到底其实也就只有2,3这两个dpr。我们很容易对其做到兼顾。

    • 先谈iphone

    • 再谈安卓

  • 首先看看手淘的解决方案

    • rem布局

      用js获取到页面的宽度,然后对其进行宽度/10的处理,再将其写到html的font-size中。手淘的flexible.js里面的这一部分,并为了方便看懂做了些改写。大体就是这样的

      function refreshRem(){
       	var docEl = window.document.documentElement;
          var width = docEl.documentElement.getBoundingClientRect().width;
      
          var rootSize = width/10;
          docEl.style.fontSize = rootSize + 'px';
      }
      Copy after login
    • dpr的配置

      首先,在引入flexible.js之前,我们可以对dpr进行手动的配置,即使用自定义的meta标签来配置dpr(看清楚是flexible,而非viewport)

      <meta name="flexible" content="initial-dpr=2,maximum-dpr=3" />
      Copy after login

      iniital-dpr是把dpr强制设定为给定的值,而maximum-dpr则是给出一个最大的dpr限制,然后对其和系统的dpr做一个比较。

      然后依然为了方便阅读我把flexble.js这一部分的代码抽象出来,

          var doc = window.document
          var metaEl = doc.querySelector('meta[name="viewport"]');
      	var flexibleEl = doc.querySelector('meta[name="flexible"]');
      	var dpr = 0;
      	var scale = 0;			//缩放比例
      	//在meta标签中,已经有了viewport,则使用已有的viewport,并根据meta标签,对dpr进行设置
      	if (metaEl) {
      		console.warn('将根据已有的meta标签来设置缩放比例');
      		var match = metaEl.getAttribute('content').match(/initial\-scale=([\d\.]+)/);
      		if (match) {
      			scale = parseFloat(match[1]);
      			dpr = parseInt(1 / scale);
      		}
      	//如果在meta标签中,我们手动配置了flexible,则使用里面的内容
      	} else if (flexibleEl) {
      		var content = flexibleEl.getAttribute('content');
      		if (content) {
      			var initialDpr = content.match(/initial\-dpr=([\d\.]+)/);
      			var maximumDpr = content.match(/maximum\-dpr=([\d\.]+)/);
      			if (initialDpr) {
          			dpr = parseFloat(initialDpr[1]);
          			scale = parseFloat((1 / dpr).toFixed(2));    
      			}
      Copy after login

      if (maximumDpr) {
      dpr = parseFloat(maximumDpr[1]);
      scale = parseFloat((1 / dpr).toFixed(2));
      }
      }
      }

      这样,我们通过flexible的分析与获取,对dpr进行了书写。不过其实这里,是有个问题的。即在书写maximum的的情况下,其实根本没有像文档中给我们的说法一样,做一个比较,而是做了和initialDpr一样的一个处理。不过这里也不对其做一个探讨了。

      然后,这套解决方案,然后当我们在meta标签里面并没有对viewport以及flexible两个的任意一个进行书写的时候,他也是会自动获取一个dpr值的

      if (!dpr && !scale) {
      	var isAndroid = window.navigator.appVersion.match(/android/gi);
      	var isIPhone = window.navigator.appVersion.match(/iphone/gi);、
      	//devicePixelRatio这个属性是可以获取到设备的dpr的
      	var devicePixelRatio = win.devicePixelRatio;
      	if (isIPhone) {
      	// iOS下,对于2和3的屏,用2倍的方案,其余的用1倍方案
      	if (devicePixelRatio >= 3 && (!dpr || dpr >= 3)) {                
          	dpr = 3;
      	} else if (devicePixelRatio >= 2 && (!dpr || dpr >= 2)){
          	dpr = 2;
      	} else {
          	dpr = 1;
      	}
      } else {
      	// 其他设备下,仍旧使用1倍的方案
      	dpr = 1;
      	}
      	scale = 1 / dpr;
      }
      Copy after login

      这里我们可以看到,手机淘宝并没有对安卓的dpr进行一个适配,原因之后再讲。

      然后到了这里,我们获取到了我们需要的dpr值,并根据dpr值获取到了我们所需要的缩放值(即scale)

      然后我们要做的,就是在并没有viewport的meta标签对情况下自己动态将这个标签写进我们的header,形式是这样的

      <meta name="viewport" content="initial-scale=scale, maximum-scale=scale, minimum-scale=scale, user-scalable=no">
      Copy after login

      这样,dpr的配置,也就完成了,当然,安卓设备并没有对dpr进行一个配置(上面的动态生成就不给出js了)

    • 文字的解决方案

      由于手淘暂时并没有对安卓做一个处理,所以,这里,只是对iphone做了一个处理

      即在html上,加入了一个自定义属性,data-dpr。

      <html data-dpr=&#39;dpr&#39;></html>
      Copy after login

      还是以750的设计稿为例(即iphone6)

      假如设计稿上某a标签是32px,那么,我们要这么写

      a{
      	font-size: 16px
      }
      /*iphone6*/
      [data-dpr='2'] a{
      	font-size: 32px
      }
      /*iphone6plus*/
      [data-dpr='3'] a{
      	font-size: 32px
      }
      Copy after login
  • 现在的一些问题

    正如我们看到的,手淘目前的方案里面,是没有考虑到安卓dpr的问题的。即,这套方案,只对于iphone的r屏做了一个处理,而对于安卓,并没有做dpr的处理。我们来分析下原因吧(个人拙见)。

    我们希望字体能够以px来展现,同时,我们也希望我们的东西能对dpr做一个适配。对于ios,这自然是可行的,即采用了data-dpr的自定义属性来调整文字。4到6写一套字体大小,6p写一套字体大小,然后在对dpr为1的屏幕写一套字体大小。其实这种写法还是很恶心,不过基于对dpr的适配,这样写也算是个解决方案了。

    不过同样的解决方案到安卓就不行了,安卓的dpr有时候会很乱(比如现在在goole的手机测试里面可以看到,安卓的dpr,lg的某些设备还采用了1.7那样的奇怪dpr)。而当1.7dpr这种不规范的数字出现的时候,我们就不能采用之前的解决方案了,比如

    [data-dpr='1.7'] a{
    	font-size: 25px
    }
    Copy after login

    这样的东西是不可能去写的,那万一还有2.25,2.5之类的呢?我们都要拿去匹配么?

    其实现在,因为我们通过devicePixelRatio可以获取到安卓的dpr值,即可以做到对安卓设备的dpr一个匹配。但是,文字如果采用px的话,确实是很难做到匹配的。

    即总结一下,就是说,对于安卓的dpr匹配,目前来说,是没有什么问题的,但是,对于dpr匹配之后的字体,那肯定是有问题的。

    常见的dpr下的字体,我们依然可以解决,但是不常见的dpr,我们确实很难做到对dpr的解决。那如何解决这些问题呢。目前以我本人这个不太灵光的脑袋,确实也不晓得该如何进行一个处理了,起码做不到很好的解决。

    不过,还是丢上些个人的观点吧。

    在之前的对dpr的判断中,是根据了设备进行判断,即安卓不对dpr进行改变,仅对ios的设备进行改变。那么,我们其实可不可以以dpr的值来做一个处理呢?即像这样写

    if (!dpr && !scale) {
    	//devicePixelRatio这个属性是可以获取到设备的dpr的
    	var devicePixelRatio = win.devicePixelRatio;
    	//判断dpr是否为整数
    	var isRegularDpr = devicePixelRatio.toString().match(/^[1-9]\d*$/g)
    	if (isRegularDpr) {
    	// 对于是整数的dpr,对dpr进行操作
     	if (devicePixelRatio >= 3 && (!dpr || dpr >= 3)) {                
        	dpr = 3;
    	} else if (devicePixelRatio >= 2 && (!dpr || dpr >= 2)){
        	dpr = 2;
    	} else {
        	dpr = 1;
    	}
    } else {
    	// 对于其他的dpr,人采用dpr为1的方案
    	dpr = 1;
    	}
    	scale = 1 / dpr;
    }	
    Copy after login

    我们对这里做了一点点修改,即来判断dpr是否是规则的,也就是是否是我们常见的1,2,3等,然后,我们只对规则的dpr,来进行一个字体的处理。这样,iphone依然还是用之前的匹配方案。而其实目前安卓,很多的设备还是比较常见的dpr了,所以我们这里,将之前对设备的判断,转变成对dpr是否是整数的一个判断。其他地方不变,可以解决对安卓dpr的部分匹配。

    同样,开发的时候,如果并不在乎字体的问题的话,大可以直接使用rem。那样是可以做到dpr和文字都适配的问题。不过正如我们讲到字体的时候所说的,使用rem是很多用户不希望的(大屏机还是和小屏机看到一样多的内容),同时,还有点阵的问题。

    好,东西写到这里,也将近到了尾声。第一次写这么长的东西,感觉好累啊=_=。嗯还有篇2000字的检讨要写,默默匿了去写检讨了。

  • 参考

    手机淘宝的flexible设计与实现

    题外话:

    1. iphone6plus很有趣的地方

      iphone6plus照理来说的,其实际dpr是2.87左右的,不过,为了方便开发者来开发,iphone6plus对其做了一个调整,将dpr调整为3,然后在对屏幕进行了一个缩放。这样做,自然是方便了开发者前去开发,然而,这样做,也有了一些性能上的损失。(iphone为开发者考虑的还是挺周全的,看看隔壁安卓,dpr怎么爽怎么来,都特么自己玩自己的)

    2. 有意思的vh和vw

      vh,vw目前还存在很大程度的兼容性问题,所以还并没有采用。

      vh,vw有什么特点呢

      这两个元素分别会把屏幕上的可视高度(说通俗点就是你手机屏幕那个框框头装起的东西),宽度,分成100份来看,比如先前我们用rem来处理的地方,我们需要在html元素下写上font-size: 75px,然后再在div下写上width:1rem。而有了vh,vw之后,我们如此处理html的font-size就好。

      html {
      	font-size: 10vw;
      }
      Copy after login

      这样写,省去了一部js操作的步骤。

    The above is the detailed content of How to operate mobile page layout. For more information, please follow other related articles on the PHP Chinese website!

    Related labels:
    source:php.cn
    Statement of this Website
    The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
    Popular Tutorials
    More>
    Latest Downloads
    More>
    Web Effects
    Website Source Code
    Website Materials
    Front End Template
    About us Disclaimer Sitemap
    php.cn:Public welfare online PHP training,Help PHP learners grow quickly!