探索CSS单行文字居中,多行文字居左的实现方式

简介: 探索CSS单行文字居中,多行文字居左的实现方式
原文链接 https://github.com/XboxYan/notes/issues/13


很久以前


刚入前端那会,产品经理提出了这样一个需求


这段文字能不能这样判断一下,当文字不足一行时,让它居中显示,当文字超过一行就让它居左,不然居中显示很奇怪,因为最后一行是吊着的


image.png

琢磨了一下,当时我还真按照产品经理的逻辑,通过js判断一下文字的高度,如果超过一行,就添加一个类名,而且这样的文字很多地方都有,所以还做了遍历,还有最重要的一点是关于方法执行的时机,有可能刚加载的时候高度还获取不到(当时好像还用了定时器,还造成了先居中随后居左跳动的现象)...

//伪代码
$('.text').each(function(){
    if($(this).height()>30){
        $(this).addClass('mul');
    }
})


然后这些文本有可能还是动态生成的,所以还得在生成文本的地方再调用一次这个方法,功能是做出来了,可别说有多啰嗦了,体验也不咋地(虽然外面的人看不到)

当时也在想,如果是CSS实现,那么就完全不用考虑这些问题了!


关于CSS实现思路


其实只要你逻辑清晰,js都能实现出来,按照正常的思路一步一步走下来就行了。CSS可不是这样,她需要你有更多的想象力。


比如上面这种需求,表面上来看是需要判断文本行数,这完全不是CSS能干的事呀,不过我们可以换个方向思考,文本默认是居左的(默认文本流),只有首行是居中的,首行可以联想到::first-line伪元素,所以可以试着这样实现一下

<p>这段文字能不能这样判断一下,当文字不足一行时,让它居中显示,当文字超过一行就让它居左</p>


p::first-line{
    text-align:center;
}


很好理解是吧,只针对首行进行居中操作,当多行时,首行已经铺满了,居中或者居左效果已经不明显了,只是稍微有点瑕疵,首行的居中效果和后面的文字看着有些不太整齐的感觉(因为当一行剩余空间不足一个字符的时候会掉下去)


image.png

解决这个问题也很简单,上面的问题是由于首行一直处于居中状态,那有没有什么办法可以只要一行的时候才居中呢?这里可以借助一下text-align-last,意思就是规定多行文本的最后一行的居中方式,如果和::first-line一起使用,既要满足首行又要满足是最后一行,是不是就判断出了当前只有一行呢?

p::first-line{/*匹配首行*/
    text-align-last:center;/*最后一行居中*/
}


image.png

这下就正常了,有点首尾夹击的味道~


See the Pen点击预览


遗憾的是,由于::first-line支持样式非常有限(MDN),上述实现方法仅在chrome下有效,不过这种逻辑还是和js差别很大的


image.png

虽然上述并没有 text-align相关属性,不过 chrome却已经支持了~


更好的实现方式


1.父级text-align:center,子级inline-block+text-align:left


首先来看看兼容性最好的实现方式


结构如下

<div class="content">
    <span class="text">这段文字能不能这样判断一下,当文字不足一行时,让它居中显示,当文字超过一行就让它居左</span>
</div>


样式如下

.content{
    text-align: center;
}
.text{
    display: inline-block;
    text-align: left;
}


这个方式最早是在《CSS世界》中学到的,


image.png

大概原理如下:


对于一个元素,如果其 display属性值是 inline-block,那么其宽度由内部元素决定,但永远小于“包含块”容器的尺寸,也就是“包裹性(shrink-to-fit)”


可能这样描述的不够直观,来上述的案例简单来讲


  • 当文本比较少时,.text的宽度跟随文本,然后我们可以使用父级text-align:center来使一个inline-block元素居中,所以可以满足单行文本居中的效果,
  • 当文本比较多时,.text的宽度跟随父级容器,由于text-align:center会继承下去,所以在.text上修复一下即可


See the Pen点击预览


兼容性一级棒~


