侯体宗的博客
  • 首页
  • Hyperf版
  • beego仿版
  • 人生(杂谈)
  • 技术
  • 关于我
  • 更多分类
    • 文件下载
    • 文字修仙
    • 中国象棋ai
    • 群聊
    • 九宫格抽奖
    • 拼图
    • 消消乐
    • 相册

移动端使用 rem 单位时 css sprites 定位问题的解决

前端  /  管理员 发布于 7年前   231

现在开发移动端 wap 页面,相信大家都会使用强大的 rem 单位去适配各种机型和屏幕;为了减少网络请求数量,提高网页访问性能,一般都会把多个小 icon 合并成一张 sprite 图,然后根据 background-position 进行定位;但是由于计算机的计算偏差,常常会导致 icon 的显示有1到2像素的偏差;

一、PC 端

如果在 PC 端,雪碧图的定位其实非常简单,不多说,直接上代码:

html 代码

<ul class="sprites-box">    <li class="icon icon-bill"></li>    <li class="icon icon-emailmsg"></li>    <li class="icon icon-import"></li>    <li class="icon icon-music"></li>    <li class="icon icon-pay"></li>    <li class="icon icon-search"></li>    <li class="icon icon-speak"></li>    <li class="icon icon-task"></li></ul>

css 代码

body, ul { margin: 0; }ul { padding: 50px; list-style: none; overflow: hidden; }li { float: left; margin: 10px; }.icon { background-image: url('./sprite.png'); }.icon-bill { background-position: -35px 0px;  width: 32px; height: 32px; }.icon-emailmsg { background-position: 0px -32px; width: 32px; height: 32px; }.icon-import { background-position: -32px -32px; width: 32px; height: 32px; }.icon-music { background-position: -67px 0px; width: 32px; height: 32px; }.icon-pay { background-position: 0px 0px; width: 35px; height: 32px; }.icon-search { background-position: -67px -32px; width: 32px; height: 32px; }.icon-speak { background-position: 0px -64px; width: 32px; height: 32px; }.icon-task { background-position: -32px -64px; width: 32px; height: 32px; }

效果

因为其使用 px 定位,且屏幕单位和倍率都是固定的,所以可以完美的实现雪碧图效果;

二、移动端

在移动端,由于各种机型的屏幕倍率,使得使用 px 作为单位的布局会有很大的适配问题,所以现在主流的适配方案就是使用 rem 作单位,并且根据屏幕倍率计算 rem 的基值进行适配;

本人是以宽为 750 的设计稿为基础,每 1rem 的值为设计稿中 100px 的长度; 由于 icon 的大小尺寸基本一致,故稍微做了点处理,裁切掉了 icon 的透明部分,合成尺寸不统一的 sprite 图;

1、直接转换为 rem 单位 换算后以上雪碧图的 css 代码为:

body, ul { margin: 0; }ul { padding: 0.5rem; list-style: none; overflow: hidden; }li { float: left; margin: 0.1rem; }.icon { background-image: url('./sprite.png'); background-size: 0.96rem 0.92rem; background-repeat: no-repeat; }.icon-bill { background-position: -0.67rem -0.26rem; width: 0.28rem; height: 0.26rem; }.icon-emailmsg { background-position: 0 -0.64rem; width: 0.26rem; height: 0.28rem; }.icon-import { background-position: -0.26rem -0.64rem; width: 0.26rem; height: 0.28rem; }.icon-music { background-position: -0.35rem 0; width: 0.32rem; height: 0.32rem; }.icon-pay { background-position: 0 0; width: 0.35rem; height: 0.32rem; }.icon-search { background-position: -0.32rem -0.32rem; width: 0.29rem; height: 0.27rem; }.icon-speak { background-position: 0 -0.32rem; width: 0.32rem; height: 0.32rem; }.icon-task { background-position: -0.67rem 0; width: 0.29rem; height: 0.26rem; }

效果:

细心留意可以看出,部分地方显示会有大概 1px 的偏差,这是由于不同手机计算偏差导致的,如果 icon 较为简单,可以接受这种效果也没关系,如果对 icon 显示的要求较高,则这种方式很明显不能达到要求;

2、转换为 rem 后通过 百分比进行定位

首先确认 background-position 使用百分比定位的概念:

属性值为百分比时,将以指定的点为重合点摆放雪碧图和显示 icon 的框。 简而言之,假设值为 10% 20%,则是将 sprite 图的 10% 20% 位置的点与显示框 10% 20% 的点重合(并不是 0% 0% 的点)

举个栗子:有一张 200X200 的 sprite 图,和一个 50X50 的 icon 显示框,这时如果设置 background-position: 0% 0%;

效果如下:

如果设置 background-position: 100% 100%; ,会先获取 icon 框 100% 100% 位置的点,和 sprite 图 100% 100% 位置的点,然后将其重合;

效果如下:

由此可知:其百分比定位的效果相当于先将 icon 框左上角的位置定位到 sprite 图 100% 100% 的位置,再往左上方回挪 icon 框 100% 100% 的位置;

