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

如今开发移动端 wap 页面,相信你们都会使用强大的 rem 单位去适配各类机型和屏幕;为了减小网络请求数量,提升网页访问性能,通常都会把多个小 icon 合并成一张 sprite 图,而后根据 background-position 进行定位;可是因为计算机的计算误差,经常会致使 icon 的显示有1到2像素的误差;css

1、PC 端

若是在 PC 端,雪碧图的定位其实很是简单,很少说,直接上代码:html

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 代码bash

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; }
复制代码

效果网络

sprite

由于其使用 px 定位,且屏幕单位和倍率都是固定的,因此能够完美的实现雪碧图效果;并发

2、移动端

在移动端,因为各类机型的屏幕倍率,使得使用 px 做为单位的布局会有很大的适配问题,因此如今主流的适配方案就是使用 rem 做单位,而且根据屏幕倍率计算 rem 的基值进行适配;less

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

一、直接转换为 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; }

复制代码

效果:ui

sprite_mobile1

细心留意能够看出,部分地方显示会有大概 1px 的误差,这是因为不一样手机计算误差致使的,若是 icon 较为简单,能够接受这种效果也不要紧,若是对 icon 显示的要求较高,则这种方式很明显不能达到要求;

二、转换为 rem 后经过 百分比进行定位

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

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

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

效果以下:

position0%0%

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

效果以下:

position100%100%ready
position100%100%result

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

这是在咱们知道百分比的状况下实现的效果,而拿到 sprite 图的时候,咱们每每知道的信息以下:

  • 每一个 icon 的大小
  • sprite 图的大小
  • 每一个 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 预编译器编写样式的就更简单了,直接写一个混入方法就搞定;

三、其余方式

  • 每一个小图标使用单张图片,再经过 background-size: cover|100%|contain; 也能完美的显示,可是一个页面的图标多的时候,请求就太多了,浏览器的并发请求数是有限制的,这样会致使网页的加载时间大大加长,不划算;
  • 每一个小图标转成 base64 图片,再直接写入代码:
    • 优势:1. 完整显示图标;2. 减小请求数量;
    • 缺点:1. 色彩丰富的图片转成 base64 效果很差;2. 会增大图片说起,至关于用下载时间换取请求时间;

好了,这篇分享就说到这里,初次写文章,语句和方式不免有瑕疵,望各位看客老爷见谅。

相关文章
相关标签/搜索