2.width:fit-content+margin:auto


上述方式是通过父级text-align:center来实现inline-block居中的,很巧妙,但是额外增加了标签,因为inline-block元素无法本身居中的。


块级block元素可以在设置宽度后直接通过margin:0 auto来实现居中,但是必须指明宽度,不然就水平填充了,这两者的关系很微妙,有没有什么办法能够让块级block元素的宽度像inline-block元素跟随内部元素呢?


答案就是width:fit-content,详细可参考这篇文章


width:fit-content可以实现元素收缩效果的同时,保持原本的 block水平状态,于是,就可以直接使用 margin:auto实现元素向内自适应同时的居中效果了。


下面的实现方式均只需要单层标签

<p class="text">这段文字能不能这样判断一下,当文字不足一行时,让它居中显示,当文字超过一行就让它居左</p>
.text{
    width: fit-content;
    width: -moz-fit-content;//火狐需要-moz-前缀
    margin: 0 auto;
}


See the Pen点击预览


当然,这种特性IE肯定是不支持的~


image.png


3.position:relative+transform


仍需设置display:inline-block来实现自适应,然后配合transform来实现水平方向居中效果,实现也很简洁~

.text{
    display: inline-block;
    position: relative;
    left: 50%;
    transform: translateX(-50%);
}


See the Pen点击预览


4.display:table+margin:auto


前一种方式width:fit-content很有效,IE不支持怎么办呢?其实默认display已经有这种特性了,当display属性值是table,元素会表现出和width:fit-content的效果,既支持宽度跟随内部元素,又支持水平方向上margin居中

.text{
    display: table;
    margin: 0 auto;
}


See the Pen点击预览


IE8也完美支持~


image.png

5.flex和grid实现


对于flexgrid来说,实现这样一个效果还是挺容易的。


flex容器中,所有子项成为弹性项,包括纯文本节点(匿名盒子),就好像包裹了一层,所以很容易通过justify-content: center实现居中,同时(匿名盒子)也跟随文本自适应宽度,当超过一行时,就按照默认的文本对齐方式。


grid同理,只不过对齐方式需要通过justify-items: center


  • flex实现
.text{
    display: flex;
    justify-content: center;
}


See the Pen点击预览

  • grid实现
.text{
    display: grid;
    justify-items: center;
}


See the Pen点击预览


相对于flexgrid的兼容性要差一些,所以尽量选取flex方式,至少移动端和IE10(需要-ms-)是没问题的


6.float实现


本以为float实现不了的,感谢林小志提供了float居中的实现方法,大致原理如下:本身float元素是具备包裹特性的,主要难点在于如何居中,毕竟没有float:center这种写法,这里主要用到两层标签,利用position:relative;left:50%正负抵消来实现

.content{
    position: relative;
    float: left;
    left: 50%;/**父级设置50%**/
}
.text{
    position: relative;
    float: left;
    left: -50%;/**子级设置-50%**/
}


See the Pen点击预览


略微繁琐一点,不过也不失为一种方法,兼容性也极好


小结


上述一共列举了8种实现方式,当然第一种属于实验性质的,兼容性少的可怜,但也不失为一种思路。怎么想到这些方法呢?


第一就是联想。比如上述提到了自适应(简单来讲就是尺寸由内容决定),我就想哪些可以实现自适应呢?除了inline-block,还有floatposition:absolutedisplay:table等...首先float就排除了,元素设置了float后,整体居中其实是件麻烦的事,几乎不可能(经过试验,可以实现)。position:absolute还是挺有希望的,借助left:50%;transform:translateX(-50%)可以实现居中效果, 尝试了一番,发现宽度无法自适应父级宽度,同样失败(说不定可以,只是没有想到)~~最后选择了diaplay:table,也算是循序渐进。flexgrid就更不用说了,天然就是为弹性布局而生了,实现这类效果不奇怪。


