首页 > 其他分享 >【转载】移动端1px误差的原因以及解决方案

【转载】移动端1px误差的原因以及解决方案

时间:2023-02-14 23:45:55浏览次数:59  
标签:误差 scale 解决方案 0.5 transform 1px border viewport

版权声明:本文为CSDN博主「开心大表哥」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/a419419/article/details/80217328
————————————————

移动端1px问题在面试和工作中会经常遇到,系统地理解它是一个优秀前端的必修课!

为什么移动端css里面写了1px, 实际看起来比1px粗. 其实原因很好理解:这2个’px’的含义是不一样的. 移动端html的header总会有一句

<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">

这句话定义了本页面的viewport的宽度为设备宽度,初始缩放值和最大缩放值都为1,并禁止了用户缩放。
手机存在一个能完美适配的理想viewport, 分辨率相差很大的手机的理想viewport的宽度可能是一样的, 这样做的目的是为了保证同样的css在不同屏幕下的显示效果是一致的, viewport的好处就在于一套css可以适配多个机型。

在window对象中有一个devicePixelRatio属性,他可以反应css中的像素与设备的像素比。然而1px在不同的移动设备上都等于这个移动设备的1px,这是因为不同的移动设备有不同的像素密度。有关这个属性,它的官方的定义为:设备物理像素和设备独立像素的比例,也就是

devicePixelRatio = 物理像素 / 独立像素

1px变粗的原因: viewport的设置和屏幕物理分辨率是按比例而不是相同的. 移动端window对象有个devicePixelRatio属性, 它表示设备物理像素和css像素的比例, 在retina屏的iphone手机上, 这个值为2或3, css里写的1px长度映射到物理像素上就有2px或3px那么长。

解决方案

  1. rem解决:
根据屏幕大小及dpi调整缩放和大小  
(function () {
        var scale = 1.0;
        var ratio = 1;
        if (window.devicePixelRatio >= 2) {
            scale *= 0.5;
            ratio *= 2;
        }
        var text = '<meta name="viewport" content="initial-scale=' + scale + ', maximum-scale=' + scale + ',' + ' minimum-scale=' + scale + ', width=device-width,' + ' user-scalable=no" />
';
        document.write(text);
        document.documentElement.style.fontSize = 50 * ratio + "px";
    })();

  1. flexible.js
    这是淘宝移动端采取的方案, github的地址:https://github.com/amfe/lib-flexible. 前面已经说过1px变粗的原因就在于一刀切的设置viewport宽度, 如果能把viewport宽度设置为实际的设备物理宽度, css里的1px不就等于实际1px长了么. flexible.js就是这样干的。

<meta name=”viewport”>里面的scale值指的是对ideal viewport的缩放, flexible.js检测到IOS机型, 会算出scale = 1/devicePixelRatio, 然后设置viewport

metaEl = doc.createElement('meta');
metaEl.setAttribute('name', 'viewport');
metaEl.setAttribute('content', 'initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no');

  1. 伪类+transform实现
    对于解决1px边框问题,我个人觉得最完美的解决办法还是伪类+transform比较好。
    原理:是把原先元素的 border 去掉,然后利用 :before 或者 :after 重做 border ,并 transform 的 scale 缩小一半,原先的元素相对定位,新做的 border 绝对定位。
    来看一个控制各条边的常用实例:
