Thoughts on truncation of multi-line text with a "show more" button

Thoughts on truncation of multi-line text with a "show more" button

I just happened to encounter this small requirement recently. I remember that I used JS to handle it a long time ago, after all, I was young and ignorant at that time. The switching operation can be implemented with the Checked pseudo-class, which is a bit cheaper. Here are the key points:

  1. Multi-line text is truncated and ellipsis is displayed
  2. The "Show More" button expands all text
  3. After expanding the text, the button text becomes "Collapse Text"
  4. The button appears when the text is truncated (if your text is only one line, there is no need to display it :sweat:)

Question: text-overflow: ellipsis does not support multi-line truncation. How to switch the text of a button with CSS? How to determine the conditions for the button to appear? I will explain them one by one below:balloon:

Multi-line text truncation

Assume that the existing HTML structure is as follows:

<div class="box">
  <p>Text content</p>
</div>

If you need to truncate a single line, the general approach is:

p {
  text-overflow: ellipsis;
  overflow: hidden;
  white-space: nowrap;
}

The effect is as follows:

Multi-line text requires line-clamp to define the number of lines of truncated text:

p {
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

The effect is as follows:

Button click to display all text

Now the HTML structure is transformed into the following:

<div class="box">
  <input type="checkbox" name="toggle" id="toggle" style="display: none;">
  <p>Text content</p>
  <label for="toggle">Show more</label>
</div>

To monitor the click behavior of a button, use the Checked pseudo-class mentioned at the beginning of the article:

input[name="toggle"]:checked {
 & + p {
   -webkit-line-clamp: unset;
 }
}

In this way, when the user clicks (selects), all text will be displayed, and the text will be hidden if it is not selected:

Dynamic button text

Logically speaking, after all the text is displayed, the button text should be switched to "Collapse Text". How to modify the text with CSS? In fact, just use the content pseudo-element.

Remove the text from HTML and replace it with CSS control:

<label for="toggle"></label>

label {
  &::after {
    content: "show more";
  }
}

Similarly, we can get:

input[name="toggle"]:checked {
  & ~ label {
    &::after {
      content: "Collapse text";
    }
  }
}

The effect is as follows:

If the button style is ugly, adjust it yourself :sweat:

Conditions under which the button appears

When the text is less than three lines, the button should not appear, because it is unnecessary:

There is a big problem. After surfing the Internet, I found that there is no pseudo-class to determine whether the text is truncated. If there is, we can do this:

p {
 &:truncated {
   & + label {
    display: block;
   }
 }   
}
label {
  display: none;
}

truncated means truncated.

But even so, we can't achieve our needs, because when you display all the text, your text is not truncated, so the button will disappear:

The above is a simulation effect achieved by a piece of JS. The source code is as follows:

let list = document.querySelectorAll("p");
let observer = new ResizeObserver(entries => {
  entries.forEach(item => {
    item.target.classList[item.target.scrollHeight > item.contentRect.height ? "add" : "remove"]("truncated");
  });
});

list.forEach(p => {
  observer.observe(p);
});

The principle is to monitor the size changes of text elements, and then dynamically add truncated class name: joy:

So, the truncated pseudo-class in your CSS should be changed to the truncated class:sweat:

p {
 &.truncated {
   & + label {
    display: block;
   }
 }   
}

We hope that the button will always be there when switching, instead of not showing the button when the text is not truncated. Therefore, we do not need to monitor the size change of the text element all the time. We only need an initial value (whether the text is truncated when it is initialized), that is, we only monitor once!

entries.forEach(item => {
  //... original code observer.unobserve(item.target); // remove the monitor });

Or you don't need to use this API at all, just traverse and judge once when the page is initialized!

let list = document.querySelectorAll("p");

list.forEach(item => {
  item.classList[item.scrollHeight > item.offsetHeight ? "add" : "remove"]("truncated");
});

In this way, the P element will automatically be added with the truncated class name when the page is initialized, and the button can be displayed all the time:

Extensions

For example, you can customize the button style, add a transparent gradient mask at the bottom, and the transition effect when switching:grin:

Summarize

The checked pseudo-class is a good thing, it can meet many needs without writing JS, so you can consider using it for any operation related to switching classes.

The above is what I would like to share with you about multi-line text truncation with a "Show More" button. I hope it will be helpful to you. If you have any questions, please leave me a message and I will reply to you in time. I would also like to thank everyone for their support of the 123WORDPRESS.COM website!
If you find this article helpful, please feel free to reprint it and please indicate the source. Thank you!

<<:  Explanation of the problem that JavaScript strict mode does not support octal

>>:  You may need a large-screen digital scrolling effect like this

Recommend

How to build your own Nexus private server in Linux

This article describes how to build a Nexus priva...

MySQL login and exit command format

The command format for mysql login is: mysql -h [...

Detailed example of using typescript to encapsulate axios in Vue3

This axios package is used in the vue3 demo. For ...

MySql 8.0.11 installation and configuration tutorial

Official website address: https://dev.mysql.com/d...

A guide to writing flexible, stable, high-quality HTML and CSS code standards

The Golden Rule Always follow the same set of cod...

Usage of Linux userdel command

1. Command Introduction The userdel (user delete)...

React Router 5.1.0 uses useHistory to implement page jump navigation

Table of contents 1. Use the withRouter component...

A brief analysis of Vue's asynchronous update of DOM

Table of contents The principle of Vue asynchrono...

Summary of practical skills commonly used in Vue projects

Table of contents Preface 1. Use $attrs and $list...

MySQL Constraints Super Detailed Explanation

Table of contents MySQL Constraint Operations 1. ...

Summary of some situations when Docker container disk is full

Preface This article describes two situations I h...

Detailed explanation of the correct use of the count function in MySQL

1. Description In MySQL, when we need to get the ...

MySQL installation tutorial under Linux centos7 environment

Detailed introduction to the steps of installing ...