一、text-decoration:underline下划线的问题

CSS text-decoration:underline可以给内联文本增加下划线,但是,如果对细节要求较高,就会发现,下划线经常会和中文文字的下边缘搞在一起,英文的话甚至直接穿越,看起来就比较香菇蓝瘦。

上图几个中文下边缘正好都是横线,结果,可以看到,基本上合在一起分不清谁是谁了,换成微软雅黑字体(见下图),似乎变本加厉了:

有没有什么办法让下划线不要靠得这么近,或者文字可以完整清晰地显示呢?

有,方法还不少,下面逐一介绍,大家可以根据自己的实际项目需求,选择合适的技术选型。

方法一:text-decoration-skip指定覆盖关系

理论上,使用下面的CSS:

a { text-decoration-skip: ink; }

机会有类似下图的效果:

text-decoration-skiptext-decoration相关的CSS3新的属性,还有很多其他新的CSS3 text-decoration属性,可以指定下划线类型等,具体可参见我之前的文章:“了解CSS3 text-decoration新特性新表现”。

看上去效果很不错,但是遗憾的是,即使现在快到2017年了,此属性的浏览器支持情况还是很不乐观,包括大头Chrome浏览器目前尚未支持。

Safari 8+ supports -webkit-text-decoration-skip with values none and skip (other values behave like none or skip)

目前也就是Safari 8+浏览器支持带-webkit-私有前缀的text-decoration-skip属性,且仅仅支持skip(默认值)和none两个值,换句话说,Safari 8+浏览器默认下划线就是和文字非穿越而是避让效果。这进一步导致CSS代码中没有text-decoration-skip属性出现的必要了。所以,此方法虽然最原生,但时机还不够。

方法二:使用border-bottom属性模拟

内联元素虽然不支持垂直方向的margin属性,但是支持垂直方向的padding属性和border属性,并且,对原来的布局定位等没有任何影响。因此,配合padding,我们就可以很有效地调节下边框和文字下边缘的距离,实现我们最想要的的效果,类似下面的CSS代码:

a {
text-decoration: none;
border-bottom: 1px solid;
}

效果类似下图:

如果觉得border-bottom模拟的下划线还是和文字走得太近,我们可以使用padding-bottom再撑开点距离,例如:

a {
text-decoration: none;
border-bottom: 1px solid;
padding-bottom: 5px;
}

则效果类似下面截图:

眼见为实,您可以狠狠地点击这里:border-bottom模拟下划线文字无重叠demo

注意,使用border-bottom模拟下划线的时候,border-color最好缺省,这样就会使用文字的color颜色作为边框色,这样,鼠标hover的时候,下划线会自动和文字一起变色,类似下图效果:

使用border-bottom模拟的另外一个好处就是我们还可以使用虚线下划线:

a {
text-decoration: none;
border-bottom: 1px dashed;
}

类似下面实际项目需求的截图就可以使用这种策略:

方法三:使用box-shadow属性模拟

我们也可以使用CSS3 box-shadow属性模拟下划线,代码如下:

a {
text-decoration: none;
box-shadow: 0 1px;
}

同样,建议颜色值缺省,使用color属性的颜色值。

效果基本上和border-bottom如出一辙,如下截图:

眼见为实,您可以狠狠地点击这里:box-shadow模拟下划线效果demo

相比border-bottom属性,box-shadow的优势在于,即使我们把内联元素设置成display:inline-block,生成的下划线也不会对垂直对齐或者布局产生影响,但,如果是border-bottom,会增加元素的尺寸,可能就会影响元素的排列。

但是,box-shadow也有不足,一是兼容性,IE9+才支持,二是只能实线,不能虚线。

方法四:使用background-image属性模拟

就是使用CSS3渐变绘制实线或虚线背景图。

效果截图如下:

相关CSS代码如下:

.solid {
padding-bottom: 2px;
background-image: linear-gradient(to top, currentColor, currentColor 1px, transparent 1px);
}
.dashed {
padding-bottom: 2px;
background: linear-gradient(to right, currentColor, currentColor 4px, transparent 4px) repeat-x 0 bottom/7px 1px;
}

由于背景图片是在原本区域内显示,有别于border-bottom或者box-shadow区域外显示,因此,实现的下划线实际上和文字还是很近的,尤其类似yqp这种基线以下的字母,就会合体。一般有两种处理手段,一种是文字增加白色描边,类似下面CSS:

a {
text-shadow: 0 1px #fff, 0 -1px #fff, 1px 0 #fff, -1px 0 #fff;
}

效果类似下面这样:

第二种就是使用padding-bottom对内联元素增加可视高度。所以,上面实线下划线和虚线下划线均有padding-bottom:2px的设置。

