Text Truncation Without the Drama
How line-clamp truncates text in four lines of CSS - no JS, no npm package, no polyfill needed.
Let’s take a general card layout, we’ve all seen this before right? Standard image, heading and text content. I’m leaving out a link, because how that is placed is a whole other thing.
Card heading
Laborum sint laborum nostrud est. Est exercitation et occaecat ut proident non voluptate et. Laborum non id voluptate tempor ea anim anim eu irure laborum velit labore ullamco. Non ipsum labore consequat adipisicing amet ut reprehenderit.
You’ve got the markup done to the design, but haven’t accounted for the huge amount of text that the client will undoubtedly drop into only some of them.
Card heading
Laborum sint laborum nostrud est. Est exercitation et occaecat ut proident non voluptate et. Laborum non id voluptate tempor ea anim anim eu irure laborum velit labore ullamco. Non ipsum labore consequat adipisicing amet ut reprehenderit. Laborum sint laborum nostrud est. Est exercitation et occaecat ut proident non voluptate et. Laborum non id voluptate tempor ea anim anim eu irure laborum velit labore ullamco. Non ipsum labore consequat adipisicing amet ut reprehenderit.Laborum sint laborum nostrud est. Est exercitation et occaecat ut proident non voluptate et. Laborum non id voluptate tempor ea anim anim eu irure laborum velit labore ullamco. Non ipsum labore consequat adipisicing amet ut reprehenderit.Laborum sint laborum nostrud est. Est exercitation et occaecat ut proident non voluptate et. Laborum non id voluptate tempor ea anim anim eu irure laborum velit labore ullamco. Non ipsum labore consequat adipisicing amet ut reprehenderit.
Yuck. So we need to trim it down, make it look a bit more visually pleasing to the user right? We could just add a max-height to the cards, with an overflow: hidden on the p tag…maybe? Chuck in a few media queries to adjust for smaller screen sizes?
Card heading
Laborum sint laborum nostrud est. Est exercitation et occaecat ut proident non voluptate et. Laborum non id voluptate tempor ea anim anim eu irure laborum velit labore ullamco. Non ipsum labore consequat adipisicing amet ut reprehenderit.
Well that looks terrible, and also ignores any padding that might around the content (hint: there is). We need to be able to trim the text off nicely, which is where line-clamp comes in. Hooray!
Using this property allows any text to be cut off, with the end of the visible text be replaced with an ellipses. There’s a few ways of doing this already kind of, using JS (there’s even a handy (?) npm script to help line-clamp ), Clamp.js or the text-overflow property, as shown below.
Card heading
Laborum sint laborum nostrud est. Est exercitation et occaecat ut proident non voluptate et. Laborum non id voluptate tempor ea anim anim eu irure laborum velit labore ullamco. Non ipsum labore consequat adipisicing amet ut reprehenderit.
To break this down quickly, there’s three properties being used to get this solution - overflow: hidden, text-overflow: ellipsis and white-space: nowrap. white-space: nowrap puts all the text on one line, disregarding the boundaries of the box, text-overflow: ellipsis puts the familiar ’…’ at the end of the text that is visible, and overflow: hidden…well…hides the overflow of the content. Due to this, it only works if you want one line of text, no more. Not ideal.
line-clamp is now supported across all major browsers - Chrome, Firefox, Edge, and Safari. The -webkit-box dependency is still required, but that’s not a reason to avoid it - the co-dependency is fully specified behaviour and isn’t going anywhere.
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
overflow: hidden;
Let’s throw this onto the p tag that’s used here (could also be a modifier on the parent block class if you’re familiar with BEM)
.clamped, /* OR */
.card--clamped p {
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
overflow: hidden;
}
<div class="card">
<img src="https://picsum.photos/550/350" alt="" width="550" height="350" />
<div class="flow">
<h3 class="heading">Card heading</h3>
<p class="clamped">
Laborum sint laborum nostrud est. Est exercitation et occaecat ut proident
non voluptate et. Laborum non id voluptate tempor ea anim anim eu irure
laborum velit labore ullamco. Non ipsum labore consequat adipisicing amet
ut reprehenderit.
</p>
</div>
</div>
We’ve got our display: -webkit-box that we need, and -webkit-line-clamp: 3 to set how many lines we want to keep visible. We still need overflow: hidden otherwise we’ll get a mix of a clamped line with an ellipses and also overflowing content. We’ve been using the -webkit-box-orient: vertical property throughout this post, but it’s an odd one. Technically it’s deprecated, but it’s a required part of using line-clamp and browsers will continue to honour it to make the entire thing work. As of writing this, there’s an unprefixed version of line-clamp in development that drops the -webkit-box entirely, but it’s not Baseline yet. For now, this four-line block is the correct production pattern and safe to ship without a preprocessor or a polyfill.
Card heading
Laborum sint laborum nostrud est. Est exercitation et occaecat ut proident non voluptate et. Laborum non id voluptate tempor ea anim anim eu irure laborum velit labore ullamco. Non ipsum labore consequat adipisicing amet ut reprehenderit.
Sweet 🤘 - that’s one client bug ticket in Trello that can go straight to Done.