Inline View More: A Better Text Truncation Pattern

Inline View More: A Better Text Truncation Pattern


Inline View More: A Better Text Truncation Pattern

We've all seen the classic "View More" button—sitting awkwardly below truncated text, taking up extra vertical space, and breaking the visual flow. There's a better way.

The Problem with Traditional Truncation

Most implementations look like this:

This is a long piece of text that gets cut off after
a certain number of lines and then you see...

[View More]

The button sits on its own line. It's clunky. It adds unnecessary height to your UI, especially problematic in data-dense interfaces like tables, approval workflows, or history logs.

The Inline Pattern

What if "View More" appeared inside the text, right where the ellipsis would be?

This is a long piece of text that gets cut off... View More

When expanded:

This is a long piece of text that gets cut off after a certain 
number of lines. Now you can see the full content without any 
awkward layout shifts. View Less

No extra rows. No layout jumps. Just seamless expansion in place.

Live Demo

Live Demo

How It Works

The trick is using CSS pseudo-elements (::before and ::after) to overlay the "View More" text at the exact truncation point and on top of it add few tweaks with Javascript.

Core CSS

.truncated-text {
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
  position: relative;
}

.truncated-text.show-more::after {
  content: " ... View More";
  position: absolute;
  right: 0;
  bottom: 0;
  background: white;
  color: var(--primary-color);
  cursor: pointer;
}

.truncated-text.expanded {
  -webkit-line-clamp: unset;
  overflow: visible;
}

.truncated-text.expanded::after {
  content: " View Less";
  position: static;
}

The White Background Trick

The background: white on the pseudo-element covers the truncated text underneath. For extra polish, use a ::before as a mask layer:

.truncated-text.show-more::before {
  content: " ... View More";
  position: absolute;
  right: 0;
  bottom: 0;
  background: white;
  color: transparent; /* invisible mask */
  z-index: 1;
}

.truncated-text.show-more::after {
  /* same positioning, visible */
  z-index: 2;
}

Detecting Overflow

Only add "View More" to text that actually overflows:

function checkOverflow(element) {
  if (element.scrollHeight > element.clientHeight) {
    element.classList.add('show-more');
  } else {
    element.classList.remove('show-more');
  }
}

Toggle Logic

function toggle(element) {
  const isExpanded = element.classList.toggle('expanded');
  element.classList.toggle('show-more', !isExpanded);
  element.setAttribute('aria-expanded', isExpanded);
}

Accessibility

<span class="truncated-text"
      role="button"
      tabindex="0"
      aria-expanded="false"
      onclick="toggle(this)"
      onkeydown="if (event.key === 'Enter' || event.key === ' ') toggle(this)">
  Your long text here...
</span>

Responsive Considerations

@media (max-width: 768px) {
  .truncated-text {
    -webkit-line-clamp: 2;
  }
}

Re-check overflow on resize:

window.addEventListener('resize', () => {
  document.querySelectorAll('.truncated-text').forEach(checkOverflow);
});

Gotchas

  1. Background color must match - Pseudo-element needs same background as container
  2. -webkit-line-clamp support - Works in all modern browsers
  3. Dynamic content - Re-run overflow detection when content changes
  4. RTL languages - Position pseudo-elements on the left

Wrapping Up

Small UI details compound. An inline "View More" removes friction—one less layout jump, one less awkward button, one more polished interaction.

The best UI patterns are the ones users don't notice. They just work.