I am trying to find a method that reduces a text HTML
until it does not exceed the size of its container with overflow
hidden
. The text can have different fonts, letter sizes or line height, so it is very likely that the last line is cut in half, this is what I want to avoid. I found this question , but the solution is made to handle only special characters like these <>&
. I've also found this one but it's too complicated and it does not work very well when the HTML
is Too complex. Some solutions are only for WebKit or do not work efficiently with any type of text.
Here I leave the code that I have made so far (it is as ineffective as the previous ones that I have found), I have only placed it to make it clear that I have been working on it and I have not come looking for an answer without having thought about it a lot. I do not want this code to be revised but only to see what path I have taken. This code is capable of doing more than 1000 iterations and take several seconds depending on the HTML and the length of it and taking into account that in my application the container will change size very often this code would make it unusable.
Does anyone know of any quick and effective method to achieve this?
NOTE: My texts
HTML
only containTEXT_NODEs
andELEMENT_NODEs
(excludingscripts
andstyles
), I do not need to handle other types of nodes at the moment. p>
function reduceHTMLText (container) {
var longer = false;
var reg = /^([\s\S]+?)\s*\.+$/;
var regpunt = /^(.*?)[,;\:\.]$/;
var isOverflow = function () {
return container.scrollHeight > container.clientHeight;
};
var reduce = function (element) {
var nodes = element.childNodes;
if (nodes.length === 0) {
longer = isOverflow();
if (longer) { reduce(container); }
return;
}
var last = nodes[nodes.length - 1];
//---Depend of the node type
switch (last.nodeType) {
//---If the node is a text
case 3:
var str = last.data.replace(reg, "$1");
var words = str.split(" ");
//---If the words array has more than five words
if (words.length > 5) {
words = words.slice(0, -5);
words[words.length - 1] = words[words.length - 1].replace(regpunt, "$1");
last.data = words.join(" ") + "...";
} else {
last.parentNode.removeChild(last);
}
longer = isOverflow();
if (longer) { reduce(element); }
break;
//---If the node is an element node
case 1:
if (last.childNodes.length) {
reduce(last);
} else {
last.parentNode.removeChild(last);
longer = isOverflow();
if (longer) { reduce(element); }
}
break;
}
};
longer = isOverflow();
if (longer) { reduce(container); }
}
var container = document.querySelector(".container");
reduceHTMLText(container);
.container {
background-color: #EEE;
height: 170px;
overflow: hidden;
width: 500px;
}
<div class="container">
<p style="text-align: left;">
Vestibulum imperdiet ipsum nec urna ornare, quis malesuada odio viverra. Etiam mollis dolor lacus, ac cursus leo aliquam ut. Etiam eu elit in <strong>massa egestas <em>interdum ut</em> vel magna</strong>. Suspendisse nisl velit, bibendum id hendrerit at, maximus vitae neque. Integer varius sed ante quis porta. Aenean venenatis pellentesque semper. Etiam a quam ut mauris imperdiet vehicula tristique id lacus. <a href='#'>Aliquam lacus metus, mattis a viverra a, <strong>convallis sit amet diam</strong>. In dignissim lorem</a> sit amet, consectetur adipiscing elit. Cras non sem laoreet, tristique felis id, fringilla mi. Fusce sit amet iaculis enim. In malesuada risus eu urna interdum gravida. <strong>Praesent malesuada felis et mi gravida</strong>, at <em>interdum nunc sollicitudin. Quisque <strong>ultrices nibh</strong> in malesuada tempus</em>. Donec tempus efficitur maximus. Praesent ac lacinia odio. Maecenas vel nunc condimentum, luctus diam ac, molestie purus. Cras non tempor magna. Nulla et eros in nunc iaculis eleifend vel at nisi. <strong>Castro pero normal</strong> Aenean quis ultricies arcu, non volutpat neque. Aliquam at justo sed nisi malesuada lobortis eu ut risus. Fusce at enim quis dolor dignissim gravida vel a felis <span class="soleil-label">text paloma samona</span> is cube rubick <a href="http://google.com">because is impossible to</a> mantain the text in a long way.
</p>
<p style="text-align: center;">
<div class='special'>
<span class="soleil-cta-button-pink">
<a href="http://google.com" class="soleil-cta-button-pink">NO REGRETS</a>
</span>
</div>
</p>
</div>