32
头图

Recently, a colleague asked me about such an interaction. When there is a lot of text (more than 5 lines), a "full text" link appears, indicating that there is more content. After clicking it, you will jump to a new page. The effect is as follows

image-20210619183222438

So, is there a way to achieve it without using js? I was intrigued as soon as I saw it. It seemed a bit similar to the CSS Implementing Multi-line Text "Expand and Collapse" (juejin.cn) But this time the layout is much simpler. After a long time of interaction, I found that it can be perfectly realized, and it is a completely different idea. Let’s take a look.

1. Layout

There is nothing to study about the layout, just write it normally, and there is no need for floating. The implementation is as follows

<div class="wrap">
  <p class="text">CSS的 margin-bottom 属性用于设置元素的底部外边距,允许设置负数值。一个正数值将让它相对于正常流与邻近块更远,而负数值将使得更近。</p>
  <a class="link">全文</a>
</div>

Then add some styles, -webkit-line-clamp achieve multi-line truncation

.wrap {
  background: #fff;
  border-radius: 8px;
  padding: 15px;
  box-shadow: 20px 20px 60px #bebebe,
    -20px -20px 60px #ffffff;
}

.text{
  overflow: hidden;
  text-overflow: ellipsis;
  text-align: justify;
  display: -webkit-box;
  -webkit-line-clamp: 3; /*多行超出省略*/
  -webkit-box-orient: vertical;
  line-height: 1.5;
}

Can get this effect

WeChatcb5c261942c01cf6b86aff084ea3902d

Obviously, the link below has always existed. So, how does CSS distinguish between these two situations?

Second, imperfect realization

At first, I quickly thought of a way to achieve it, as follows

At the end of the text, use an element cover the link below, which can be implemented ::after

.text::after{
  content: '';
  position: absolute;
  display: block;
  width: 100%;
  height: 50px; /*只要能盖住链接就行*/
  background: red;
}

The effect is as follows

WeChatf3ea94b878055a68706d38979366e110

Note that to achieve the above, as at the time of setting absolute positioning, and is not set top value, ::after back still followed in the text. Therefore, when the text is out of ::after already outside the visible range, so the link below will not be covered. It actually looks like this

image-20210620223022954

Finally, change the color of the cover to the same background color.

.text::after{
  background: inherit; /*继承父级的背景*/
}

Kapture 2021-06-21 at 19.04.33

The complete code can be accessed auto expand cover (codepen.io)

So why is it imperfect?

Careful friends may have discovered that when the link is not displayed, the space below is still occupied. When I gave this realization to a colleague, it really was like this

image-20210619195050563

Three, perfect realization

Although there is nothing wrong with the function, it is definitely difficult to accept visually. Comparing the difference between the two cases carefully, it is not difficult to find that the height of the two cases is different (😂When there is less text, the height of one line of links is less by default), so you can think about how to reduce the height of the container? Here I think of the negative margin , which is realized as follows

First of all, absolute positioning must not be used anymore

.text::after{
  content: '';
  /*position: absolute;*/
  display: block;
  height: 50px; /*随便给一个高度,也可以为0*/
  background: red;
}
You can give any height here, and it can also be 0. For the convenience of the color, 50px is given, and a background color is added.

In this way, the effect when there is less text is as follows (it is out of bounds when there is more text, it will not be affected)

image-20210619210740118

Then, to ::after set a negative margin-Top , assuming that the height of the link is 20, then you need to move up their own height plus 20, that is,

.text::after{
  /*其他样式*/
  margin-top: -70px; /*50 + 20*/
}

image-20210619214435486

It can be found that the height of the entire container has been subtracted from the height of the link. The demonstration is as follows

HZBdkv1EaCzJ8Nf But now the link below is still visible. At this time, you can copy a copy of the text overlay, and set the same style, and then use the absolute positioning overlay (remember to add the background)

<div class="wrap">
  <p class="text">CSS的 margin-bottom 属性用于设置元素的底部外边距,允许设置负数值。一个正数值将让它相对于正常流与邻近块更远,而负数值将使得更近。</p>
  <p class="copy">CSS的 margin-bottom 属性用于设置元素的底部外边距,允许设置负数值。一个正数值将让它相对于正常流与邻近块更远,而负数值将使得更近。</p><!--新加一层标签-->
  <a class="link">全文</a>
</div>
.text .copy{
  /*相同的样式*/
}
.copy{
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
}

The principle is as follows

Kapture 2021-06-19 at 22.14.46

This is perfect. Although there is an extra layer of label, it can also be generated with pseudo elements

<div class="wrap">  
    <p class="text" title="CSS的 margin-bottom 属性用于设置元素的底部外边距,允许设置负数值。一个正数值将让它相对于正常流与邻近块更远,而负数值将使得更近。">CSS的 margin-bottom 属性用于设置元素的底部外边距,允许设置负数值。一个正数值将让它相对于正常流与邻近块更远,而负数值将使得更近。</p>  
    <a class="link">全文</a>
</div>
.text::before{  
    content: attr(title);  /*其他样式*/
}

Kapture 2021-06-21 at 19.01.44

The complete code can be viewed auto expand margin (codepen.io)

Four, summary and explanation

Even if it's just a small interaction, it also contains a lot of CSS tips, so there is no need to worry about compatibility. Except for line-clamp , all other attributes are fully compatible. To sum up the following points

  1. Make full use of CSS cover and overflow hiding, many special effects can be used
  2. Absolute positioning is still in the default text flow position when left or top is not used
  3. Negative margin can change the size of the container

Perhaps in the future there will be a text beyond the pseudo-category, such as :trunk , so that many related interactions can be easily realized. But before that, it can still be realized by various blindfold simulations. Although some are not concise enough, it is the unique fun of CSS, isn't it? Finally, if you think it’s pretty good, if it’s helpful to you, please like, bookmark, and forward ❤❤❤


XboxYan
18.1k 声望14.1k 粉丝