眼见为实,您可以狠狠地点击这里:background-image模拟下划线效果demo

对了,突然想起来,demo中的下划线使用的是currentColor变量,但是在Chrome浏览器和IE浏览器下,currentColor作为背景图片色值的时候,当:hover改变元素的color颜色值的时候,背景图片颜色并不会跟着变,Firefox浏览器的表现符合预期,因此,如果使用此方法,需要:hover时候,背景图片重新绘制下。

使用background-image绘制的好处在于,我们对样式的控制更灵活的,例如我们可以把线放在文字的后面,我们可以上下划线,我们控制虚线的稀松程度,我们也可以使用圆点表示虚线,我们甚至也可以使用径向渐变绘制波浪样子的下划线,甚至可以把线做成倾斜的等等。不足在于IE10+浏览器才支持。

方法五:使用SVG滤镜处理

该SVG滤镜相关HTML代码如下:

<svg class="out">
<filter id="svg-underline" primitiveUnits="objectBoundingBox">
<!-- 原图文基础上水平垂直方向一点点扩展并存储到新的层上 -->
<feMorphology in="SourceGraphic" operator="dilate" radius="0.0075 0.05" result="outline"></feMorphology>
<!-- 一个蓝色矩形,高度3%然后宽度100%,位置稍微往下一点 -->
<feFlood flood-color="#34538b" width="1" height="0.03" x="0" y="0.9" result="underline"></feFlood>
<!-- 遮罩蓝色矩形,这样,文字重合部分边缘会镂空 -->
<feComposite in="underline" in2="outline" operator="out" result="underline"></feComposite>
<!-- 效果合体 -->
<feMerge>
<feMergeNode in="underline"></feMergeNode>
<feMergeNode in="SourceGraphic"></feMergeNode>
</feMerge>
</filter>
</svg>

相关CSS代码如下:

a {
-webkit-filter: url('#svg-underline');
filter: url('#svg-underline');
text-decoration: none;
}

然后,实现的效果类似下面的截图(截自Chrome浏览器):

看上去很麻烦很啰嗦,hover变色还需要另外的处理,SVG滤镜兼容性并不乐观,IE现在都不支持,所以,这种方法的意义在哪里?

意义就在于可以实现真正意义上的text-decoration-skip效果,也就是下划线和文字重叠的位置自动从文字下面穿过,并且附近完全是真正的透明,仔细看上面截图,可以看到,文字和下划线接触的位置的地方,看上去有1像素的接触点是透明的。

原生的Safari外加SVG滤镜下的Chrome/Firefox,也就是绝大多数浏览器都可以实现下划线和文字自动接触点镂空的效果。

眼见为实,您可以狠狠地点击这里:使用SVG滤镜模拟下划线demo

方法六:使用canvas实现(著名的Underline.js)

Underline.js项目地址:https://github.com/wentin/underlineJS

作者是这位妹纸(图片源自网络):

zhangwenting,目前任职于 Adobe Typekit。

underline.js同样实现的是下划线和文字重叠自动避让的效果,类似下图:

您可以狠狠地点击这里:canvas原理的underline.js解决下划线重叠demo

基本上,下划线文字穿越效果只有英文才好看,中文如果穿越,我去,基本上下划线就没了,尤其类似“金玉全王”这样的汉字:

所以,对于中文,最好的效果还是避让,就是直接线和文字留点距离,这样是最好的。对于,英文为主的内容,则text-decoration-skip效果确实还是挺有价值的。

根据我自己对underline.js的使用,发现,局限性还不小,内联元素最好要inline-block化,纯inline生成的canvas的垂直位置不是很精准,然后,不支持文字自动换行下划线折线显示,毕竟canvas元素是个独立的替换元素,跟图片一样,不可能换行时候分一半上面再一半下面。

基本上,适合用在局部一些大的标语,标题,slogon等位置或者追求视觉的官方网站或活动页面上使用。

八、结束语

今天群里都在玩风景照一下子变成动漫风格的滤镜,实际上,使用PS,分分钟搞定。

我特意找了张质量很差的自己钓鱼拍的风景图,PS中滤镜搞搞,2分钟,就好了,效果如下:

效果还行,如果换个清晰明丽的图,效果会更好。

步骤如下:
1. 滤镜→滤镜库→干画笔→0 10 1!
2. 滤镜→Camera Raw滤镜→色温高,色调绿,曝光增加,对比对增加,阴影和黑色最大,饱和度和清晰度适当增加,然后第三个“细节”小按钮,数量和蒙版很大的值,半径和细节自己看着调;
3. done!

