Open muwoo opened 6 years ago
理想视窗的观点应该不对吧,这个应该是浏览器自己决定的,并不是计算公式出来的。另外,设置initial-scale和设置width的功能接近,都是用来设置layout viewport的宽度的,为什么要先产生visual viewport?我认为visual viewport是浏览器默认为了显示全部内容,所以第一次加载页面的时候将visual viewport设置成layout viewport的宽度,当你缩放页面后再刷新,它会保留上次visual viewport的宽度,和meta里面的值并没有什么关系。
@lisalin880505 感谢,已纠正
所以开头的问题是一个是逻辑像素一个是物理像素对吗?还有一个疑问是使用安卓模拟器时,我调整不同的DPR后,页面没有任何改变
最近一直在看一些手淘移动端适配rem之类的技术方案,在研究这些技术方案之前,首先需要掌握一些基本的单位概念,所以在网上也搜了一些资料。虽然全部看下来还是存在一些疑惑的地方,在此做一下记录。
有趣的问题
人物:前端实习生「阿树」与 切图工程师「玉凤」 事件:设计师出设计稿,前端实现页面
玉凤:树,设计稿发给你啦,差那么点像素,就叼死你┏(  ̄へ ̄)=☞ 阿树:(>_<)没问题啦~ 阿树:哇靠,为啥你给的设计稿是750px宽 ,iPhone 6不是375px宽吗??? 玉凤:A pixel is not a pixel is not a pixel, you know ? 阿树:(#‵′),I know Google。。。
为什么会出现以上的情况,难道他们当中一位出错了,摆了这样的乌龙? 事实上,他们都是对的,只是谈的不是同一个「像素」。
1. dp (设备像素)
1.1 概念
2. px (CSS pixels)
比如iPhone 6使用的是Retina视网膜屏幕,使用2px x 2px的 device pixel 代表 1px x 1px 的 css pixel,所以设备像素数为750 x 1334px,而CSS逻辑像素数为375 x 667px。
3. dpr(Device Pixel Ratio) 设备像素比
设备像素比表示1个CSS像素(宽度)等于几个物理像素(宽度):
比如dpr=2时,1个CSS像素宽度等于2个物理像素宽度。1css像素由2 * 2个物理像素点组成,见上面对CSS像素的解释。DPR不是单位,而是一个属性名,比如在浏览器中通过
window.devicePixelRatio
获取屏幕的DPR。4. ppi (pixel per inch)每英寸的像素数,像素密度。
5. viewport 视窗
在桌面浏览器中,viewport就是浏览器窗口的宽度高度。 但移动设备的屏幕比桌面屏幕要小得多,为了要让网页在小尺寸的屏幕上显示正确,就需要对viewport做些处理。需要把viewport分成两部分:
visual viewport
和layout viewport
。George Cummins在Stack Overflow上对这两个概念做了分析。大致意思如下:5.1 visual viewport
visual viewport是页面当前显示在屏幕上的部分。用户可以通过滚动来改变他所看到的页面的部分,或者通过缩放来改变visual viewport的大小。
5.2 layout viewport
layout viewport就是页面原来的大小。 但是我们用在手机用浏览器打开PC的网页的时候,会看到网页被浏览器自动缩小了,变的太小会导致无法浏览内容。
5.3 idea viewport
布局视口的默认宽度并不是一个理想的宽度,大家从上面的图就可以看出来了,所以苹果公司就引进了理想窗口这个概念:
注意:
width=device-width
或者initial-scale=1.0
),就没问题了。5.4 viewport meta标签
为了不让浏览器自动缩小,引入了viewport元标签。通过这个元标签控制layout viewport的宽度。
上面这行代码就是告诉浏览器,布局视口的宽度应该与理想视口的宽度一致。
注意下图片中的红色框,第二张图片内容超了出来,应该是给文字设置了宽度,并且这个宽度大于layout viewport导致了出来。但其实在Android和IOS中会有不一样的表现。在文章《A tale of two viewports》中指出:
移动端 1px 像素问题
一直以来我们实现边框的方法都是设置
border: 1px solid #ccc
,但是在 retina 屏上因为设备像素比(dpr)的不同,边框在移动设备上的表现也不相同: 1px 可能会被渲染成 2px, 3px....也就是说逻辑像素1px会被用不同大小的物理像素来表示。(这里只介绍几种常用的方式,更多可以自行Google)rem + viewport
按照上面这种表述,首先想到的最快解决这种问题的肯定是根据dpr不同来进行缩放就好了,这种方式也就是常说的
rem + viewpor
。关于rem的介绍可以参考这里。核心的实现如下:大概意思就是设置网页根字体 font-size 为
37.5 * dpr
,这样根据 rem 产出的网页就会被放大 dpr 倍,此时css里面写的还是1px
,然后再通过initial-scale= 1 / dpr
来对网页进行缩小dpr倍。这样 1px 就会显示成1 / dpr
px。border-image 实现
这篇文章是腾讯github上的解决方案border-image来实现的。缺点是,你需要制作图片,圆角的时候会出现模糊。
border.png
也可以用 base64 图片替代。background-image 渐变实现
除啦用图片,难道纯粹的css就不能实现吗?我的确不想使用图片,感觉制作起来很麻烦,其实百度糯米团首页就是这么做的但是这种方法有个缺点,就是不能实现圆角
box-shadow 实现
利用阴影我们也可以实现,那么我们来看看阴影,优点是圆角不是问题,缺点是颜色不好控制。
伪类 + transform 实现
原理是把原先元素的
border
去掉,然后利用:before
或者:after
重做border
,并 transform 的 scale 缩小一半,原先的元素相对定位,新做的 border 绝对定位。 单条border样式设置(其他的类似):优点可以实现圆角,京东就是这么实现的。缺点是按钮添加active比较麻烦,对于已经使用伪类的元素(例如clearfix),可能需要多层嵌套。