第二还是基础。CSS属性可就那么多,那只是停留在表面,很多看起来不相关的属性在整个体系中又会有些微妙的关系,比如上面的width:fill-content,单独看这个肯定很鸡肋,完全可以用inline-block来代替,但是他却可以让一个普通的div元素具备inline-block的特性,不得不佩服CSS的设计~(肯定有设计人员参与)


前一段时间在思考做一个可视化编辑工具,希望可以通过一些属性,就像photoshop那样,直接作出一个页面来,想想看,发现只能作出最最基本的样式,也就颜色,大小什么的,如果要做成本文这样一个效果,八成是做不了的,除了本身是做开发,别人怎么可能知道这样设置呢?可视化编辑工具的道路还很长很长,所以做前端的也无需担心被其他什么“一键生成工具”给取代了~


image.png


各位小伙伴如果还有其他实现方式可在下方留言评论,如果文章有错误请及时指出,谢谢~

相关文章
|
2月前
|
前端开发
前端基础(五)_CSS文本文字属性、背景颜色属性
本文详细介绍了CSS中关于文本和背景颜色的样式属性。包括字体大小、字体族、字体加粗、字体样式、文本行高、`font`属性、文本颜色、文本对齐方式、文本装饰线、首行缩进等文本属性,以及背景颜色、背景图片、背景重复、背景位置等背景属性。文章通过示例代码展示了这些属性的具体应用和效果。
28 3
前端基础(五)_CSS文本文字属性、背景颜色属性
|
3月前
|
前端开发
简单几行代码CSS实现网页自动打文字效果
简单几行代码CSS实现网页自动打文字效果
52 1
简单几行代码CSS实现网页自动打文字效果
|
2月前
|
前端开发
css中的多行省略和单行省略
css中的多行省略和单行省略
|
1月前
|
Web App开发 前端开发 iOS开发
|
2月前
|
前端开发
css中的多行省略和单行省略
css中的多行省略和单行省略
|
3月前
|
移动开发 前端开发 HTML5
css实现涂绘文字的效果
如何使用HTML5和CSS3创建一个简单的文字涂抹动画效果。通过设置一个相对定位的父级div包含文本,并在其上使用绝对定位的伪元素与之重叠,实现动画效果。关键在于控制伪元素的宽度从0%到100%的变化过程,同时利用`overflow: hidden`和`white-space: nowrap`确保文本按预期显示。光标效果则通过添加右边界来模拟。整体代码简洁明了,便于理解和实践。
36 1
css实现涂绘文字的效果
|
3月前
|
前端开发 程序员
HTML+CSS+JavaScript制作动态七夕表白网页(含音乐+自定义文字)
一年一度的520情人节/七夕情人节/女朋友生日/程序员表白,是不是要给女朋友或者正在追求的妹子一点小惊喜呢,今天这篇博客就分享下前端代码如何实现HTML+CSS+JavaScript制作七夕表白网页(含音乐+自定义文字)。赶紧学会了,来制作属于我们程序员的浪漫吧!
78 0
HTML+CSS+JavaScript制作动态七夕表白网页(含音乐+自定义文字)
|
3月前
|
前端开发
CSS流光文字效果:打造网页上的霓虹灯效果!
CSS流光文字效果:打造网页上的霓虹灯效果!
|
4月前
|
前端开发 容器
CSS【详解】对齐 (含文本垂直对齐,文本水平对齐、单行文本垂直居中、多行文本垂直居中、6 种方案块级元素水平垂直居中 、7 种方案图片水平垂直居中、文本自适应对齐、图标和文本对齐,图片和文本对齐等)
CSS【详解】对齐 (含文本垂直对齐,文本水平对齐、单行文本垂直居中、多行文本垂直居中、6 种方案块级元素水平垂直居中 、7 种方案图片水平垂直居中、文本自适应对齐、图标和文本对齐,图片和文本对齐等)
65 0
|
4月前
|
前端开发 JavaScript
前端 CSS 经典:文字描边
前端 CSS 经典:文字描边
211 0