letter-spacing+first-letter实现按钮文字隐藏

这篇文章发布于 2013年07月30日,星期二,17:50,归类于 CSS相关。 阅读 82642 次, 今日 7 次 31 条评论

 

一、文不在长,有货则灵

图片式按钮的文字隐藏看来是大家都比较关注的一个问题(分享讨论、微博转发等可见一斑),text-indent负值为最常用方法,然问题有三:

  1. 较大的负值有性能问题,例如新浪/腾讯微博提交按钮的-9999em,大概12~16万像素的宽度,相对于100个显示器宽度,在低配Android pad上,尤其含动画效果的时候,会直接卡爆;
  2. FireFox浏览器下虚框。其实问题不大,overflow:hidden可修复;
  3. 不能应用在IE6/IE7伪inline-block水平元素上,否则元素会被text-indent拐走。

即使有人提出:

{ text-indent: 100%; white-spacing: nowrap; overflow: hidden; }

除了性能有所缓解,后面两个问题依旧存在。

二、法不在高,能用则行

上周分享,有同行提到另外一个隐藏之法,简称为:font: 0/0 a法。

释义为,字号大小0, 行高0,字体a是因为就一个字母,换成b也是OK的,实际并无a字体。日本高中社团要至少4个人才能成立,游泳社就3个人,于是就去田径队找了个旱鸭子来充数,这个旱鸭子就是这里的a.

一般要配合overflow: hidden使用。

实例顶千言,您可以狠狠地点击这里:font:0/0 a与按钮文字隐藏demo

CSS代码如下:

.btn {
    display: inline-block;
    width: 52px; height: 25px;
    border: 0;
    background: #f0f0f0 url(/study/image/flash_copy_btn.png);
    font: 0/0 a;
    overflow: hidden;    /* 抹掉a标签按钮最上面的小点 */
}

说明:

  1. 网上有说法是Chrome下需要添加color: transparent,不过据我win7 Chrome浏览器查看,没什么问题,因此CSS中无此声明;
  2. overflow: hidden用来解决IE6浏览器下,a元素等模拟标签下最顶部残存小点点的问题。
  3. 对于原生的button按钮元素,此方法表示无能为力,低版本IE浏览器下,小点点依旧存在,如下放大后的截图:
    IE6 按钮元素中的点点仍然存在

相比text-indent负值缩进,此方法优点在于可以应用在inline-block水平元素上;不足在于不能用在原生的button按钮元素上。

因此,还有改进余地以及寻找更好方法的动力。

三、斯是吾法,齐论德馨

此方法是我午饭后打瞌睡的时候想到的,一句话概括就是letter-spacing负值+first-letter伪元素负值实现。

对于新方法,先展示效果才能让别人有继续深入的兴趣。您可以狠狠地点击这里:letter-spacing/first-letter与按钮文字隐藏demo

IE6浏览器下的截图如下:
IE6浏览器下letter-spacing负值+first-letter伪类实现的文字隐藏效果

CSS代码如下:

.btn {
    display: inline-block;
    width: 52px; height: 25px;
    border: 0;
    background: #f0f0f0 url(/study/image/flash_copy_btn.png);
    letter-spacing: -3em;
    overflow: hidden;
}
.btn:first-letter {
    margin-left: -20em;
}

1. 关于letter-spacing负值
letter-spacing控制字符间距,可以是负值,可以让字符水平方向重叠,甚至倒序排列,如值为-2em时候。选择下面下拉值,可以看到不同letter-spacing大小对应效果:

更改letter-spacing大小:

我是测试文字!

于是,如果按钮text-alignleft的话,letter-spacing值在小于-2em的时候,字符都跑到了首字符的左侧(也就是在按钮的外面)。一旦按钮设置了overflow:hidden除了第一个字符,其余字符都隐藏了

2. 关于first-letter伪元素
first-letter伪元素与first-line伪元素实际是表兄弟关系,first-line可以实现IE6/IE7的单标签多背景效果,前不久刚介绍,那first-letter呢?

