微信号:FrontDev

介绍:分享 Web 前端相关的技术文章、工具资源、精选课程、热点资讯

CSS镂空图片transition过渡初加载背景色块问题解决

2016-02-27 20:04 前端大全

(点击上方,可快速关注)

作者:张鑫旭(@张鑫旭) 

网址:http://www.zhangxinxu.com/wordpress/2016/02/css-hollow-image-for-transition-background-color-problem-fixed/


一、从哪里说起呢…


数年前写过一篇很实用的文章,介绍了一个很有创意的技术:“CSS背景色镂空技术实际应用及进阶”,讲的图标图形为了更容易控制其颜色,对图片采用了镂空的处理。例如,下面这张图片(点击会有随机的背景色):


于是,我们只要一套图片就可以实现各种颜色效果了!



而不要类似下面这样,为了各种状态凑齐完整的葫芦七兄弟:



除了节约图片资源大小,CSS镂空图片技术还有一个好处,就是由于我们的图标颜色是CSS属性控制的,因此,我们可以渐进使用transition实现过渡效果,让交互更细腻。


说到CSS控制图标颜色,我们自然而然会想到icon fonts, 或者使用SVG sprites技术,或者使用混合模式来实现。


然而,都是有不足的,比方说:


SVG的兼容性以及混合模式的理解成本和环境限制等。


因此,转了一圈,会发现,有时候,还是图片来得最实在,且看下面demo实现的效果,虽然使用的是background-image实现的,但是hover态,selected态都和文字hover transition过渡,这是传统背景图片所没法实现的。


您可以狠狠地点击这里:镂空背景图片下的transition过渡效果


一行:


transition: background-color .25s;


就可以让交互变得细腻!



default, hover, selected三种颜色态仅仅一个系列图片就搞定(见下图),看上去很赞,赞到飞起来。



然而,这种实现有一个致命的不足,就是CSS的加载和背景图片的加载不是同步的,尤其首次加载的时候,图片是异步的,具有明显的延迟,于是,我们会看到非常丑陋的色块在一瞬间出现了(大家可以强刷demo体验到)! 


正所谓“开发可忍设计不可忍”,这种问题显然是非常严重的,直接导致此看上去很酷的方法濒临夭折的边缘,看上去只适用于默认隐藏的元素。


大家莫慌莫慌,有我在呢!


二、base64 url图片与异步色块问题解决


这个很好理解,就是把背景图片转换成base64 url图片,因为是集成在CSS文件中的,因此,基本上是同时呈现,不会出现色块。然而,此方法局限性很明显,就是只适用于一些尺寸很小的小图。类似上面demo的背景图片,有5K多大小,直接内嵌在CSS文件中,就像是身体里长了个瘤子,太笨重了,而且base64渲染是比较烧性能的,图片越大越慢,且IE7浏览器很难支持base64图片。


因此,此方法在这里不适用,难道要天亡我也?非也!


三、content url图片与异步色块问题解决


6年前,也就是10年的时候,我在“CSS content内容生成技术以及应用”一文中首次介绍了CSS content url图片内容生成技术,就是before, after伪元素可以直接插入图片,注意,是直接图片,不是元素的背景图,语法如下:


.demo:after { content: url(xxx.png); }


OK, 大家如果观察过页面图片的加载,应该注意到这么个现象,就是如果图片没有通过HTML属性或者CSS值限定width/height宽高的时候,在浏览器get到图片的原始尺寸之前,图片占据的空间大小是0. 我们如果刷新浪微博,会发现页面高度蹭蹭蹭地往上涨,就是这么个原因,这种不对图片限定尺寸的做法在网页布局中是不推荐的,因为,会造成页面布局重绘,影响加载性能。


但是,存在必有道理,在这里,我们就可以好好地利用图片为加载时候占据空间为0的特性避免出现色块的问题,怎么解决呢?就是把元素的background-image url值变成伪元素的content url值;同时background-position定位改成其他定位,如relative定位,如下代码示意:


.icon {

    width: 140px; height: 140px;

    background: #c8c8c8 url(icon.png) no-repeat 0 -140px;

}

.icon {

    /* 注意,只设高度不设宽度 */

    height: 140px;

    background-color: #c8c8c8;

    overflow: hidden;

}

.icon:after {

    content: url(icon.png);

    position: relative;

    top: -140px;

}


上面绿色注释“只设高度不设宽度”点出了实现的关键:


页面渲染流程如下,1. CSS加载;2. 对应DOM渲染,背景色出现;3.拉取DOM样式对应背景图片。


传统实现就是从2到3的时候出现了问题,图片从服务器重新请求,导致了时间差,出现了色块。而我们这里的实现就不一样,当我们背景色出现,但是图片未加载的时候,由于我们的CSS没有设置元素的宽度,加上图片未加载占据宽度为0的特性,于是,在2完成3即将进行的时候,我们整个元素的高度140px, 宽度0,宽度是0啊!这意味着什么,意味着元素看不见啊,也即是虽然有背景色,无奈尺寸为0,我们是看不出有一丝丝背景色的;然后等图片请求到,自然就填满了元素,背景色也被遮掉了。没有了时间差,于是,完美解决了色块出现的问题!



您可以狠狠地点击这里:content url生成的解决色块问题demo(http://www.zhangxinxu.com/study/201602/hollow-content-url-transition.html)


IE7浏览器


什么年代了,还IE7浏览器,要是喜欢,可以使用expression表达式,或者直接JS打个补丁,小弟我现在对这些浏览器不奉陪了!


四、结束语


我测试发现,时间差似乎就Chrome浏览器比较明显,另外后面的content url有一定几率会出现最后一个有色块的情况,按照道理应该不会的,现在太晚了,都2点了,我有时间在研究研究。


【今日微信公号推荐↓】

更多推荐请看值得关注的技术和设计公众号


其中推荐了包括技术设计极客 和 IT相亲相关的热门公众号。技术涵盖:Python、Web前端、Java、安卓、iOS、PHP、C/C++、.NET、Linux、数据库、运维、大数据、算法、IT职场等。点击《值得关注的技术和设计公众号》,发现精彩!

 
前端大全 更多文章 5个典型的JavaScript面试题(上) Limu:JavaScript的那些书 Web开发:我希望得到的编程学习路线图 JavaScript基础工具清单 常用排序算法之JavaScript实现
猜您喜欢 【数据小鲜肉】魅族MX3 VS 小米M3 VS 锤子手机大比拼 双语 | 数据科学家抢了经济学家的饭碗吗? Android 开发者选项详述 互联网协议入门(一) Mono 生态系统未来可能的进化方向