欢送关注我的公众号:前端侦探
Ant-design
中有一个这样的头像组件,当字符串较长时,字体大小能够依据头像宽度主动调整,成果如下
当然,这里是通过 JS
依据字符数量主动缩放文本实现的
而当初,仅仅通过 CSS
也能达到相似的成果,一起看看吧
你也能够提前拜访线上 demo:CSS avator (runjs.work)
一、CSS 容器尺寸单位
实现这个成果须要借助 容器尺寸单位。这些单位是追随 CSS 容器查问一起呈现的,有以下几种
对于容器查问,能够参考这篇文章:介绍 2022 最期待且已正式反对的 CSS container 容器查问 « 张鑫旭 - 鑫空间 - 鑫生存 (zhangxinxu.com),本文并不波及具体容器查问语句
- cqw 容器查问宽度(Container Query Width)占比。1cqw 等于容器宽度的 1%。假如容器宽度是 1000px,则此时 1cqw 对应的计算值就是 10px。
- cqh 容器查问高度(Container Query Height)占比。1cqh 等于容器高度的 1%。
- cqi 示意容器查问内联方向尺寸(Container Query Inline-Size)占比。这个是逻辑属性单位,默认状况下等同于cqw
- cqb 容器查问块级方向尺寸(Container Query Block-Size)占比。同上,默认状况下等同于cqh
- cqmin 容器查问较小尺寸的(Container Query Min)占比。取 cqw和 cqh 中较小 的一个
- cqmax 示意容器查问较大尺寸的(Container Query Min)占比。取 cqw和 cqh 中较大 的一个
有了这些尺寸单位,能够很轻易的实现文字大小随着容器尺寸的变动而变动,上面举个例子
<div class="con">
<p class="text"> 大家好,欢送关注前端侦探 </p>
</div>
在不申明容器类型的状况下,cqw
等同于 vw
,也就是相当于把整个页面当成容器,这里心愿将这个div
作为参考对象,须要提前申明container-type
,如下
.con {container-type: inline-size;}
.text{font-size: 10cqw;}
成果如下
这样就很轻易的实现了文本缩放成果。
原理很简略,怎么利用呢?
二、自适应文本头像
再回过头来看看理论案例,如何让字体大小依据头像宽度自适应呢?也就是文字越多,字号越小。
有一个比较简单的思路就是,文字越多,占据的宽度越多,而后依据后面的原理,让文字大小随着宽度的变动而变动,只不过这里是成反比,宽度越宽,字号越小。
假如 HTML
是这样的
<div class="avator">
<span> 侦探 </span>
</div>
简略润饰一下
.avator{
display: flex;
align-items: center;
justify-content: center;
width: 40px;
height: 40px;
border-radius: 8px;
background: bisque;
color: rgb(250, 84, 28);
white-space: nowrap;
}
成果如下
当初问题来了,目前外层宽度是固定的,如同没方法依据文字占据宽度就行容器查问,怎么办呢?
我的思路是这样的,创立一份截然不同的文本,让外层容器(A)宽度由外部文本决定,而后将容器盒子(B)的宽度设置成和(A)一样,这样不就实现了容器查问吗?
依据这个思路,能够将 HTML
革新成这样
<div class="avator">
<div class="avator-inner" alt="侦探"><!-- 外层容器 A -->
<div class="avator-container"><!-- 容器盒子 B -->
<span> 侦探 </span>
</div>
</div>
</div>
外层容器 A 的文本能够通过伪元素生成
.avator-inner::before{content: attr(alt);
font-size: 40px;
}
这时外层容器 A,也就是 .avator-inner
的尺寸齐全由伪元素 ::before
撑开,如下
而后,将容器盒子 B,也就是 .avator-container
设置成和外层容器 A 一样,能够采纳相对定位的形式
.avator-container {
position: absolute;
inset: 0;
container-type: inline-size;
text-align: center;
display: flex;
justify-content: center;
align-items: center;
}
这样,容器盒子就能够追随伪元素所占大小主动变动了,而后给外部文字设置一个适合的大小,因为是 成反比 ,所以能够采取 相减 的形式,如下
.avator-container span {font-size: calc( 24px - 10cqw);
}
成果如下
再换一下文本,比方 4 个字的
能够看到,文本越多,外部文字大小越小,正好是咱们须要的成果
上面把伪元素生成的文本暗藏起来,就能够失去文章结尾的成果了,如下
上面是残缺代码
.avator{
display: flex;
align-items: center;
justify-content: center;
width: 40px;
height: 40px;
border-radius: 8px;
background: bisque;
color: rgb(250, 84, 28);
white-space: nowrap;
}
.avator-inner{position: relative;}
.avator-inner::before{content: attr(alt);
visibility: hidden;
font-size: 40px;
}
.avator-container {
position: absolute;
inset: 0;
container-type: inline-size;
text-align: center;
display: flex;
justify-content: center;
align-items: center;
}
.avator-container span {font-size: calc( 24px - 10cqw);
overflow: hidden;
max-width: 40px;
text-overflow: ellipsis;
}
你也能够拜访线上 demo:CSS avator (runjs.work)
三、容器查问的一些局限性
尽管后面实现这样的成果,然而还不是很优雅,次要是因为容器查问有诸多的限度
1. 首先,容器查问只对容器的子元素无效,对自身有效,这样导致构造有些冗余
在下面的例子中,div
容器中还蕴含了一个 p
元素,文字大小是设置在 p
元素上,看似有些多余,能不能间接设置在 div
上呢?这样就能够省一层标签了。答案是 不能够!上面是间接设置在 div
上的成果
能够看到,文字大小依赖于页面视图宽度了。所以,如果间接设置在 div
上,那么此时 cqw
参考的容器就不再是自身了,而是持续向上查找,直到最外层,也就是说 cqw
查找的对象是 最近的父级容器元素,并不蕴含本身,这个须要多多留神
2. 再者,容器查问盒子尺寸自身不能由外部元素所决定
下面的例子中为啥要创立一份雷同的文本呢,起因就是这个,比方在容器盒子自身不设置宽度的状况下,失常的 inline-block
元素宽度应该是有外部文本决定的,然而设置 container-type
之后就不行了,齐全没有宽度了,这也就是为啥后面要通过相对定位的形式间接设置宽度了
不过这个起因也容易了解:假如这个成立,如果子元素字号发生变化,导致容器宽度发生变化,容器宽度发生变化又会导致字号发生变化,这样就死循环了,所以不容许这种状况
3. 最初,容器查问尺寸对应的具体的尺寸,是一种尺寸单位,这样导致有很多属性无奈利用,比方scale
在下面的例子中,文字大小是通过 font-size
扭转的,其实最好的形式是 scale
,因为浏览器有最小字号的限度,而scale
就没这个限度了,然而 cqw
这种单位无奈用在 scale
之上,稍微遗憾,如果有一种百分比单位就好了
当然,不嫌麻烦的能够用 @container
进行精准管制
四、总结一下
以上就是本文全部内容了,次要是利用容器尺寸单位实现了一个自适应文本大小的成果,以及总结了一些容器查问目前的一些局限性,上面总结一下
- 容器尺寸单位是追随 CSS 容器查问一起呈现的新单位,有 cqw、cqh、cqi、cqb、cqmin、cqmax
- 容器尺寸单位须要在申明容器类型的盒子内才无效,不然会把整个页面当成容器,等同于 vw、vh
- 因为头像宽度是固定的,无奈间接依据文字宽度容器查问,须要创立一份雷同的文原本创立容器查问条件
- 头像文字越多,字号越小,所以是成反比,能够采纳相减的形式
- 实现还不是很优雅,HTML 构造比拟多,次要是因为容器查问有诸多的限度
- 容器查问只对容器的子元素无效,对自身有效,这样导致构造有些冗余
- 容器查问盒子尺寸自身不能由外部元素所决定,会导致死循环
- 容器查问尺寸对应的具体的尺寸,不反对绝对单位,比方百分比
不过,只管有诸多限度,容器查问依然是目前最具价值的新个性之一了,以前很多须要用到的奇技淫巧都能够用新的形式来实现了,这个前面再分享。最初,如果感觉还不错,对你有帮忙的话,欢送点赞、珍藏、转发❤❤❤
欢送关注我的公众号:前端侦探