<html>
	<body>
	<div class="btn normal">normal</div>
	<div class="btn all">all</div>
	<div class="btn top">top</div>
	<div class="btn bottom">bottom</div>
	<div class="btn left">left</div>
	<div class="btn right">right</div>
	<style>
		body{
			text-align: center;
		}
		.normal{
			border: 1px solid #DDDDDD;
		}
		.btn{
			width: 70px;
			height: 30px;
			margin-top: 10px;
			position: relative;
			margin-left: 100px;
		}
		.all::after{
          content: '';
          position: absolute;
          pointer-events: none; /* 元素永远不会成为鼠标事件的target。 */
          top: -50%;
          bottom: -50%;
          left: -50%;
          right: -50%;
          -webkit-transform: scale(0.5);
          transform: scale(0.5);
          border: 1px solid #DDDDDD;
        }
		.top:after{
			content: '';
			position: absolute;
			top: 0;
			left: 0;
			right: 0;
			-webkit-transform: scale(1, 0.5);
			transform: scale(1, 0.5);
			border-top: 1px solid #DDDDDD;
		}
		.bottom:after{
			content: '';
			position: absolute;
			bottom: 0;
			left: 0;
			right: 0;
			-webkit-transform: scale(1, 0.5);
			transform: scale(1, 0.5);
			border-bottom: 1px solid #DDDDDD;;
		}
		.left:after{
		  content: '';
		  display: block;
		  position: absolute;
		  top: 0;
		  bottom: 0;
		  left: 0;
		  -webkit-transform: scale(0.5, 1);
		  transform: scale(0.5, 1);
		  border-left: 1px solid #DDDDDD;
		}
		.right:after{
          content: '';
          display: block;
          position: absolute;
          top: 0;
          bottom: 0;
          right: 0;
          -webkit-transform: scale(0.5, 1);
          transform: scale(0.5, 1);
          border-right: 1px solid #DDDDDD;
		}
	</style>
	</body>
</html>

由于所有的边都列出来了,所以就不一一说明了,复制到项目里面就可以用了!
不过对于input、texteara这类不能插入伪元素dom应该如何处理呢?
方案:
将伪元素换成一个div,然后通过position:absolute将这个div与input的位置重合,将input的border设为0就可以了!

标签:误差,scale,解决方案,0.5,transform,1px,border,viewport
From: https://www.cnblogs.com/wanglei1900/p/17121247.html

相关文章

  • 白嫖一个WebAPI限流解决方案
    什么是API限流:API限流是限制用户在一定时间内API请求数量的过程。应用程序编程接口(API)充当用户和软件应用程序之间的网关。例如,当用户单击社交媒体上的发布按钮时,......
  • PHP上传大文件的三种解决方案
    ​PHP用超级全局变量数组$_FILES来记录文件上传相关信息的。1.file_uploads=on/off 是否允许通过http方式上传文件2.max_execution_time=30 允许脚本最大执行时间......
  • JSP上传大文件的三种解决方案
    ​ 在Web应用系统开发中,文件上传和下载功能是非常常用的功能,今天来讲一下JavaWeb中的文件上传和下载功能的实现。先说下要求:PC端全平台支持,要求支持Windows,Mac,Linux......
  • Web上传大文件的三种解决方案
    ​ 前言:因自己负责的项目(jetty内嵌启动的SpringMvc)中需要实现文件上传,而自己对java文件上传这一块未接触过,且对Http协议较模糊,故这次采用渐进的方式来学习文件上传的......
  • JavaScript 大文件上传下载解决方案
    ​ javaweb上传文件上传文件的jsp中的部分上传文件同样可以使用form表单向后端发请求,也可以使用ajax向后端发请求    1.通过form表单向后端发送请求     ......
  • centos7下远程图形化浏览器解决方案
    背景:越来越多的项目会首选linux作为基础系统,一般情况下客户提供的都是没有图像化的linux,但有些配置需要通过浏览器来修改并查看(比如nacos,roketmq-admin等),因此便需要centos......
  • JS 大文件上传下载解决方案
    ​前言一、SpringMVC简介1.1、SpringMVC引言为了使Spring有可插入的MVC架构,SpringFrameWork在Spring基础上开发SpringMVC框架,从而在使用Spring进行WEB开发时可以......
  • SQL Server 只有数据库文件,没有日志文件,恢复数据时报1813错误的解决方案
    无法打开新数据库'ASR'。CREATEDATABASE中止。文件激活失败。物理文件名称'E:\SqlServer\MSSQL\Data\ASR_log.LDF'可能不正确。无法重新生成日志,原因是数据库关闭时存......
  • VUE 项目大文件上传下载解决方案
    ​ 一、基本介绍 1,什么是WebUploader?WebUploader是由百度公司团队开发的一个以HTML5为主,FLASH为辅的现代文件上传组件。官网地址:http://fex.baidu.com/webuploa......
  • B端业务架构解决方案
    在B端业务中常见系统模块分类为:cms系统,crm系统,会员系统,订单管理,采购管理,wms仓储管理,财务管理,供应商管理,质检系统等;常见服务:文件图片上传服务,物流服务,商品搜索服务,订单服......