移动端的1px问题
布局视口 layout viewport:
手机一般为了容纳为桌面浏览器设计的网站,默认布局viewport宽度远大于屏幕的宽度,为了让用户看到网站全貌,缩小网站。例如,apple一般将viewport宽度定为980px。主要意义是手机厂商不至于让自家手机变得可笑,在打开大于980宽度的页面的时候可以横向拖动,而不至于挤成一团。可以通过
document.documentElement.clientWidth
来获取。视觉视口 visual viewport:
屏幕的可视区域,即物理像素尺寸,可以通过window.innerWidth来获取。对于iPhone 6 Plus来说,在加了著名代码前提下,值是414px,不加的话,值是980px,著名代码如果改一改
width=device-width, initial-scale=1.5
,这时值是276px。所以它是一个可变的值。理想视口 ideal viewport:
最适合移动设备的viewport,ideal viewport的宽度等于移动设备的屏幕宽度
为了让viewport能够等于ideal viewport,一般我们会添加meta标签。
width=device-width,initial-scale=1.0
的时候,视觉视口的大小。对于iPhone 6 Plus来说,是固定值414px。所以,理想视口就等于设备宽度。
1、什么是1px问题
移动端css设置1px(如border:1px solid #000;),实际上边框的宽度比设置的1px要宽
2、移动端1px变宽原因
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
这句话定义了本页面的viewport的宽度为设备宽度,初始缩放值和最大缩放值都为1,并禁止了用户缩放. viewport通俗的讲是浏览器上可用来显示页面的区域, 这个区域是可能比屏幕大的.
3、1px解决方案
(1) 用小数写1px
//这是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 } }
//如果使用less/sass的话只是加了1句mixin
//缺点: IOS8下已经支持带小数的px值,安卓与低版本IOS不适用, 这个或许是未来的标准写法, 现在不做指望
//这是JavaScript方式
<body> <div id="main" style="border: 1px solid #000000;"></div> </body> <script type="text/javascript"> if (window.devicePixelRatio && devicePixelRatio >= 2) { var main = document.getElementById('main'); main.style.border = '.5px solid #000000'; } </script>
//优点: 简单
//缺点: 兼容性差,目前之余IOS8+才支持,在IOS7及其以下、安卓系统都是显示0px。
(2)使用border-image(但要注意这个属性的兼容性):不推荐
//第一种写法 使用媒体查询 @media screen and (-webkit-min-device-pixel-ratio: 2){ .border{ border: 1px solid transparent; border-image: url(border.gif) 2 repeat; } } //第二种写法 直接用类名 .border { border-width: 1px 0px; -webkit-border-image: url(border.png) 2 0 stretch; border-image: url(border.png) 2 0 stretch; }
(3)使用background渐变(但要注意这个属性的兼容性)设置1px的渐变背景,50%有颜色,50%透明--->背景渐变, 渐变在透明色和边框色中间分割
//第一种方式:媒体查询
@media screen and (-webkit-min-device-pixel-ratio: 2){ .border{ background-position: left top; background-image: -webkit-gradient(linear,left bottom,left top,color-stop(0.5,transparent),color-stop(0.5,#e0e0e0),to(#e0e0e0)); } }
//缺点: 代码量大, 而且需要针对不同边框结构,而且这只是背景, 这样做出来的边框实际是在原本的border空间内部的, 如果元素背景色有变化的样式, 边框线也会消失;不适应圆角样式
//第二种方式:直接类名
.border { background: linear-gradient(180deg, black, black 50%, transparent 50%) top left / 100% 1px no-repeat, linear-gradient(90deg, black, black 50%, transparent 50%) top right / 1px 100% no-repeat, linear-gradient(0, black, black 50%, transparent 50%) bottom right / 100% 1px no-repeat, linear-gradient(-90deg, black, black 50%, transparent 50%) bottom left / 1px 100% no-repeat; }
(4)会用 :before , :after 与 transform(推荐使用)
原理:把原先元素的 border 去掉,然后利用 :before 或者 :after 重做 border ,并 transform 的 scale 缩小一半,原先的元素相对定位,新做的 border 绝对定位。
//第一种方法
//构建1个伪元素, 将它的长宽放大到2倍, 边框宽度设置为1px, 再以transform缩放到50%
.radius-border{ position: relative; } @media screen and (-webkit-min-device-pixel-ratio: 2){ .radius-border:before{ content: ""; pointer-events: none; /* 防止点击触发 */ box-sizing: border-box; position: absolute; width: 200%; height: 200%; left: 0; top: 0; border-radius: 8px; border:1px solid #999; -webkit-transform(scale(0.5)); -webkit-transform-origin: 0 0; transform(scale(0.5)); transform-origin: 0 0; } }
//需要注意<input type="button">是没有:before, :after伪元素的
//优点: 其实不止是圆角, 其他的边框也可以这样做出来
//缺点: 代码量也很大, 占据了伪元素, 容易引起冲突
//第二种方式 //单条border样式设置: .scale-1px{ position: relative; border:none; } .scale-1px:after{ content: ''; position: absolute; bottom: 0; background: #000; width: 100%; height: 1px; -webkit-transform: scaleY(0.5); transform: scaleY(0.5); -webkit-transform-origin: 0 0; transform-origin: 0 0; } //四条border样式设置: .scale-1px{ position: relative; margin-bottom: 20px; border:none; } .scale-1px:after{ content: ''; position: absolute; top: 0; left: 0; border: 1px solid #000; -webkit-box-sizing: border-box; box-sizing: border-box; width: 200%; height: 200%; -webkit-transform: scale(0.5); transform: scale(0.5); -webkit-transform-origin: left top; transform-origin: left top; } //结合js来代码来判断是否是Retina屏 if(window.devicePixelRatio && devicePixelRatio >= 2){ document.querySelector('div').className = 'scale-1px'; } //优点:所有场景都能满足 支持圆角 //缺点:对于已经使用伪类的元素,可能需要多层嵌套
(5)使用flexible.js(https://github.com/amfe/lib-flexible)
原理:viewport宽度设置为实际的设备物理宽度,
(6)使用CSS3 box-shadow
.shadow { -webkit-box-shadow:0 1px 1px -1px rgba(255, 0, 0, 0.5); box-shadow:0 1px 1px -1px rgba(255, 0, 0, 0.5); } //不好用,不推荐
(7)viewport结合rem
//devicePixelRatio=2设置meta <meta name="viewport" content="initial-scale=0.5, maximum-scale=0.5, minimum-scale=0.5, user-scalable=no">
//devicePixelRatio=3设置meta <meta name="viewport" content="initial-scale=0.3333333333333333, maximum-scale=0.3333333333333333, minimum-scale=0.3333333333333333, user-scalable=no">
参考文献:
https://www.cnblogs.com/lunarorbitx/p/5287309.html
https://blog.csdn.net/xuexizhe88/article/details/80566552
本文为自己知识点搜索整理,若有侵权麻烦联系我,删除本文章。谢谢(* ̄︶ ̄)