乐趣区

关于前端:CSS-实现自适应文本的头像

欢送关注我的公众号:前端侦探

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)占比。取 cqwcqh较小 的一个
  • cqmax 示意容器查问较大尺寸的(Container Query Min)占比。取 cqwcqh较大 的一个

有了这些尺寸单位,能够很轻易的实现文字大小随着容器尺寸的变动而变动,上面举个例子

<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 进行精准管制

四、总结一下

以上就是本文全部内容了,次要是利用容器尺寸单位实现了一个自适应文本大小的成果,以及总结了一些容器查问目前的一些局限性,上面总结一下

  1. 容器尺寸单位是追随 CSS 容器查问一起呈现的新单位,有 cqw、cqh、cqi、cqb、cqmin、cqmax
  2. 容器尺寸单位须要在申明容器类型的盒子内才无效,不然会把整个页面当成容器,等同于 vw、vh
  3. 因为头像宽度是固定的,无奈间接依据文字宽度容器查问,须要创立一份雷同的文原本创立容器查问条件
  4. 头像文字越多,字号越小,所以是成反比,能够采纳相减的形式
  5. 实现还不是很优雅,HTML 构造比拟多,次要是因为容器查问有诸多的限度
  6. 容器查问只对容器的子元素无效,对自身有效,这样导致构造有些冗余
  7. 容器查问盒子尺寸自身不能由外部元素所决定,会导致死循环
  8. 容器查问尺寸对应的具体的尺寸,不反对绝对单位,比方百分比

不过,只管有诸多限度,容器查问依然是目前最具价值的新个性之一了,以前很多须要用到的奇技淫巧都能够用新的形式来实现了,这个前面再分享。最初,如果感觉还不错,对你有帮忙的话,欢送点赞、珍藏、转发❤❤❤

欢送关注我的公众号:前端侦探

退出移动版