解决文字和text-decoration:underline下划线重叠问题的更多相关文章

  1. 使用 Sublime Text 将含下划线的字符串批量替换为驼峰命名法格式的字符串

    本文版权归cxun所有,如有转载请注明出处与本文链接,谢谢!原文地址:http://www.cnblogs.com/cxun/p/7762984.html For indexing: Convert ...

  2. iOS 开发富文本之TTTAttributedLabel 在某个特定位置的文字添加跳转,下划线,修改字体大小,颜色

    @property(nonatomic , strong) TTTAttributedLabel * ttLabel; @property(nonatomic , strong) NSRange li ...

  3. css标题文字和下划线重叠

    <view class="text"> <text class="textCon">标题</text> <text c ...

  4. PostgreSQL解决"Abc_de_fghijkl_mn" 首字母小写去掉下划线并且下划线后面的第一个字母大写或首字母大写去掉下划线并且下划线后面的首字母大写的js

    select "lower"(substr('Abc_de_fghijkl_mn', 1, 1)) || substr(replace(REGEXP_REPLACE(INITCAP ...

  5. text-decoration:underline与字体重叠

    前几天工作遇到了字体与underline下划线重叠的问题,折腾了半天.今天在张鑫旭的博客上找到了几种解决方法分享一下 1 text-decoration-skip:不推荐使用 17年了这个属性支持率依 ...

  6. iOS - UIButton设置文字标题下划线以及下划线颜色

    创建button设置可以折行显示 - (void)viewDidLoad { [super viewDidLoad]; UIButton * button = [[UIButton alloc] in ...

  7. Markdown - 如何给文本加下划线

    解决方法 Markdown可以和HTML的语法兼容,可以通过HTML的标签来实现效果: 写法 效果 <u>下划线</u> 下划线 这里解释下,u指的是underline下划线. ...

  8. css删除线,下划线等

    <style> .p1 { text-decoration:overline; //上划线 } .p2 { text-decoration:line-through; //删除线 }  . ...

  9. 下划线css

    /* <div class="text">header</div> */ .text { /* 作用元素 */ display: inline-block; ...

随机推荐

  1. Weekly Contest 131

    1021. Remove Outermost Parentheses A valid parentheses string is either empty (""), " ...

  2. 分布式ehcache缓存

    今天在这里了记录一下学习ehcache分布式集群的过程. ehcache的三种最为常用集群方式,分别是 RMI.JGroups 以及 EhCache Server . 这里主要讲一下rmi方式. 1. ...

  3. [underscore源码学习]——`>>` 运算符和二分查找

    这是一篇记录学习 underscore v0.0.5 的fragment,觉得有点意思,和大家分享一下. 先看_.sortedIndex的源码,它用来确定 obj 在 array中的位置(array升 ...

  4. string的相关问题

    http://blog.csdn.net/seu_calvin/article/details/51404589 http://rednaxelafx.iteye.com/blog/774673 ht ...

  5. JavaWeb之Servlet中ServletConfig和ServletContext

    [声明] 欢迎转载,但请保留文章原始出处→_→ 文章来源:http://www.cnblogs.com/smyhvae/p/4140877.html [正文] 一.ServletConfig:代表当前 ...

  6. 汉诺塔问题(C++版)

    题目描述 Description 约19世纪末,在欧州的商店中出售一种智力玩具,在一块铜板上有三根杆,最左边的杆上自上而下.由小到大顺序串着由64个圆盘构成的塔.目的是将最左边杆上的盘全部移到中间的杆 ...

  7. 【NOIP2017】列队 splay

    当年太菜了啊,连$60$分的暴力都没拿满,只打了一个$30$分的. 考虑到这题最多只会询问到$30W$个点,且整个矩阵会去到$30W\times 30W$,显然不能将所有的点存下来. 对于每一行(除最 ...

  8. selenium IDE的基本命令

    waitForText.verifyText和asserText命令 waitForText语句在测试执行时用来判断某些文本是否存在界面中.若界面上显示了指定文本,测试程序会继续执行:若等待一段时间后 ...

  9. (转)python高级:列表解析和生成表达式

    一.语法糖的概念 “糖”,可以理解为简单.简洁,“语法糖”使我们可以更加简洁.快速的实现这些功能. 只是Python解释器会把这些特定格式的语法翻译成原本那样复杂的代码逻辑 我们使用的语法糖有: if ...

  10. EF基础知识小记七(拆分实体到多个表以及拆分表到多个实体)

    一.拆分实体到多个表 1.在日常开发中,会经常碰到一些老系统,当客户提出一些新的需求,这些需求需要在原来的表的基础上加一些字段,大多数人会选择通过给原表添加字段的方式来完成这些需求,方法,虽然可行,但 ...