这是在我们知道百分比的情况下实现的效果,而拿到 sprite 图的时候,我们往往知道的信息如下:

  1. 每个 icon 的大小
  2. sprite 图的大小
  3. 每个 icon 在 sprite 图中的定位

这时候我们就需要通过已知的条件计算出定位的百分比,这就变成了一道数学题:

已知 icon 宽高都为 50,sprite 宽高都为 200,icon 左上角在 sprite 内的坐标为 (50, 60),计算其 background-position ;

解:因为 background-position 定位的概念为 icon 框和 sprite 图各自指定位置重合;

设:sprite 宽为 W,高为 H,icon 宽为 w,高为 h,icon 在 sprite 中的坐标为 (x,y),得到百分坐标为 (m,n) 故可得到以下公式:

mW-mw=x => m(W-w)=x => m=x/(W-w)*100%

nH-nh=y => n(H-h)=y => n=y/(H-h)*100%

计算可得:

m=50/(200-50)*100%=33.3%

n=60/(200-50)*100%=40%

当然,公式是上面那样,如果写到 css 中,就需要配合 css 的计算方法 calc() 进行计算,如果对 calc 不明确的同学自行百度一下;如果同学使用 scss 或者 less 等 css 预编译器编写样式的就更简单了,直接写一个混入方法就搞定;

3、其他方式

每个小图标使用单张图片,再通过 background-size: cover|100%|contain; 也能完美的显示,但是一个页面的图标多的时候,请求就太多了,浏览器的并发请求数是有限制的,这样会导致网页的加载时间大大加长,不划算;

每个小图标转成 base64 图片,再直接写入代码:

优点:1. 完整显示图标;2. 减少请求数量;
缺点:1. 色彩丰富的图片转成 base64 效果不好;2. 会增大图片提及,相当于用下载时间换取请求时间;

好了,这篇分享就说到这里,初次写文章,语句和方式难免有瑕疵,望各位看客老爷见谅。也希望大家多多支持。


  • 上一条:
    CSS3地图动态实例代码(圆圈向外扩散)
    下一条:
    css实现各种0.5px的线(小结)
  • 昵称:

    邮箱:

    0条评论 (评论内容有缓存机制,请悉知!)
    最新最热
    • 分类目录
    • 人生(杂谈)
    • 技术
    • linux
    • Java
    • php
    • 框架(架构)
    • 前端
    • ThinkPHP
    • 数据库
    • 微信(小程序)
    • Laravel
    • Redis
    • Docker
    • Go
    • swoole
    • Windows
    • Python
    • 苹果(mac/ios)
    • 相关文章
    • 使用 Alpine.js 排序插件对元素进行排序(0个评论)
    • 在js中使用jszip + file-saver实现批量下载OSS文件功能示例(0个评论)
    • 在vue中实现父页面按钮显示子组件中的el-dialog效果(0个评论)
    • 使用mock-server实现模拟接口对接流程步骤(0个评论)
    • vue项目打包程序实现把项目打包成一个exe可执行程序(0个评论)
    • 近期文章
    • 智能合约Solidity学习CryptoZombie第四课:僵尸作战系统(0个评论)
    • 智能合约Solidity学习CryptoZombie第三课:组建僵尸军队(高级Solidity理论)(0个评论)
    • 智能合约Solidity学习CryptoZombie第二课:让你的僵尸猎食(0个评论)
    • 智能合约Solidity学习CryptoZombie第一课:生成一只你的僵尸(0个评论)
    • 在go中实现一个常用的先进先出的缓存淘汰算法示例代码(0个评论)
    • 在go+gin中使用"github.com/skip2/go-qrcode"实现url转二维码功能(0个评论)
    • 在go语言中使用api.geonames.org接口实现根据国际邮政编码获取地址信息功能(1个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf分页文件功能(0个评论)
    • gmail发邮件报错:534 5.7.9 Application-specific password required...解决方案(0个评论)
    • 欧盟关于强迫劳动的规定的官方举报渠道及官方举报网站(0个评论)
    • 近期评论
    • 122 在

      学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..
    • 123 在

      Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..
    • 原梓番博客 在

      在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..
    • 博主 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..
    • 1111 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
    • 2016-10
    • 2016-11
    • 2017-06
    • 2017-07
    • 2017-08
    • 2017-09
    • 2017-10
    • 2017-11
    • 2018-03
    • 2018-04
    • 2018-05
    • 2018-06
    • 2018-09
    • 2018-11
    • 2018-12
    • 2019-02
    • 2020-03
    • 2020-04
    • 2020-05
    • 2020-06
    • 2021-04
    • 2021-05
    • 2021-07
    • 2021-08
    • 2021-09
    • 2021-10
    • 2021-11
    • 2022-08
    • 2022-09
    • 2022-10
    • 2022-11
    • 2022-12
    • 2023-01
    • 2023-02
    • 2023-03
    • 2023-04
    • 2023-05
    • 2023-06
    • 2023-07
    • 2023-09
    • 2023-10
    • 2023-11
    • 2023-12
    • 2024-01
    • 2024-02
    • 2024-03
    • 2024-04
    Top

    Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号 PHP交流群

    侯体宗的博客