zoukankan      html  css  js  c++  java
  • 一个标签的72变,打造一个纯CSS图标库

    每次要用到图标的时候都会到 icono 去copypaste,但每次用到的时候尺寸都各不一样,总是要调整参数,巨烦。当然你可以会想到用zoom、scale来做缩放,但是这样的缩放会使得线宽也变粗了,不甚满意。

    终于下定心思来改造一个可缩放的图标库。github先上:https://github.com/qieguo2016/iconoo目前提供下载link标签引入和npm+webpack的引入方式,详见项目的readme。(喂,来个star!)。上图:

    关于改造,一开始的想法就是使用百分比尺寸来改造,然后马上发现不可行了,绘制图标最依赖的两种手段:border、box-shadow都不可以用百分比,所以这个想法,pass!然后很自然就想到了在单位上做文章,rem?No、No、No,一个库依赖全局变量那简直是个笑话。剩下的自然就是em了,在icon级设置font-size,然后icon本身以及后代都以这个font-size为参照,Perfect!

    CSS绘图的原理

    使用CSS绘制线条,用到的不外乎两个属性:border & box-shadow。而形状则可以用border-radius、transform控制,位置会用到绝对定位、transform、margin等。CSS的绘图,做过几个就知道大概是怎么回事了,归根到底,还是几何。

    比如最简单的加号:

     1 .plus {
     2     box-sizing : border-box;
     3     display : inline-block;
     4     position : relative;
     5     font-size : 20px;
     6 }
     7 
     8 .plus:before, plus:after {
     9     content : '';
    10     pointer-events : none;
    11     position : absolute;
    12     left : 50%;
    13     top : 50%;
    14     transform : translate(-50%, -50%);
    15     box-shadow : inset 0 0 0 1em;
    16 }
    17 
    18 .plus:before {
    19     width : 1em;
    20     height : 2px;
    21 }
    22 
    23 .plus:after {
    24     height : 1em;
    25     width : 2px;
    26 }
    View Code

    实现非常简单,通过设置两个伪类的宽高形成横竖两个小矩形,接着用阴影填充满,这样一个加号必需的图形就出来了。然后就是调整位置了,将这两个矩形居中,加号就出来了。具体是通过绝对定位+反向偏移的方式,巧妙利用了这两个属性百分比参照的不同实现居中。尺寸方面,所有尺寸除了线宽(2px)外都使用em这个相对单位,所以调整font-size的值就可以调整图标的大小了。如果要调整线宽,那就需要改变这个2px了,引入less、sass将线宽定义成变量就可以很方便地改变线宽了。

    CSS的各种玩法

    原理虽然简单,但是很多图标还是相当有意思的,通过分析这些图标也能加深对css的认识。例如:

    这个图形网上说的应该还是比较多的了,第一眼看到懵逼了。。。分析一下,最外层的边框明显可以用border来做,然后用个before来做圆点也非常简单,关键是两座大山要如何绘制呢?box-shadow貌似可以做多层边框呢,然后加个旋转是不是就出来了呢?绘制流程如下:

    上CSS代码吧:

     1 .icon-test {
     2     display: inline-block;
     3     position: relative;
     4     box-sizing: border-box;
     5     width: 90px;
     6     height: 80px;
     7     border: 5px solid;
     8     border-radius: 10px;
     9     color: #2ba5bb;
    10     overflow: hidden;
    11 }
    12 
    13 .icon-test:before,.icon-test:after {
    14     content: '';
    15     pointer-events: none;
    16     position: absolute;
    17 }
    18 
    19 .icon-test:before {
    20     width: 10px;
    21     height: 10px;
    22     top: 18px;
    23     right: 20px;
    24     box-shadow: inset 0 0 0 1em;
    25     border-radius: 50%;
    26 }
    27 
    28 .icon-test:after {
    29     width: 60px;
    30     height: 50px;
    31     left: 0;
    32     bottom: -27px;
    33     box-shadow: inset 0 0 0 50px,30px -20px 0 0;
    34     transform: rotate(45deg);
    35 }
    View Code

    再来一个:

    看起来跟上一个有点像,然而,按照上一个的绘制方式却怎么也画不出来~~~还是分解几步来画,边框很容易解决,一个box-shadow就完事。这两座大山其实形状都一样,都是一个三角形下接一个矩形,三角形显然可以用border来画,而矩形用box-shadow就可以了!这里还用了透明border来做左侧和下侧的留白,比直接用尺寸对齐要好很多。

     1 .icon-test {
     2     display: inline-block;
     3     position: relative;
     4     box-sizing: border-box;
     5     color: #2ba5bb;
     6     width: 60px;
     7     height: 40px;
     8     border-top-width: 0;
     9     border-right-width: 0;
    10     border: 4px solid;
    11     border-color: transparent;
    12     box-shadow: -4px 5px;
    13     overflow: hidden;
    14 }
    15 
    16 .icon-test:before,.icon-test:after {
    17     content: '';
    18     pointer-events: none;
    19     position: absolute;
    20 }
    21 
    22 .icon-test:before {
    23     left: 0;
    24     bottom: 8px;
    25     border: 14px solid transparent;
    26     border-bottom-color: currentColor;
    27     box-shadow: 0 16px;
    28 }
    29 
    30 .icon-test:after {
    31     left: 28px;
    32     bottom: 9px;
    33     border-width: 0 9px 21px;
    34     border-style: solid;
    35     border-color: transparent transparent currentColor;
    36     box-shadow: 0 17px;
    37 }
    View Code

    怎么样?觉得这些都是小玩意?好吧,都让开,我要开始装逼了!

     
     

    蒙娜丽莎?什么鬼?我会告诉你这也是一个单标签纯CSS画出来的吗?

    几千条box-shadow构成的蒙娜丽莎,看的我内分泌都失调了。。。

    (author:Jay Salvat, 来源:http://codepen.io/jaysalvat/pen/HaqBf )

    如此变态的绘图,都没有怎么用到CSS中最强大的变形,如果加入变形,那可以画出来的形状就更多了。。。更多CSS玩意儿,请到codepen上去探宝吧!

    PS: 蒙娜丽莎这种图形,可以读取原图信息转换成单位面积的box-shadow,前端用canvas就可以做的,其实这货的技术含量比一个图片图标还要少呢。话虽如此,复杂图形使用CSS来绘制的话,性价比还是太低,建议还是使用图片,这样会更具表现力一些,操作起来也更加简单!专业的绘图还是交给专业的UI去做吧!

    大大小小的坑

    其实,遇到的这些都不能叫做坑,是自己对CSS的理解度不够而已。原以为,将原来icono使用的单位换算成em就算完事了,然而,一改font-size就变形了,顿时懵逼!究其原因,其实也很简单,并不是所有地方与font-size都是正比的,很多地方混入了线宽的影响,所以要剔除线宽的影响。

    去除线宽影响的方法不外乎两种:

    1)去掉线宽,例如使用box-shadow等不影响尺寸的属性

    2)将线宽纳入计算内,比如translate反向偏移掉线宽,这样整体缩放就不会受到线宽的影响了。

    另外一个比较烦的就是居中,其实居中基本上就只用到了下面两种方式,还是蛮简单的。只是,这个反复的copypaste,烦哪!

    1. 绝对定位+margin:auto。

    position: absolute;
    left: 0;
    right: 0;
    top: 0;
    bottom: 0;
    margin: auto;

    实现原理:利用css定位规则,设置左右、上下方向定位为0,margin为auto,让css根据定位计算margin值,用hack的方式实现居中。居中块的尺寸需要可控,因为css计算margin时也需要参考尺寸值,由于四周为0,所以自动计算得到的盒子尺寸(含margin)是与父容器一样的。无论是设置居中块的width、height或者是max-height、max-width,都是让尺寸不会扩大到与父级一样。

    局限:在参考系父级(position!=static)大小比本身要小的时候,水平方向的居中就会失效。(垂直方向依然居中)

    2. 绝对定位 + transform反向偏移。

    position: absolute;
    top: 50%; left: 50%;
    transform: translate(-50%, -50%);
    margin: auto; 

    实现原理:先绝对定位相对父级偏移50%,然后使用transform来反向偏移。由于transform的计算基准是元素本身,所以这里可以用50%来做反向偏移。

    局限:这个方案需要固定居中块的尺寸值(不能设置max-width等范围限制),浏览器需要以此为基准来计算定位!

    综合来说,方案2的居中方式明显会比方案1要好,但是在绘制图标的时候会用到transform来做一些偏移,为了不覆盖偏移效果所以要用到方案的方式来做居中。除了这两种居中方式,还有inline-block对齐after/before子元素的方式,还有table和flexbox的方式来实现居中,但是画图标本身层级有限而且也用到了before/after,所以不适用图标绘制。

    最后一点

    目前纯CSS的图标还是挺多应用场景的,这种图标的方案免去了做雪碧图和维护雪碧图的麻烦,而且减少了图片资源的请求,从性能上来说会有那么0.01s的提高吧。不用堆雪碧图还方便调整颜色,性能还有0.01s的优化,这套CSS图标你还不赶紧用起来?!

    PS:各位看官觉得不错的话,还请顺手给个github星星哈。多攥几颗星星,说不定就升职加薪赢取白富美了呢~~~

    PPS:再附上几个神级的CSS效果吧(by Fabrizio Bianchi  来源: http://codepen.io/fbrz/pen/iqtlk):

     
     
  • 相关阅读:
    Leetcode 121. Best Time to Buy and Sell Stock
    Leetcode 120. Triangle
    Leetcode 26. Remove Duplicates from Sorted Array
    Leetcode 767. Reorganize String
    Leetcode 6. ZigZag Conversion
    KMP HDU 1686 Oulipo
    多重背包 HDU 2844 Coins
    Line belt 三分嵌套
    三分板子 zoj 3203
    二分板子 poj 3122 pie
  • 原文地址:https://www.cnblogs.com/qieguo/p/5999630.html
Copyright © 2011-2022 走看看