I'm working on a template in Craft 2, and I have a number of divs which are part of a Javascript "read more" script, which automatically shortens the visible text at a set number of characters and then adds a "read more" link. I have added the Javascript in the page template, but the entire text of the div displays briefly before the page loads completely. I have a Javascript to hide the text until page load (below), but the text is still briefly visible. It was successful in my non-Craft test, however, with the text never visible on page load. In the meantime, I've had to resort to a seemingly redundant default style of display:none style for .post . With that style in place, the page does load correctly. Is this a problem having to do with positioning within the template?

I've tried to position the Javascripts above and below {% extends "_layout" %} to no effect.

{% set myJs4 %}
// Set the display property of the element to none using CSS
var divsToHide = document.getElementsByClassName("post");        
//divsToHide is an array
    for(var i = 0; i < divsToHide.length; i++){
        divsToHide[i].style.display = "none"; 

// Remove the display property after the page loads using the DOMContentLoaded event
document.addEventListener("DOMContentLoaded", function() {
var divsToShow = document.getElementsByClassName("post"); 
//divsToShow is an array
    for(var i = 0; i < divsToShow.length; i++){
        divsToShow[i].style.display = "block"; 
{% includeJs myJs4 %}

And then,

2 Answers 2


What you are seeing is the page being rendered with HTML and CSS first. This is the part where the text is completely visible. After a second the Javascript is executed which shortens the texts.

I would not use Javascript for this. There are other ways to handle it:

  • Shorten the text server side and show the complete text when the "read more" button is clicked. You can either render the complete text server side along with the shorter text but put a display none property on it inline. On click you can remove the display property. Or fetch the content with Javascript on click from the server.
  • Use CSS to put a max-height property on the text container along with overflow hidden. Note that this still won't completely fix your issue because CSS is loaded after HTML so there will still be layout shift but much less noticable. I'm also guessing this is not the design you want to achieve.

I think option 1 is the best choice here.

  • If I used an all Twig solution, like with slice (I'm not sure if the truncate filter works in Craft 2), how would I go about revealing all of the text on click? I got this far in hiding part of the text, greater than 50 characters: {{ myText|length > 50 ? myText|slice(0, 51)|split(' ')|slice(0, -1)|join(' ') ~ '…' : myText }} Or, assign 2 different variables and hide one/show the other on click?
    – buck1112
    Sep 19, 2023 at 20:14
  • 1
    Correct. In this specific case I would render the same text twice. Once for the trimmed version and once for the full version. Then just toggle the visibility of both. One can only be visible is the other one is hidden. If you want to prevent the full text from flashing when loading the page you can set display none on the element inline. I know it seems a bit crappy to do this inline but it's the only way to make sure it will get loaded at the same time as the template. Performance is key here.
    – Matthias
    Sep 19, 2023 at 20:31

I have a number of divs which are part of a Javascript "read more" script…

For a readmore?? Why not just use the truncate filter?

<p>{{ entry.intro|truncate(10, '…') }}</p>

<a href="{{ entry.url }}">Read more…</a>

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.