顾名思意,first-letter控制第一个字符的样式,IE5.5开始支持,支持的样式有(参考自MDN):

  • 所有字体相关属性:font, font-style, font-variant, font-weight, font-size, line-height以及font-family.
  • 所有背景相关属性:background-color, background-image, background-position, background-repeat, background-size, 以及background-attachment.
  • 所有margin相关属性:margin, margin-top, margin-right, margin-bottom, margin-left.
  • 所有padding相关属性:padding, padding-top, padding-right, padding-bottom, padding-left.
  • 所有border相关属性:缩写的border, border-style, border-color, border-width及普通书写的属性。
  • color属性。
  • text-decoration, text-transform, letter-spacing, word-spacing(合适情境下), line-height, float, vertical-align(只有当floatnone的时候)这些CSS属性们.

要隐藏第一个字符,我采用的就是margin负值。例如:

.btn:first-letter {
    margin-left: -20em;
}

于是,字符们全部都隐藏了

当然,还是有些需要说明的。

3. 其他一些说明:

  1. 此方法兼容IE6+, 适用于inline-block水平元素,且适用于button元素,不过,需要是下面这种写法:
    <button type="button/submit">按钮</button>

    而不能是这样子:

    <input type="button/submit" value="按钮" />
  2. 此方法受text-align属性影响。letter-spacing负值+first-lettermargin负值适用于text-align:left;的情况,如果按钮text-alignright,则letter-spacing以及first-lettermargin需要使用正值。

    值的大小其实没有定值。一般,letter-spacing绝对值大于2em可以,首字符margin可以大一些,demo中是-20em.

  3. 多个:first-letter伪元素不要使用逗号分隔,貌似会全部失效,应分开写使用逗号分隔的时候逗号前面一定要留一个空格,就跟众所周知的{前面要留有空格一样,否则,IE6浏览器会忽略这条声明:
    .btn:first-letter,
    .img:first-letter {
        margin-left: -20em;
    }
    
    .btn:first-letter ,    /* 逗号前需有1个空格 */
    .img:first-letter {
        margin-left: -20em;
    }
    

未大规模测试,欢迎反馈问题。

在实际应用的时候,我们可以把该功能的CSS独立出来,公共使用,例如:

.notext {
    text-align: left;
    letter-spacing: -3em;
    overflow: hidden;
}
.notext:first-letter {
    margin-left: -20em;
}

四、不是会两句古诗就了不起的

其实呢,如果不要兼顾原生button按钮,还可以使用padding撑开容器尺寸隐藏文字的方法,类似下面:

.btn {
    display: inline-block;
    padding-top: 25px;
    width: 52px; height: 0;
    background: #f0f0f0 url(/study/image/flash_copy_btn.png);
    overflow: hidden;
}

代码少,理解简单,兼容性还不错。就是不能用在正宗的按钮元素上(IE6/IE7直接隐藏抗议)。
抗议

五、孔子曰:“何陋之有?”

letter-spacing+first-letter隐藏文字的方法动用了伪元素,方法虽糙,但效果不糙。我个人觉得比前两种方法都要好一些,您觉得呢?

行文仓促,文中难免有表达不准确之处,欢迎指正;如果有技术性错误,务必指出,感谢阅读!

(本篇完)

分享到:


发表评论(目前31 条评论)

  1. yipanhuasheng说道:

    这个文字隐藏,就主要是为了帮助一些困难用户吗?没有别的什么特殊用意了吗?

  2. 邹远通说道:

    在imooc看到那张张含韵了。

  3. Fenz说道:

    想到一个貌似很妙的方法
    :first-line{visibility:hidden;}但遗憾chrome不支持,
    而chrome却又支持:first-letter{visibility:hidden;},什么鬼。
    不知在其它浏览器上兼容性如何

  4. yao说道:

    亲 我把这东西应用到项目,本以为是个perfect的方案 可是发现…ie6下,a标签 如果同时有hover和first-letter的话 hover无效

  5. d说道:

    我测试IE6发现,恰恰支持。button会出现第二个字。a标签出现第一个字。只好写个hack,给大点的行高。那还不如全部给大行高来的痛快。

  6. Richard说道:

    讲得挺好的。很受益。
    我有个想法:如果只是想要实现button换成图片的。是否可以直接将button样式设置成
    .btn{
    border:0 none;
    display:inline-block;
    height:25px;
    width:60px;
    background:url(flash_copy_btn.png) no-repeat;
    cursor:pointer;}

    button中的value直接为空就行了。不知道这样会不会有没设么不良影响。请哥给指明一下。谢谢。

  7. 静寂无闻之夜说道:

    感觉color:transparent靠谱

  8. philoyou说道:

    在IE67中你的方法并不起作用啊,还需要加上较大的line-height值才能够将文字隐藏

  9. richard chen说道:

    发现IE6有个bug,如果直接跟a:first-letter {}的话,后面写的CSS中a:hover将不会生效。

    .div1 { width:100px; height: 20px; line-height: 20px; }
    .div1 a { display:block; width:100%; height: 100%; background: #ccc; letter-spacing: -3em;}
    .div1 a:first-letter { margin-left:-20em;}
    .div2 { width:100px; height: 20px; line-height: 20px; }
    .div2 a { display: block; width: 100%; height: 100%; background: #f00;}
    .div2 a:hover { background: #ff0; }

    这是文字哟
    这又是文字哟

    这是我的测试代码

    • richard chen说道:

      于是我在需要隐藏文字的a标签给一个class=”text-hide”,在CSS里面写.text-hide:first-letter就解决了

  10. 分享园说道:

    mark,我之前都是font-size: 0;line-height: 100em; overflow: hidden;这样写的,呵呵~

  11. web前端之家说道:

    我觉得还有一种方法可以实现隐藏:设置行高然后overflow:hidden
    CSS:
    ———————————————
    #aa{dipslay:inline-block;height:20px;line-height:9999px;overflow:hidden}

    虽然跟text-indent:-9999em相比都有些性能问题,但是个人觉得比其好。

  12. iamght说道:

    学习了,以后可以用得到

  13. GenialX说道:

    写得不错不错~~~

  14. 免费部落说道:

    有些水平哦!

  15. grass说道:

    综合你上面的方法,我又总结出一个可以兼容input的写法,你看下可以不;

    .class{
    color:transparent;/*大于ie8 + 其它浏览器就可隐藏文字 */
    letter-spacing:-2em;
    text-align:left;
    font-size:0;/* for ie8+ 在ie8非要font-size:0才能隐藏input中value的文字*/
    }
    .class:first-letter {
    margin-left: -20em;
    }
    如果是input的话,就在value里加个空格,如vlaue=” 按钮”;ie6,7不会自动删除这个空格, letter-spacing:-2em;时候就直接隐藏了,但是ie8+会删除空格,所以ie8要加上font-size:0;

  16. 叶小钗说道:

    哥,我来上海了,有时间我来找你交流

  17. grass说道:

    “多个:first-letter伪元素不要使用逗号分隔,貌似会全部失效,应分开写。”

    不是说不能合并着写,而是在ie6里p:first-letter {}伪元素与{}之间要有个空格的,如果没有的话ie6就不认识了。。所以你合并的时候也应该留下这个空格,如下,,你可以试试
    .btn:first-letter ,.img:first-letter {margin-left: -20em;}

  18. Kxxw说道:

    在给定宽度的情况下,ie67下inline-block元素是可以使用text-indent的,测试了没有问题,元素不会被拐走。

    • grass说道:

      ie中内联元素(如span/i/strong等)触发它的inline-block,需要加上*zoom:1;;
      块级元素(如div/p等)要触发他的inline-block效果则要加上*display:inline;*zoom:1,前把他变成内联元素(display:inline)然后再zoom:1;