htmltr⾏内样式左对齐,探索CSS单⾏⽂字居中,多⾏⽂字居左
的实现⽅式
很久以前
刚⼊前端那会,产品经理提出了这样⼀个需求
这段⽂字能不能这样判断⼀下,当⽂字不⾜⼀⾏时,让它居中显⽰,当⽂字超过⼀⾏就让它居左,不然居中显⽰很奇怪,因为最后⼀⾏是吊着的
琢磨了⼀下,当时我还真按照产品经理的逻辑,通过js判断⼀下⽂字的⾼度,如果超过⼀⾏,就添加⼀个类名,⽽且这样的⽂字很多地⽅都有,所以还做了遍历,还有最重要的⼀点是关于⽅法执⾏的时机,有可能刚加载的时候⾼度还获取不到(当时好像还⽤了定时器,还造成了先居中随后居左跳动的现象)...
//伪代码
$('.text').each(function(){
if($(this).height()>30){
$(this).addClass('mul');
}
})
然后这些⽂本有可能还是动态⽣成的,所以还得在⽣成⽂本的地⽅再调⽤⼀次这个⽅法,功能是做出来了,可别说有多啰嗦了,体验也不咋地(虽然外⾯的⼈看不到)
当时也在想,如果是CSS实现,那么就完全不⽤考虑这些问题了!
关于CSS实现思路
其实只要你逻辑清晰,js都能实现出来,按照正常的思路⼀步⼀步⾛下来就⾏了。CSS可不是这样,她需要你有更多的想象⼒。
⽐如上⾯这种需求,表⾯上来看是需要判断⽂本⾏数,这完全不是CSS能⼲的事呀,不过我们可以换个⽅向思考,⽂本默认是居左的(默认⽂本流),只有⾸⾏是居中的,⾸⾏可以联想到::first-line伪元素,所以可以试着这样实现⼀下
这段⽂字能不能这样判断⼀下,当⽂字不⾜⼀⾏时,让它居中显⽰,当⽂字超过⼀⾏就让它居左
p::first-line{
text-align:center;
}text align center
很好理解是吧,只针对⾸⾏进⾏居中操作,当多⾏时,⾸⾏已经铺满了,居中或者居左效果已经不明显了,只是稍微有点瑕疵,⾸⾏的居中效果和后⾯的⽂字看着有些不太整齐的感觉(因为当⼀⾏剩余空间不⾜⼀个字符的时候会掉下去)
解决这个问题也很简单,上⾯的问题是由于⾸⾏⼀直处于居中状态,那有没有什么办法可以只要⼀⾏的时候才居中呢?这⾥可以借助⼀下text-align-last,意思就是规定多⾏⽂本的最后⼀⾏的居中⽅式,如果和::first-line⼀起使⽤,既要满⾜⾸⾏⼜要满⾜是最后⼀⾏,是不是就判断出了当前只有⼀⾏呢?
p::first-line{/*匹配⾸⾏*/
text-align-last:center;/*最后⼀⾏居中*/
}
这下就正常了,有点⾸尾夹击的味道~
遗憾的是,由于::first-line⽀持样式⾮常有限(MDN),上述实现⽅法仅在chrome下有效,不过这种逻辑还是和js差别很⼤的
虽然上述并没有text-align相关属性,不过chrome却已经⽀持了~
更好的实现⽅式
1.⽗级text-align:center,⼦级inline-block+text-align:left
⾸先来看看兼容性最好的实现⽅式
结构如下
这段⽂字能不能这样判断⼀下,当⽂字不⾜⼀⾏时,让它居中显⽰,当⽂字超过⼀⾏就让它居左
样式如下
.content{
text-align: center;
}
.text{
display: inline-block;
text-align: left;
}
这个⽅式最早是在《CSS世界》中学到的,
⼤概原理如下:
对于⼀个元素,如果其display属性值是inline-block,那么其宽度由内部元素决定,但永远⼩于“包含块”容器的尺⼨,也就是“包裹性(shrink-to-fit)”
可能这样描述的不够直观,来上述的案例简单来讲
当⽂本⽐较少时,.text的宽度跟随⽂本,然后我们可以使⽤⽗级text-align:center来使⼀个inline-block元素居中,所以可以满⾜单⾏⽂本居中的效果,
当⽂本⽐较多时,.text的宽度跟随⽗级容器,由于text-align:center会继承下去,所以在.text上修复⼀下即可
兼容性⼀级棒~
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实现元素向内⾃适应同时的居中效果了。
下⾯的实现⽅式均只需要单层标签
这段⽂字能不能这样判断⼀下,当⽂字不⾜⼀⾏时,让它居中显⽰,当⽂字超过⼀⾏就让它居左
.text{
width: fit-content;
width: -moz-fit-content;//⽕狐需要-moz-前缀
margin: 0 auto;
}
当然,这种特性IE肯定是不⽀持的~
3.position:relative+transform
仍需设置display:inline-block来实现⾃适应,然后配合transform来实现⽔平⽅向居中效果,实现也很简洁~
.text{
display: inline-block;
position: relative;
left: 50%;
transform: translateX(-50%);
}
4.display:table+margin:auto
前⼀种⽅式width:fit-content很有效,IE不⽀持怎么办呢?其实默认display已经有这种特性了,当display属性值是table,元素会表现出和width:fit-content的效果,既⽀持宽度跟随内部元素,⼜⽀持⽔平⽅向上margin居中
.text{
display: table;
margin: 0 auto;
}
IE8也完美⽀持~
5.flex和grid实现
对于flex和grid来说,实现这样⼀个效果还是挺容易的。
在flex容器中,所有⼦项成为弹性项,包括纯⽂本节点(匿名盒⼦),就好像包裹了⼀层,所以很容易通过justify-content: center实现居中,同时(匿名盒⼦)也跟随⽂本⾃适应宽度,当超过⼀⾏时,就按照默认的⽂本对齐⽅式。
grid同理,只不过对齐⽅式需要通过justify-items: center。
flex实现
.text{
display: flex;
justify-content: center;
}
grid实现
.text{
display: grid;
justify-items: center;
}
相对于flex,grid的兼容性要差⼀些,所以尽量选取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%**/
}
略微繁琐⼀点,不过也不失为⼀种⽅法,兼容性也极好
⼩结
上述⼀共列举了8种实现⽅式,当然第⼀种属于实验性质的,兼容性少的可怜,但也不失为⼀种思路。怎么想到这些⽅法呢?
第⼀就是联想。⽐如上述提到了⾃适应(简单来讲就是尺⼨由内容决定),我就想哪些可以实现⾃适应呢?除了inline-block,还有float、position:absolute、display:table等...⾸先float就排除了,元素设置了float后,整体居中其实是件⿇烦的事,⼏乎不可能(经过试验,可以实现)。position:absolute还是挺有希望的,借助left:50%;transform:translateX(-50%)可以实现居中效果, 尝试了⼀番,发现宽度⽆法⾃适应⽗级宽度,同样失败(说不定可以,只是没有想到)~~最后选择了diaplay:table,也算是循序渐进。flex和grid就更不⽤说了,天然就是为弹性布局⽽⽣了,实现这类效果不奇怪。
第⼆还是基础。CSS属性可就那么多,那只是停留在表⾯,很多看起来不相关的属性在整个体系中⼜会有些微妙的关系,⽐如上⾯的width:fill-content,单独看这个肯定很鸡肋,完全可以⽤inline-block来代替,但是他却可以让⼀个普通的div元素具备inline-block的特性,不得不佩服CSS的设计~(肯定有设计⼈员参与)
前⼀段时间在思考做⼀个可视化编辑⼯具,希望可以通过⼀些属性,就像photoshop那样,直接作出⼀个页⾯来,想想看,发现只能作出最最基本的样式,也就颜⾊,⼤⼩什么的,如果要做成本⽂这样⼀个效果,⼋成是做不了的,除了本⾝是做开发,别⼈怎么可能知道这样设置呢?可视化编辑⼯具的道路还很长很长,所以做前端的也⽆需担⼼被其他什么“⼀键⽣成⼯具”给取代了~
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论