<div id="content" style="min-height:10px;width:190px;background:lightblue;">
<?php
function truncate($text,$numb) {
// source: www.kigoobe.com, please keep this if you are using the function
$text = html_entity_decode($text, ENT_QUOTES);
if (strlen($text) > $numb) {
$text = substr($text, 0, $numb);
$etc = "...";
$text = $text.$etc;
}
$text = htmlentities($text, ENT_QUOTES);
return $text;
}
echo truncate("this is a multi-lines text block, some lines inside the div, while some outside", 63);
?>
</div>
<div id="fos">
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin nisi ligula, dapibus a volutpat sit amet, mattis et dui. Nunc porttitor accumsan orci id luctus. Phasellus ipsum metus, tincidunt non rhoncus id, dictum a lectus. Nam sed ipsum a lacus sodales eleifend. Vestibulum lorem felis, rhoncus elementum vestibulum eget, dictum ut velit. Nullam venenatis, elit in suscipit imperdiet, orci purus posuere mauris, quis adipiscing ipsum urna ac quam.</p>
</div>
// @param 1 = element containing text to truncate
// @param 2 = the maximum number of lines to show
function limitLines(el, nLines) {
var nHeight,
el2 = el.cloneNode(true);
// Create clone to determine line height
el2.style.position = 'absolute';
el2.style.top = '0';
el2.style.width = '10%';
el2.style.overflow = 'hidden';
el2.style.visibility = 'hidden';
el2.style.whiteSpace = 'nowrap';
el.parentNode.appendChild(el2);
nHeight = (el2.clientHeight+2)*nLines; // Add 2 pixels of slack
// Clean up
el.parentNode.removeChild(el2);
el2 = null;
// Truncate until desired nLines reached
if (el.clientHeight > nHeight) {
var i = 0,
imax = nLines * 35;
while (el.clientHeight > nHeight) {
el.innerHTML = el.textContent.slice(0, -2) + '…';
++i;
// Prevent infinite loop in "print" media query caused by
// Bootstrap 3 CSS: a[href]:after { content:" (" attr(href) ")"; }
if (i===imax) break;
}
}
}
limitLines(document.getElementById('target'), 7);
#test {
width: 320px;
font-size: 18px;
}
<div id="test">
<p>Paragraph 1</p>
<p id="target">Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
<p>Paragraph 3</p>
</div>
您可以在下面的 codepen 中使用它。尝试更改 CSS 面板中的字体大小,并在 HTML 面板中进行小的编辑(例如,在某处添加额外的空间)以更新结果。不管字体大小如何,中间的段落应该总是被截断为第二个参数中传递给 limit Lines ()的行数。
/**
* Helper to get the average width of a character in px
* NOTE: Ensure this is used only AFTER font files are loaded (after page load)
* @param {DOM element} parentElement
* @param {string} fontSize
*/
function getAverageCharacterWidth(parentElement, fontSize) {
var textSample = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890!@#$%^&*()";
parentElement = parentElement || document.body;
fontSize = fontSize || "1rem";
var div = document.createElement('div');
div.style.width = "auto";
div.style.height = "auto";
div.style.fontSize = fontSize;
div.style.whiteSpace = "nowrap";
div.style.position = "absolute";
div.innerHTML = textSample;
parentElement.appendChild(div);
var pixels = Math.ceil((div.clientWidth + 1) / textSample.length);
parentElement.removeChild(div);
return pixels;
}
/**
* Helper to truncate text to fit into a given width over a specified number of lines
* @param {string} text Text to truncate
* @param {string} oneChar Average width of one character in px
* @param {number} pxWidth Width of the container (adjusted for padding)
* @param {number} lineCount Number of lines to span over
* @param {number} pad Adjust this to ensure optimum fit in containers. Use a negative value to Increase length of truncation, positive values to decrease it.
*/
function truncateTextForDisplay(text, oneChar, pxWidth, lineCount, pad) {
var ellipsisPadding = isNaN(pad) ? 0 : pad;
var charsPerLine = Math.floor(pxWidth / oneChar);
var allowedCount = (charsPerLine * (lineCount)) - ellipsisPadding;
return text.substr(0, allowedCount) + "...";
}
//SAMPLE USAGE:
var rawContainer = document.getElementById("raw");
var clipContainer1 = document.getElementById("clip-container-1");
var clipContainer2 = document.getElementById("clip-container-2");
//Get the text to be truncated
var text=rawContainer.innerHTML;
//Find the average width of a character
//Note: Ideally, call getAverageCharacterWidth only once and reuse the value for the same font and font size as this is an expensive DOM operation
var oneChar = getAverageCharacterWidth();
//Get the container width
var pxWidth = clipContainer1.clientWidth;
//Number of lines to span over
var lineCount = 2;
//Truncate without padding
clipContainer1.innerHTML = truncateTextForDisplay(text, oneChar, pxWidth, lineCount);
//Truncate with negative padding value to adjust for particular font and font size
clipContainer2.innerHTML = truncateTextForDisplay(text, oneChar, pxWidth, lineCount,-10);
<h4>Untruncated</h4>
<div id="raw" class="container">
This is super long text which needs to be clipped to the correct length with ellipsis spanning over two lines
</div>
<h4>Truncated</h4>
<div id="clip-container-1" class="container">
</div>
<h4>Truncated with Padding Tweak</h4>
<div id="clip-container-2" class="container">
</div>
附注:
如果截断只在一行上,那么使用 text-overflow: 省略号的纯 CSS 方法更为简洁
没有固定宽度的字体可能会导致截断发生得太早或太晚(因为不同的字符有不同的宽度)。在某些情况下,使用 pad 参数有助于缓解这种情况,但并非万无一失:)
var processTexts = function processTexts($dom) {
var canvas = processTexts .canvas || (processTexts .canvas = document.createElement("canvas"));
$dom.find('.block-with-ellipsis').each(function (idx, ctrl) {
var currentLineAdded = false;
var $this = $(ctrl);
var font = $this.css('font-family').split(",")[0]; //This worked for me so far, but it is not always so easy.
var fontWeight = $(this).css('font-weight');
var fontSize = $(this).css('font-size');
var fullFont = fontWeight + " " + fontSize + " " + font;
// re-use canvas object for better performance
var context = canvas.getContext("2d");
context.font = fullFont;
var widthOfContainer = $this.width();
var text = $.trim(ctrl.innerHTML);
var words = text.split(" ");
var lines = [];
//Number of lines to span over, this could be calculated/obtained some other way.
var lineCount = $this.data('line-count');
var currentLine = words[0];
var processing = "";
var isProcessing = true;
var metrics = context.measureText(text);
var processingWidth = metrics.width;
if (processingWidth > widthOfContainer) {
for (var i = 1; i < words.length && isProcessing; i++) {
currentLineAdded = false;
processing = currentLine + " " + words[i];
metrics = context.measureText(processing);
processingWidth = metrics.width;
if (processingWidth <= widthOfContainer) {
currentLine = processing;
} else {
if (lines.length < lineCount - 1) {
lines.push(currentLine);
currentLine = words[i];
currentLineAdded = true;
} else {
processing = currentLine + "...";
metrics = context.measureText(processing);
processingWidth = metrics.width;
if (processingWidth <= widthOfContainer) {
currentLine = processing;
} else {
currentLine = currentLine.slice(0, -3) + "...";
}
lines.push(currentLine);
isProcessing = false;
currentLineAdded = true;
}
}
}
if (!currentLineAdded)
lines.push(currentLine);
ctrl.innerHTML = lines.join(" ");
}
});
};
(function () {
$(document).ready(function () {
processTexts($(document));
});
})();
使用它的 HTML 应该是这样的:
<div class="block-with-ellipsis" data-line-count="2">
VERY LONG TEXT THAT I WANT TO BREAK IN LINES. VERY LONG TEXT THAT I WANT TO BREAK IN LINES.
</div>
<div>Vel mollis dignissim duis ligula nisl tincidunt eget aliquet eget efficitur quis justo integer pellentesque lacus. Viverra libero viverra finibus. Non id diam lorem ipsum dolor sit amet. Consectetur adipiscing elit sed ac eleifend lorem et placerat. Ante vestibulum. Congue augue vel turpis aliquet. Urna a varius urna convallis sed integer dapibus lobortis enim non venenatis orci varius ut fusce porttitor eros vel. Mollis dignissim duis ligula nisl tincidunt eget aliquet eget efficitur.</div>
Fortunately, the element's height can easily be corrected with a bit of JavaScript.