In a Vue.js application, truncating text can help display large amounts of text in a limited space, such as in a list or a card. Truncating text can help improve the readability and layout of the content by ensuring that it doesn’t take up too much space or become overwhelming for the user.
To truncate text in a Vue.js app, you can use the vue-clamp
library. This library provides a simple and lightweight component that adds a “Read more” link to reveal the full text in a designated area. This allows users to choose whether they want to read the full text or just the truncated version.
In this article, we’ll look at how to use the vue-clamp
library to truncate text in Vue.js applications.
Jump ahead:
vue-clamp
vue-clamp
vue-clamp
to truncate text in a Vue appvue-clamp
As stated in the introduction, vue-clamp
is an npm library that helps with the truncation of text in Vue apps.
There are several advantages to using vue-clamp
to truncate text in a Vue.js app:
vue-clamp
is a simple and easy-to-use library, with a straightforward API that allows you to quickly set up text truncationvue-clamp
provides a number of customization options, such as the ability to set the maximum number of lines that should be displayed before truncation, and the text and styling of the “Read more” linkvue-clamp
is designed to be responsive, so it can automatically adjust the truncation of text based on the available screen sizevue-clamp
is a lightweight library that has minimal impact on the performance of your Vue appIn order to show elaborate examples of vue-clamp
in action, we’ll build a small Vue app that displays a couple of blog posts.
N.B., we’ll build this application using Vue 2 because the vue-clamp
package is compatible with Vue 2. There is a different package that is compatible with Vue 3: vue3-text-clamp
.
First, let’s install the Vue-CLI by running the following command:
npm install -g @vue/cli
Once the installation is complete, we can create a new Vue project by running this command:
vue create v-clamp-tut
Proceed as usual and select the options you would like to have, making sure to select 2.x when asked for the Vue version.
In the router/index.js
file, update its contents to look as follows:
import Vue from "vue"; import VueRouter from "vue-router"; // import HomeView from "../views/HomeView.vue"; import PostView from "../views/PostView.vue"; import SinglePost from "../views/SinglePost.vue"; Vue.use(VueRouter); const routes = [ { path: "/post", name: "home", component: PostView, }, { path: "/post/:id", name: "singlePost", component: SinglePost, }, ]; const router = new VueRouter({ mode: "history", base: process.env.BASE_URL, routes, }); export default router;
The above lines of code take care of the routing in our Vue application.
Next, create an index.js
file in the store
directory and place the following lines of code in it:
export const posts = [ { id: "1", author: "Jane Doe", description: "A post about the benefits of meditation", content: "Meditation has been shown to have a number of benefits for both the mind and the body. It can reduce stress and anxiety, improve focus and concentration, and even help to lower blood pressure. In this post, we'll explore some of the science behind meditation and how you can get started with a daily practice.", photo: "https://blog.logrocket.com/wp-content/uploads/2020/11/rust-grpc-tonic.png", featured: true, }, { id: "2", author: "John Smith", description: "A guide to creating a successful morning routine", content: "Starting your day off on the right foot can set the tone for the rest of the day. In this post, we'll go over some tips for creating a morning routine that will help you feel energized, productive, and ready to tackle the day ahead. From exercise and meditation to making your bed and setting goals, we've got you covered.", photo: "https://images.unsplash.com/photo-1591035897819-f4bdf739f446?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxzZWFyY2h8MTB8fGhhcHB5fGVufDB8fDB8fA%3D%3D&auto=format&fit=crop&w=500&q=60", featured: false, }, { id: "3", author: "Sara Johnson", description: "The importance of self-care for busy professionals", content: "In today's fast-paced world, it's easy to get caught up in the hustle and forget to take care of ourselves. But self-care is crucial for maintaining our physical, mental, and emotional health. In this post, we'll explore some simple self-care strategies that busy professionals can incorporate into their daily routines. With cold and flu season in full swing, it's important to take steps to boost our immune systems. In this post, we'll go over five natural ways to support your body's natural defenses, including eating a healthy diet, getting enough sleep, and reducing stress. By following these tips, you can help keep yourself healthy and feeling your best.", photo: "https://images.unsplash.com/photo-1524250502761-1ac6f2e30d43?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxzZWFyY2h8MTZ8fGhhcHB5fGVufDB8fDB8fA%3D%3D&auto=format&fit=crop&w=500&q=60", featured: true, }, { id: "4", author: "Emily Williams", description: "5 ways to boost your immune system naturally", content: "With cold and flu season in full swing, it's important to take steps to boost our immune systems. In this post, we'll go over five natural ways to support your body's natural defenses, including eating a healthy diet, getting enough sleep, and reducing stress. By following these tips, you can help keep yourself healthy and feeling your best.", photo: "https://images.unsplash.com/photo-1489710437720-ebb67ec84dd2?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxzZWFyY2h8MTd8fGhhcHB5fGVufDB8fDB8fA%3D%3D&auto=format&fit=crop&w=500&q=60", featured: false, }, { id: "5", author: "Alex Thompson", description: "The benefits of journaling for mental health", content: "Journaling has long been recognized as a powerful tool for self-reflection and personal growth. In this post, we'll look at the science behind why journaling is so beneficial for mental health and provide some tips for getting started with your own journaling practice.", photo: "https://images.unsplash.com/photo-1519834785169-98be25ec3f84?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxzZWFyY2h8MjF8fGhhcHB5fGVufDB8fDB8fA%3D%3D&auto=format&fit=crop&w=500&q=60", featured: true, }, { id: "6", author: "Laura Davis", description: "The best plant-based protein sources", content: "If you're trying to incorporate more plant-based protein into your diet, you're in luck! There are plenty of delicious and nutritious options to choose from. In this post, we'll go over some of the best plant-based protein sources, including beans, lentils, tofu, and more. Plus, we'll include some tasty recipe ideas to help you get started.", photo: "https://images.unsplash.com/photo-1657664073337-31394d7e5c7a?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxzZWFyY2h8NXx8aGFwcHl8ZW58MHx8MHx8&auto=format&fit=crop&w=500&q=60", featured: false, }, ];
This file will help us with the data rendered on the Vue frontend as we won’t make any real API calls.
Finally, create two files in the views
folder: PostView.vue
and SinglePost.vue
.
In the PostView.vue
file, add the following code:
<template> <div class="home"> <h1>All Posts</h1> </div> </template> <style> </style> <script> import { posts } from "../store/articles.js"; export default { name: "PostView", components: {}, data: function () { return {}; }, methods: {}, computed: {}, }; </script>
And in the SinglePost.vue
file, add this code:
<template> <div class="home"> <div class="homeContainer"> <h1>Single Post</h1> <hr /> </div> </div> </template> <style> </style> <script> import { posts } from "../store/articles.js"; export default { name: "SinglePost", components: { }, data: () => { return {}; }, methods: {}, created() {}, }; </script>
vue-clamp
in a Vue applicationFirst, let’s start by installing the vue-clamp
library. You can do this by running the following command in your terminal:
npm install vue-clamp
Once the library is installed, we’ll need to import it into the Vue component. We can do this by adding the following lines to the component’s script tag:
import VClamp from "vue-clamp"; export default { ... components: { VClamp, }, ... }
Finally, we use the v-clamp
component in our component’s template:
<v-clamp></v-clamp>
vue-clamp
to truncate textNow that we’ve installed the vue-clamp
library, let’s see how to use it to carry out basic text truncation in a Vue app.
First, update the contents of the PostView.vue file with the following lines of code:
<template> <div class="home"> <h1>All Posts</h1> <div class="homeContainer"> <div v-for="(post, i) of articles" :key="i" class="articles"> <img class="thumbnail" :src="`${post.photo}`" alt="" /> <div class="text-content"> <h3>{{ post.description }}</h3> <!-- clamping post content --> <v-clamp autoresize :max-lines="max_lines" ellipsis="..." location="end"> {{ post.content }} </v-clamp> <router-link :to="`/post/${post.id}`"> <button class="button">Read</button> </router-link> </div> </div> </div> </div> </template> <style> .homeContainer { width: 60%; margin: 0px auto; /* border: 1px solid black; */ } .articles { display: flex; flex-direction: row; margin: 2em; align-items: center; } .thumbnail { width: 100px; height: 100px; display: inline; } .text-content { text-align: left; margin: 0 0 0 1em; } .button { padding: 0.5em; } .tags { background-color: rgb(33, 33, 180); border-radius: 50px; border: 0px; color: white; padding: 0.5em; margin-right: 2px; } </style> <script> import VClamp from "vue-clamp"; import { posts } from "../store/articles.js"; export default { name: "PostView", components: { VClamp, }, data: function () { return { articles: posts, max_lines: 2, }; } }; </script>
The code snippet above iterates through the posts in store/articles.js
, then displays the appropriate data. The text displayed between the <v-clamp>
tag is truncated appropriately.
vue-clamp
allows modifications to the display of the truncated text using props. Here are some of the allowed props and their functionalities:
Prop | Use | Default | Values |
---|---|---|---|
max-line |
Allows us to specify how many lines we want the truncated text to span | Any number | |
ellipsis |
Allows us to specify the particular ellipsis we wish to use to specify truncated text | ‘…’ | Any string |
location |
Specifies where text should be truncated from | ‘start’ | ‘start’ |
vue-clamp
vue-clamp
also allows us to modify the behavior of the clamp using slots. vue-clamp
provides before
and after
slots. The effects of the before
slot are seen before the clamped text and the results of the after
slot are seen after the clamped text.
To see scenarios of these slots, let’s add slots to the <v-clamp>
in our PostView.vue
and singlePost.vue
views.
In PostView.vue
, update the <v-clamp>
tag as follows:
... <v-clamp autoresize :max-lines="max_lines" ellipsis="..." location="end" > {{ post.content }} <template v-if="post.featured" #before> <button class="tags">Featured</button> </template> <template #after="{ toggle, clamped }"> <button @click="toggle"> {{ clamped == true ? "see more" : "see less" }} </button> </template> </v-clamp> ...
The result of the above code can be seen in the image below:
The Featured
tag is displayed using the before
slot while the see more/see less
button is displayed using the after
slot.
Slot scopes allow for the passing of state from the parent to the slots. vue-clamp
has a couple of slots that allow us to use the state of the parent clamp in the before
and after
slots:
... <template #after="{ toggle, clamped, expanded, expand, collapse }"> ... </template> ...
These slot scopes are useful because we can have data on the state of each clamped text. So we can do things like toggle the clamped state of a single text without affecting others, and change what our expand buttons say for a single clamped text. In a nutshell, these slot scopes help to scope events to each clamped text.
In SinglePost.vue
, update its entire contents with the following code:
<template> <div class="home"> <div class="homeContainer"> <h1>{{ post.description }}</h1> <img alt="Vue logo" :src="`${post.photo}`" /> <div class="text-content"> <v-clamp autoresize :max-lines="max_lines"> {{ post.content }} <template #after="{ toggle, clamped, expanded }"> <button v-if="clamped == true || expanded == true" @click="toggle"> {{ clamped == true ? "see more" : "see less" }} </button> </template> </v-clamp> </div> <hr /> </div> </div> </template> <style> .homeContainer { width: 60%; margin: 0px auto; /* border: 1px solid black; */ } .text-content { text-align: left; margin: 2em 0 0 1em; } .button { padding: 0.5em; } </style> <script> import VClamp from "vue-clamp"; import { posts } from "../store/articles.js"; export default { name: "SinglePost", components: { VClamp, }, data: () => { return { max_lines: 3, }; }, methods: {}, created() { this.id = this.$route.params.id; this.post = posts.find((el) => el.id == this.id); }, }; </script>
In the code block above, using the created()
lifecycle method, we fetched a single post and displayed its contents. Within the <v-clamp>
, we’re using an after
slot to check for the clamped state of the text and then displaying the appropriate button.
Clampchange
eventsvue-clamp
provides a clampchange
event that allows us to perform an action when the clamp state changes from clamped
to expanded
and vice versa. It gives a clamped callback with a Boolean value depending on the current clamped state:
... <v-clamp autoresize :max-lines="max_lines" @clampchange="changed"> ... </v-clamp> ... //inside your script ... methods: { changed(clamped) { console.log("clamped", clamped); }, }, ...
In the code snippet above, we console.log
the current clamped state of the text within the <v-clamp>
tag, in order to see what it returns. If the clamped stated is toggled, its new state is printed out to the console.
And there we have it! We were able to build a blog application using vue-clamp
and gain an understanding of advanced techniques, including slots, slot scopes, and events.
In this article, we learned how to simplify the process of truncating text in Vue apps using the vue-clamp
library.
As a recap, truncating text can be useful in a Vue.js app for several reasons:
Check out this GitHub repo containing the complete code for this article.
Debugging Vue.js applications can be difficult, especially when there are dozens, if not hundreds of mutations during a user session. If you’re interested in monitoring and tracking Vue mutations for all of your users in production, try LogRocket.
LogRocket is like a DVR for web and mobile apps, recording literally everything that happens in your Vue apps, including network requests, JavaScript errors, performance problems, and much more. Instead of guessing why problems happen, you can aggregate and report on what state your application was in when an issue occurred.
The LogRocket Vuex plugin logs Vuex mutations to the LogRocket console, giving you context around what led to an error and what state the application was in when an issue occurred.
Modernize how you debug your Vue apps — start monitoring for free.
Would you be interested in joining LogRocket's developer community?
Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.
Sign up nowBuild scalable admin dashboards with Filament and Laravel using Form Builder, Notifications, and Actions for clean, interactive panels.
Break down the parts of a URL and explore APIs for working with them in JavaScript, parsing them, building query strings, checking their validity, etc.
In this guide, explore lazy loading and error loading as two techniques for fetching data in React apps.
Deno is a popular JavaScript runtime, and it recently launched version 2.0 with several new features, bug fixes, and improvements […]