I got used to Gatsby providing Excerpts from GraphQL. Many CMS do the same. However, I recently converted my Gatsby site to Astro and want this functionality back. A LogRocket article has some techniques to accomplish this. For this article, I will create a Codepen based on that article so I can easily reference it in the future.
Ideally, I want a solution to be as simple as possible. A pure CSS solution would is preferred. A bit of Javascript is the next best option. I would rather not have to pull in a library but let’s look at the trade-offs.
To truncate a single line, just add this class.
.single-line-css {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
This solution falls short since it only works for a single line and doesn’t respect work boundaries.
.multi-line-css {
overflow: hidden;
text-overflow: ellipsis;
max-height: 2rem;
line-height: 1rem;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
text-overflow: ellipsis;
display: block;
}
This solution is closer, but the ellipsis is missing.
It looks like we need to reach for Javascript.
function truncate(words, maxlength) {
return `${words.slice(0, maxlength)} …`;
}
const excerptElement = document.getElementById('js-excerpt')
const excerpt = excerptElement.innerText
excerptElement.innerText = truncate(excerpt, 200)
This solution is close, but I want to split on a word boundary. We can fix that with a bit more complicated javascript.
function smartTruncate(words, maxlength) {
if (words.length <= maxlength) {
return words;
}
if (/\s/.test(words[maxlength])) {
return `${words.slice(0, maxlength)} …`;
}
const positionOfLastWhiteSpace = words.slice(0, maxlength).search(/ [^ ]*$/);
return `${words.slice(0, positionOfLastWhiteSpace)} …`;
}