How to dynamically truncate text in Shopify Liquid?

I’m developing a custom Shopify theme and need help with text truncation. My goal is to display product titles and descriptions in boxes with equal character counts.

Here’s what I’m trying to do:

  1. Add up the characters in the title and description
  2. Subtract this total from 200
  3. Use the result to truncate the description

I’ve written some Liquid code, but it’s not working as expected:

{% capture char_limit %}
{{ product.title.size | plus: product.description.size | minus: 200 }}
{% endcapture %}

<p>{{ product.description | strip_html | replace: '&nbsp;', ' ' | truncate: char_limit }}</p>

The capture part seems to work fine, but the truncate filter doesn’t accept the variable. Am I missing something? How can I make this work?

I’ve faced a similar challenge when working on a Shopify theme. The issue you’re encountering is because Liquid’s truncate filter expects a number, not a string. Here’s a workaround I’ve used:

Instead of capturing the character limit, try using the assign tag to create a variable. Then, use the minus filter directly in the truncate operation. Something like this:

{% assign total_chars = product.title.size | plus: product.description.size %}
{% assign remaining_chars = 200 | minus: total_chars %}

{{ product.description | strip_html | replace: ' ', ' ' | truncate: remaining_chars }}

This approach should work for dynamically truncating the text based on your criteria. Remember to adjust the ‘200’ value if you want a different total character count.

Also, consider adding a fallback in case the calculation results in a negative number, which could happen with very long titles. You might use an if statement to set a minimum truncation length.

I’ve encountered this issue before, and there’s a simple solution. The problem lies in how Liquid handles variables in filters. Instead of using capture, try using assign to create your variable:

{% assign char_limit = product.title.size | plus: product.description.size | minus: 200 %}

{{ product.description | strip_html | replace: ' ', ' ' | truncate: char_limit }}

This should work as expected. However, be cautious with very short descriptions or long titles, as you might end up with negative numbers. To prevent this, you could add a safeguard:

{% assign char_limit = product.title.size | plus: product.description.size | minus: 200 | at_least: 10 %}

This ensures you always have at least 10 characters to display. Adjust as needed for your specific design requirements.