layout 和 screen的宽度
在比较遥远的时候,网页还是在pc端流行,很少有人开发移动端网页,所有网页的宽度比较大。 随着移动端开发的慢慢崛起,我们就想把pc端的页面放到移动端也能正常的查看,但是手机屏幕那么小,怎么才能完全的显示整个页面的布局呢?
我们通过手机浏览器打开网页,尽然手机屏幕的大小改变不了,那么有没有一种办法,让手机浏览器的内部宽度变得和pc端的大小相近呢?浏览器的厂商开始发现了这个商机,纷纷的开始开发,终于达成了,在一般情况下,手机浏览器的内置宽度是980px。这样,我们用手机浏览器打开pc端的页面也可以看了,但是需要用户滚动和缩放才可以清除的查看网页,但是作为一个开发人员,对用户这么不友好,饭碗都没有了。
// iphone 7
document.documentElement.clientWidth // 980px
screen.width // 375px
上面提到了2个宽度,屏幕宽度(visual width)和手机浏览器内部宽度(layout width)
之后出现了<meta name='viewport>可以进行设置和开发, 下面再探讨。
通过meta改变layout width
我们从上面知道,如果不设置,浏览器默认的layout width的值是980px
,但是我们在移动端开发的时候,不希望用户非要通过方法页面和滚动页面来展示内容,有没有一种方法,让我们的在开发移动端页面的时候layout width和visual width一样呢?这样我们设置的css
的像素就会很清晰的反应在页面中。用户也可以不需要缩放的查看页面。
这个时候meta标签就登场了。
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
通过上面代码layout width===visual width。
initial-scale缩放什么
直接上公式:
initial-scale = layout width(布局宽度) / visual width(视口宽度)
我是这样理解的,如果我们设置了initial-scale = 0.5
,意味着缩小一半,那应该是什么缩小呢? 通过测试,我得到是页面的元素缩小了,例如:本来10px可以展示30长度,现在要缩小一半,10px不能变,30长度也不能变,要让30长度在layout width
中显示的区域缩小一半,只能是放大layout width了
动态REM移动端方案
1. 把html的font-size设置成设计稿的宽度
<meta name="viewport" content="width=device-width ,initial-scale=1,maximum-scale=1,minimum-scale=1" > <!--如果不设置width= device-width,则浏览器默认模拟的是980px-->
<script>
var css = `html{
font-size: 320px
}`
document.write(`<style>${css}</style>`)
<script>
- 设计稿页面的宽度 === 320px === html的font-size
- 1rem === html的font-size
- 由1和2 推出 1rem = 设计稿页面的宽度
2. 根据设备的尺寸调正html的font-size
把html的font-size*修改后的数据
<meta name="viewport" content="width=device-width ,initial-scale=1,maximum-scale=1,minimum-scale=1" > <!--如果不设置width= device-width,则浏览器默认模拟的是980px-->
<script>
var width = document.documentElement.clientWidth //如果不设置宽度,浏览器默认模拟的是980px
var scale = width/320;
console.log(scale)
var css = `html{
font-size: ${320*scale}px
}`
document.write(`<style>${css}</style>`)
</script>
- 实际页面的宽度 === ? === html的font-size
- 1rem === 实际页面的宽度
3. 设置好font-size后根据比例换成rem
统一根据自身尺寸/设计稿尺寸
来设置rem
- 由于1rem=320px(设计稿尺寸) ,所有我们需要把对应的比例px变成rem
- 例如原来的16px的margin-top,变成现在的16/320rem 是不是觉得会变得很小,不方便计算,所以又有一个方案,统一的把html的
font-size除以10
,然后我们在转换的时候再乘以10
<!-- 防止数据太小,统一变化下 -->
<script>
var width = document.documentElement.clientWidth //如果不设置宽度,浏览器默认模拟的是980px
var css = `html{
font-size: ${width/10}px
}`
document.write(`<style>${css}</style>`)
</script>
<!--使用css函数来统一变化rem-->
rem($px)
($px/320*10)rem
<!-- 是不是好奇为什么不除以100,因为除以100的话,font-size=320/100 = 3.2px -->
<!-- 3.2px???你想想浏览器的最小像素是多少?是多少?默认的是12px,你设置的话,最小也是6px,所以不行 -->
4. 结尾
到这里,其实已经做好了手机端的rem,但是由于设计师的职业病,就出现了border1px的小小小bug,你如果觉得1px不重要,到这里就可以了。下面我将要解析下设计师的处女座情节
相关文章
border-1px的问题
这个问题的来源
- 人有富贫,屏幕也一样,好的屏幕的dpr是不同的,展示在我们面前的色彩,清晰度都是不一样的。
- retina屏幕下,dpr = 2或3,但是在普通的屏下面dpr=1
dpr(设备像素比)
devicePixelRatio = 物理像素 / 独立像素
// 我们的css中的px === 独立像素
// 实际屏幕像素 === 物理像素
-
首先我们手机的分辨率高,就看的东西越仔细,这是为什么呢? 分辨率和我们的dpr又有什么联系呢?
在屏幕大小都差不多的情况下,一个分辨率为750的, 一个分辨率为640的手机,都要展示一个长度为30px的物体,让这个物体占有同样的面积,所以只有高分辨率(750)的1物理像素对应的独立像素多,也就是dpr高。不然的话,在同等dpr中,css的1px对应相同的物理像素,在750的分辨率中就会变小。
通过dpr,我们可以知道该设备上一个css像素代表多少个物理像素。例如,在Retina屏的iphone上,dpr的值为2,也就是说1个css像素相当于2个物理像素。
然后得说一下,为什么存在retina下,border: 1px这一说?
我们正常的写css,像这样border: 1px;
,在retina屏幕下,会有什么问题吗?
在retina屏幕下,我们设计师想要的1px,其实是1物理像素,但是对于css而言,只需要显示0.5px,但是在普通的屏下面的,css的0.5px会被默认的当成0px处理,这就是一个矛盾了。
解决border 1px
- 通过windon.devicePixelRatio获取页面的设备像素比
- 通过<meta name="viewport" content="width=device-width ,initial-scale=${scale},maximum-scale=${scale},minimum-scale=${scale}" > scale来缩放比例
var scale = 1 / window.devicePixelRatio; //获取对应的缩放比例 - 由于initial-scale的改变,引起了设备独立像素的改变,也就是document.documentElement.clientWidth的改变。第二步 把initial-scale变小了,引起了document.documentElement.clientWidth的变大对应的倍数,所以这一缩小,一放大就抵消了。
- 获取正确的document.documentElement宽度
<!-- 由于我们在meta中没有设置width=device-width 所以我们
通过document.documentElement.clientWidth获取的宽度是物理像素 * dpr
-->
<script>
var scale = 1 / window.devicePixelRatio; //获取对应的缩放比例
var meta = `<meta name="viewport" content="initial-scale=${scale}, maximum-scale=${scale}, minimum-scale=${scale} user-scalable=no">`
document.write(meta);
var width = document.documentElement.clientWidth
var css = `html{
font-size: ${width / 10}px
}`
document.write(`<style>${css}</style>`)
</script>