CSS realizes the avatar of adaptive text

Author: @XboxYan
Original: https://segmentfault.com/a/1190000042675552

Table of contents

1. CSS container size unit

2. Adaptive text avatar

3. Some limitations of container query

1. First of all, the container query is only valid for the child elements of the container, not for itself, which leads to some redundant structure

2. Furthermore, the size of the container query box itself cannot be determined by the internal elements

3. Finally, the specific size corresponding to the container query size is a unit of size, which leads to many attributes that cannot be applied.

Fourth, summarize


There is such an avatar component in Ant-design. When the string is long, the font size can be automatically adjusted according to the width of the avatar. The effect is as follows 

Of course, this is achieved by JS automatically scaling the text according to the number of characters 

Now, a similar effect can be achieved only through CSS, let's take a look. You can also visit the online demo in advance: CSS avator (runjs.work)

1. CSS container size unit

Achieving this effect requires the help of container size units. These units appear together with the CSS container query, and there are the following

[Issue 2758] new features of the new era layout -- container query

For container query, you can refer to this article: Introduce the most anticipated and officially supported CSS container container query in 2022. This article does not involve specific container query statements

  • cqw container query width (Container Query Width) ratio. 1cqw is equal to 1% of the width of the container. Suppose the container width is 1000px, then the calculated value corresponding to 1cqw is 10px.

  • cqh container query height (Container Query Height) ratio. 1cqh is equal to 1% of the container height.

  • cqi indicates the proportion of container query inline size (Container Query Inline-Size). This is the logical attribute unit, which is equivalent to cqw by default

  • cqb container query block-level direction size (Container Query Block-Size) ratio. Same as above, equivalent to cqh by default

  • cqmin container query smaller size (Container Query Min) ratio. Take the smaller of cqw and cqh

  • cqmax indicates the proportion of container query with larger size (Container Query Min). Take the larger of cqw and cqh

With these size units, it is easy to realize that the size of the text changes with the size of the container. Here is an example

 <div class="con">
   <p class="text">大家好,欢迎关注前端侦探</p>
 </div>

In the case of not declaring the container type, cqw is equivalent to vw, which is equivalent to treating the entire page as a container. Here, we hope to use this div as a reference object, which needs to be declared in advance, as  container-typefollows

 .con {
     container-type: inline-size;
 }
 .text{
   font-size: 10cqw;
 }

The effect is as follows

In this way, the text scaling effect can be easily realized.

The principle is very simple, how to apply it?

2. Adaptive text avatar

Looking back at the actual case, how to make the font size adaptive according to the width of the avatar? That is, the more text, the smaller the font size.

A relatively simple idea is that the more text, the more width it occupies, and then according to the previous principle, let the text size change with the width, but here it is inversely proportional, the wider the width, the smaller the font size.

Suppose the HTML is like this

 <div class="avator">
     <span>侦探</span>
 </div>

simple modification

 .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;
 }

The effect is as follows

Now comes the problem. Currently, the width of the outer layer is fixed. It seems that there is no way to query the container according to the width occupied by the text. What should I do?

My idea is to create an identical text, let the width of the outer container (A) be determined by the inner text, and then set the width of the container box (B) to be the same as that of (A), so that the container is not completed query?

According to this idea, the HTML can be transformed into this

 <div class="avator">
   <div class="avator-inner" alt="侦探"><!--外层容器A-->
     <div class="avator-container"><!--容器盒子B-->
       <span>侦探</span>
     </div>
   </div>
 </div>

The text of outer container A can be generated by pseudo-element

 .avator-inner::before{
   content: attr(alt);
   font-size: 40px;
 }

At this time, the outer container A, that is, .avator-inner the size of is completely ::before expanded by pseudo-elements, as follows

Then, set the container box B, that is, .avator-container set it to be the same as the outer container A, and use absolute positioning

 .avator-container {
   position: absolute;
   inset: 0;
   container-type: inline-size;
   text-align: center;
   display: flex;
   justify-content: center;
   align-items: center;
 }

In this way, the container box can automatically change with the size of the pseudo-element, and then set an appropriate size for the internal text. Since it is inversely proportional, it can be subtracted, as follows

 .avator-container span {
   font-size: calc( 24px - 10cqw );
 }

The effect is as follows

Change the text again, such as 4 characters

It can be seen that the more text, the smaller the internal text size, which is exactly the effect we need

Next, hide the text generated by the pseudo-element to get the effect of the beginning of the article, as follows

Below is the full code

 .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;
 }

You can also visit the online demo: CSS avator (runjs.work)

3. Some limitations of container query

Although this effect was achieved earlier, it is not very elegant, mainly because there are many restrictions on container queries

1. First of all, the container query is only valid for the child elements of the container, not for itself, which leads to some redundant structure

In the above example, the div container also contains a p element, and the text size is set on the p element, which seems redundant. Can it be set directly on the div? This saves a layer of labels. The answer is no! The following is the effect of setting directly on the div

As you can see, the text size depends on the page view width. Therefore, if it is directly set on the div, then the container referenced by cqw is no longer itself at this time, but continues to search upwards until the outermost layer, that is to say, the object that cqw searches is the nearest parent container element, and Does not contain itself, this requires a lot of attention

2. Furthermore, the size of the container query box itself cannot be determined by the internal elements

This is the reason for creating the same text in the above example. For example, if the width of the container box itself is not set, the normal element width should be determined by the internal  inline-block text, but  container-type it will not work after setting. There is no width at all, which is why the width is set directly by absolute positioning.

However, the reason is also easy to understand: assuming this is true, if the font size of the child element changes, the width of the container will change, and the change of the container width will cause the font size to change. This is an infinite loop, so this is not allowed

3. Finally, the specific size corresponding to the container query size is a unit of size, which leads to many attributes that cannot be applied.

such as scale

In the above example, the text size is changed by  font-size changing. In fact, the best way is  scalebecause the browser has a minimum font size limit, and scale does not have this limit, but the unit cqw cannot be used on scale, slightly Sorry, it would be nice if there was a percentage unit

Of course, if you don’t mind the trouble, you can use @container for precise control

Fourth, summarize

The above is the whole content of this article. It mainly uses the container size unit to realize an adaptive text size effect, and summarizes some current limitations of some container queries. Let’s summarize it below

  • The container size unit is a new unit that appears along with the CSS container query, including cqw, cqh, cqi, cqb, cqmin, cqmax

  • The container size unit needs to be valid in the box that declares the container type, otherwise the entire page will be regarded as a container, which is equivalent to vw, vh

  • Since the width of the avatar is fixed, it cannot be queried directly based on the text width container. It is necessary to create a copy of the same text to create the container query condition

  • The more text on the avatar, the smaller the font size, so it is inversely proportional, you can use the method of subtraction

  • The implementation is not very elegant, and there are many HTML structures, mainly because there are many restrictions on container queries

  • The container query is only valid for the child elements of the container, not for itself, which leads to some redundant structure

  • The size of the container query box itself cannot be determined by the internal elements, which will lead to an infinite loop

  • The specific size corresponding to the container query size does not support relative units, such as percentage

However, despite many limitations, container query is still one of the most valuable new features at present, and many tricks and tricks that were previously needed can be implemented in new ways.

Guess you like

Origin blog.csdn.net/maxue20161025/article/details/127801415