一、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. 2017 NAIPC A:Pieces of Parentheses

    my team solve the problem in the contest with similar ideathis is a more deep analysis The main idea ...

  2. Aizu 2249Road Construction 单源最短路变形《挑战程序设计竞赛》模板题

    King Mercer is the king of ACM kingdom. There are one capital and some cities in his kingdom. Amazin ...

  3. poj3624 Charm Bracelet

    http://poj.org/problem?id=3624 题目大意:贝茜去了商场的珠宝店,发现了一个迷人的手镯.当然,她想装最好的魅力(N(1≤N≤3402)可用的魅力).每个魅力提供的列表中都有 ...

  4. vector.clear()不能用来清零

    vector.clear()函数并不会把所有元素清零,笔者就曾经这样幻想过这个函数的作用,然而事实证明并不是. vector有两个参数,一个是size,表示当前vector容器内存储的元素个数,一个是 ...

  5. 【xsy1147】 异或(xor) 可持久化trie

    我的脑回路可能比较奇怪. 我们对这些询问离线,将所得序列${a}$的后缀和建$n$棵可持久化$trie$. 对于一组询问$(l,r,x)$,我们在主席树上询问第$l$棵树$-$第r$+1$棵树中与$s ...

  6. 【codeforces 623E】dp+FFT+快速幂

    题目大意:用$[1,2^k-1]$之间的证书构造一个长度为$n$的序列$a_i$,令$b_i=a_1\ or\ a_2\ or\ ...\ or a_i$,问使得b序列严格递增的方案数,答案对$10^ ...

  7. easyui 中iframe嵌套页面,提示弹窗遮罩的解决方法,parent.$.messager.alert和parent.$.messager.confirm

    项目中用到easyui 布局,用到north,west,center三个区域,且在center中间区域嵌入iframe标签.在主内容区做一些小提示弹窗(例如删除前的弹窗提示确认)时,会遇到遮罩问题,由 ...

  8. Oracle 数据库维护管理之--dbms_lock

    1.查询相关的v$视图,但是提示表或视图不存在解决办法     原因是使用的用户没有相关的查询权限导致 解决办法: grant select  any dictionary to 用户;    --这 ...

  9. 为Linux集群创建新账户,并配置hadoop集群

    转自:http://blog.csdn.net/bluesky8640/article/details/6945776 之前装python.jdk.hadoop都是用的root账户,这是一个绝对的失策 ...

  10. Python 日期和时间的几种输出格式

    在python中,我们可以使用 time 模块的 strftime 方法来格式化日期,例子如下: import time # 格式化成2016-03-20 11:45:39形式 print (time ...