Recently, a colleague asked me about such an interaction. When there is a large amount of text (more than 5 lines), the “full text” link appears, indicating that there is more content. After clicking it, it will jump to a new page

So, is there a way to do this without using JS? I looked at the interest, looked like the previous article CSS implementation of multi-line text “expand and fold” (juejin. Cn) a little similar? However, the layout is much simpler this time. After thinking about interaction for a long time, I found that it can be perfectly realized, and it is a completely different idea. Let’s take a look

A, layout,

There’s nothing more to study about the layout, just write it normally, and there’s no need to float it

<div class="wrap">
  <p class="text">The margin-bottom property of the CSS sets the bottom margin of the element, allowing negative values. A positive value will bring it farther from the neighboring block relative to the normal flow, while a negative value will bring it closer.</p>
  <a class="link">The full text</a>
</div>
Copy the code

Then add style and -webkit-line-clamp to 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; /* Multiple lines beyond ellipsis */
  -webkit-box-orient: vertical;
  line-height: 1.5;
}
Copy the code

You can get something like this

Obviously, the link below has always been there, too. So, how does CSS distinguish between these two cases?

Second, imperfect implementation

At first, I quickly came up with the following implementation

Use an element at the end of the text to mask the link below, which can be implemented with the pseudo-element ::after.

.text::after{
  content: ' ';
  position: absolute;
  display: block;
  width: 100%;
  height: 50px; /* As long as it covers the link */
  background: red;
}
Copy the code

Results the following

Note the implementation above, since the absolute positioning is not set, so ::after still follows the text. So in the case of text beyond, ::after is already out of visual range, so it doesn’t obscure the link below, which is actually what it looks like

Finally, change the covering color to the same background color

.text::after{
  background: inherit; /* Inherits the parent's background */
}
Copy the code

Auto expand cover (codepen.io)

So why is it not perfect?

As you may have noticed, when the link is not displayed, the space below is still occupied. When I implemented this to a colleague, it worked

Three, perfect realization

While there’s nothing wrong with the functionality, it must be visually unacceptable. A careful comparison of the two cases shows that the height of the two cases is not the same (😂 when the text is small, the default link height is less), so you can think about how to reduce the height of the container. Here I think of a negative margin, implemented as follows

First of all, you can’t use absolute positioning anymore

.text::after{
  content: ' ';
  /*position: absolute; * /
  display: block;
  height: 50px; /* Give me any height, or 0*/
  background: red;
}
Copy the code

I can give you any height here, it could be 0, so I gave it 50px for the sake of color, and I added a background color

This will have the following effect on a small amount of text (more text is already out of bounds and not affected)

Next, set negative margin-top to ::after, assuming the link height is 20, then move its height up plus 20, i.e

.text::after{
  /* Other styles */
  margin-top: -70px; 50 + 20 / * * /
}
Copy the code

You can see that the entire container height has now been subtracted from the link height, as shown below

For now, however, the link below is still visible. At this point, you can copy the text overlay and set the same style, then use the absolute positioning overlay (remember to add the background).

<div class="wrap">
  <p class="text">The margin-bottom property of the CSS sets the bottom margin of the element, allowing negative values. A positive value will bring it farther from the neighboring block relative to the normal flow, while a negative value will bring it closer.</p>
  <p class="copy">The margin-bottom property of the CSS sets the bottom margin of the element, allowing negative values. A positive value will bring it farther from the neighboring block relative to the normal flow, while a negative value will bring it closer.</p><! Add a new layer of tags -->
  <a class="link">The full text</a>
</div>
Copy the code
.text .copy{
  /* Same style */
}
.copy{
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
}
Copy the code

The schematic principle is as follows

This is perfect, although there is an extra layer of tags, but can also be generated using pseudo-elements

<div class="wrap">  
    <p class="text" title="The margin-bottom property of the CSS sets the bottom margin of the element, allowing negative values. A positive value will bring it farther from the adjacent block relative to the normal flow, while a negative value will bring it closer.>The margin-bottom property of the CSS sets the bottom margin of the element, allowing negative values. A positive value will bring it farther from the neighboring block relative to the normal flow, while a negative value will bring it closer.</p>  
    <a class="link">The full text</a>
</div>
Copy the code
.text::before{  
    content: attr(title);  /* Other styles */
}
Copy the code

Auto expand Margin (codepen.io)

Iv. Summary and explanation

Even if it’s just a small interaction, there are a lot of CSS tricks involved, so don’t worry about compatibility. Besides line-clamp, all other properties are fully compatible

  1. Take full advantage of CSS masking and overflow hiding, and many special effects can be used
  2. Absolute position Is still the default text stream position when left or top is not used
  3. A negative margin changes the size of the container

Perhaps in the future there will be a text beyond the pseudo class, such as trunk, so that many related interactions can be easily implemented. But before that, you can still use a variety of smoke and mirrors to simulate the implementation, although some are not concise, but is the unique fun of CSS is not it? Finally, if you think it’s good and helpful, please like, bookmark and retweet ❤❤❤