क्रॉस-ब्राउज़र मल्टी-लाइन टेक्स्ट ओवरफ्लो के साथ दीर्घवृत्त एक निश्चित चौड़ाई और ऊंचाई के भीतर जोड़ा गया


178

मैंने इस प्रश्न के लिए एक छवि बनाई जिससे इसे समझने में आसानी हो।

क्या <div>एक निश्चित चौड़ाई और कई लाइनों के साथ एक दीर्घवृत्त बनाना संभव है ?

पाठ-अतिप्रवाह

मैं यहाँ और वहाँ से कुछ jQuery प्लगइन्स की कोशिश की है, लेकिन मैं जो देख रहा हूँ वह नहीं मिल सकता है। कोई सिफारिश? विचार?



1
और stackoverflow.com/questions/3922739/… css- केवल समाधान के लिए
एवगेनी

संबंधित लेख css-tricks.com/line-clampin
Adrien Be

2
2016 के मध्य में इसे खोजने वाले किसी भी व्यक्ति के लिए संक्षिप्त उत्तर है: NO यह सुरुचिपूर्ण, क्रॉस ब्राउज़र, CSS केवल तरीके से संभव नहीं है। समाधान के रूप में अक्सर पूरा करने के लिए निकटतम दिया गया है ( codepen.io/romanrudenko/pen/ymHFh ) इतना Goldbergian यह आपके सभी शरीर को चोट पहुंचाता है, और अभी भी काफी बदसूरत है।
कोनराड

जवाबों:


91

बस एक त्वरित मूल विचार है।

मैं निम्नलिखित मार्कअप के साथ परीक्षण कर रहा था:

<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>

और सीएसएस:

#fos { width: 300px; height: 190px; overflow: hidden; }
#fos p { padding: 10px; margin: 0; }

इस jQuery को लागू करने से वांछित परिणाम प्राप्त होगा:

var $p = $('#fos p');
var divh = $('#fos').height();
while ($p.outerHeight() > divh) {
    $p.text(function (index, text) {
        return text.replace(/\W*\s(\S)*$/, '...');
    });
}

यह बार-बार पाठ के अंतिम शब्द को हटाने की कोशिश करता है जब तक कि यह वांछित आकार तक नहीं पहुंच जाता। अतिप्रवाह के कारण: छिपा हुआ; यह प्रक्रिया अदृश्य बनी हुई है और यहां तक ​​कि जेएस बंद होने के बाद भी परिणाम 'नेत्रहीन सही' ("..." के बिना) रहता है।

यदि आप इसे सर्वर-साइड पर एक समझदार ट्रंकेशन के साथ जोड़ते हैं (जो केवल एक छोटा ओवरहेड छोड़ता है) तो यह क्विकली रन करेगा :)।

फिर, यह एक पूर्ण समाधान नहीं है, सिर्फ एक विचार है।

अद्यतन: एक jsFiddle डेमो जोड़ा गया ।


1
महान समाधान @bazmegakapa ... लेकिन मेरे पास कुछ मामले हैं जो मेरे मामले में इसे अनुकूलित करने की कोशिश कर रहे हैं। मेरे पास विभिन्न हैं liऔर हर एक के अंदर एक .blockऔर एक है .block h2और मुझे इसे h2अंदर लागू करने की आवश्यकता है, .blockलेकिन मुझे यह काम करने के लिए नहीं मिला। अगर यह एक से अधिक हैं तो क्या यह कोई भिन्न है .block h2?
एलेक्स

1
मेरे मामले में यह पाठ की सिर्फ 2 पंक्तियों को छोड़ रहा था जब होना चाहिए था 3. स्पष्ट रूप से मेरा कंटेनर height*3कुछ पिक्सेल द्वारा लाइन से छोटा था । आसान फिक्स केवल कुछ पिक्सल जोड़ना हैdivh
लुकास एलटी

3
मुझे इस स्क्रिप्ट के साथ अनंत लूप का एक बुरा अनुभव था क्योंकि पाठ में केवल एक बहुत लंबा शब्द था, इसलिए रीप्जेक्सप कभी भी मेल नहीं खाता। इससे बचने के लिए, whileलाइन के ठीक बाद इस कोड को जोड़ें :if(!$p.text().match(/\W*\s(\S)*$/)) break;
KrisWebDev

1
इस मामले में समस्या होने की संभावना नहीं है, लेकिन डोम को अपडेट करना और लेआउट को बार-बार जांचना एक बुरा विचार है क्योंकि यह धीमा हो सकता है। इसे कम करने के लिए, आप द्विआधारी खोज के समान कुछ कर सकते हैं: यह देखने के लिए परीक्षण करें कि क्या टेक्स्ट ब्लॉक पहले से ही फिट है, अन्यथा पाठ को शब्दों या वर्णों में विभाजित करें और अपनी सीमाएं परिभाषित करें (निचला = 1 शब्द / वर्ण, ऊपरी = सभी शब्द / वर्ण) , while ((upper-lower)>1) {let middle=((lower+upper)/2)|0 /*|0 is quick floor*/; if (test(words.slice(0,middle)+'...')) {lower=middle;} else {upper=middle;}}। जैसा कि @KrisWebDev ने पाया है, आप एक विशाल शब्द की भी जांच करना चाहेंगे।
चिनोटो वोक्रो

1
यह समाधान महान है। मेरे मामले में, मुझे मूल पाठ का ट्रैक रखने की आवश्यकता है ताकि मैं पूरे पाठ मूल्य को जिम्मेदारी से काट सकूं। इसलिए जब पृष्ठ लोड होता है, तो मैं मूल पाठ को एक चर में संग्रहीत करता हूं, और इस तर्क को चलाने से पहले मैं मूल पाठ मान के साथ तत्व को 'रिफ्रेश' करना सुनिश्चित करता हूं। बहस जोड़ें, और यह अद्भुत रूप से काम करता है।
bddrest

68

JQuery.dotdotdot प्लगइन का प्रयास करें ।

$(".ellipsis").dotdotdot();

11
आप उसका उच्चारण कैसे करेंगे? डॉट डॉट-डॉट डॉट?
जैकअस

58
वास्तव में बेकार हो जाता है> एक समस्या को हल करने के लिए js की 600 लाइनें जो सीएसएस द्वारा हल की जानी चाहिए
जेथ्रो लार्सन

मैंने इसकी कोशिश की है, और यह ठीक काम कर रहा है। स्वीकृत उत्तर होना चाहिए
अब्देलहेडी

1
काम करता है, लेकिन सुनिश्चित करें कि window.loaded ईवेंट का उपयोग करें और $ (दस्तावेज़) पहले से ही नहीं है (), क्योंकि फ़ॉन्ट और अन्य बाहरी संसाधन आपके HTML के लेआउट को प्रभावित कर सकते हैं। यदि शोध के संसाधन लोड होने से पहले dotdotdot निष्पादित करते हैं, तो पाठ को सही स्थिति में छोटा नहीं किया जाएगा।
sboisse

10
यह एक वाणिज्यिक उपकरण है, इसमें एक साइट के लिए $ 5 और कई साइटों के लिए $ 35 खर्च होते हैं। लाइसेंस एक दर्द होगा। मैंने सोचा था कि यह मुफ़्त था और तुरंत अप्राप्य था, इसलिए नहीं!
जीन b।

29

"लाइन क्लैंपिंग" के लिए जावास्क्रिप्ट लाइब्रेरी

ध्यान दें कि "लाइन क्लैम्पिंग" को "मल्टी-लाइनों के ब्लॉक पर एलिप्सिस" या "वर्टिकल एलिप्सिस" के रूप में भी संदर्भित किया जाता है।


github.com/BeSite/jQuery.dotdotdot


github.com/josephschmitt/Clamp.js


यहाँ कुछ और हैं जिनकी मैंने अभी तक जाँच नहीं की है:


लाइन क्लैंपिंग के लिए सीएसएस समाधान

कुछ सीएसएस समाधान हैं, लेकिन सबसे सरल उपयोग -webkit-line-clampजिनके पास खराब ब्राउज़र समर्थन हैJsfiddle.net/AdrienBe/jthu55v7/ पर लाइव डेमो देखें

केवल सीएसएस का उपयोग करके ऐसा करने के लिए कई लोग महान प्रयासों में गए। इसके बारे में लेख और प्रश्न देखें:


मैं क्या सुझाऊंगा

इसे सरल रखें। जब तक आपके पास इस सुविधा को समर्पित करने के लिए बहुत समय नहीं है, सरल और परीक्षण किए गए समाधान के लिए जाएं: सरल सीएसएस या एक अच्छी तरह से परीक्षण की गई जावास्क्रिप्ट लाइब्रेरी।

कुछ फैंसी / जटिल / अत्यधिक-अनुकूलित के लिए जाएं और आप इस सड़क के लिए कीमत का भुगतान करेंगे।


दूसरे क्या करते हैं

Airbnb की तरह फीका होने से अच्छा समाधान हो सकता है। यह शायद बेसिक सीएसएस है जो बेसिक jQuery के साथ युग्मित है। दरअसल, यह CSSTricks पर इस समाधान के समान लगता है

AirBnb "अधिक पढ़ें" समाधान

ओह, और यदि आप डिजाइन प्रेरणा की तलाश करते हैं:

  • smashingmagazine.com/2009/07/designing-read-more-and-continue-reading-links/ , 2009 से हालांकि ...
  • ड्रिबल में शायद दिलचस्प डिज़ाइन हैं ... मुझे उन्हें इकट्ठा करने का कोई तरीका नहीं मिला, हालांकि (खोज या टैग के माध्यम से), एक लिंक साझा करने के लिए स्वतंत्र महसूस करें

6

HTML में ऐसी कोई सुविधा नहीं है, और यह बहुत निराशाजनक है।

मैंने इससे निपटने के लिए एक पुस्तकालय विकसित किया है ।

  • बहुस्तरीय पाठ-अतिप्रवाह: दीर्घवृत्त
  • प्रौद्योगिकियों के साथ बहुस्तरीय पाठ जो इसका समर्थन नहीं करता है: उदाहरण के लिए एसवीजी, कैनवस
  • अपने HTML पाठ में, और अपने PDF निर्यात में उदाहरण के लिए, आपके SVG पाठ में ठीक वैसी ही रेखाएँ हैं

स्क्रीनशॉट, ट्यूटोरियल और डाउलोड लिंक के लिए मेरी साइट देखें ।


"db कनेक्शन स्थापित करने में त्रुटि" ... आप हर किसी की तरह करना चाहते हैं और गितुब पर अपनी परियोजना की मेजबानी कर सकते हैं, यह शायद आपके लिए और समुदाय के लिए अच्छा होगा :)
Adrien Be

@ AdrienBe यह Github पर है: github.com/rossille/jstext , और आप सही कह रहे हैं, github मेरी वेबसाइट की तुलना में अधिक स्थिर है, मैं github पृष्ठ को मुख्य लिंक के रूप में सेट करता हूं
Samuel Rossille

@SamuelRossille बड़ी खबर, त्वरित अद्यतन के लिए धन्यवाद!
Adrien Be

4

प्योर जेएस समाधान बाएजमेगाकापा के समाधान पर आधारित है, और कुछ क्लीनअप उन लोगों के लिए खाते हैं जो ऊंचाई / अधिकतम ऊंचाई देने की कोशिश करते हैं जो तत्व की लाइनहाइट से कम है:

  var truncationEl = document.getElementById('truncation-test');
  function calculateTruncation(el) {
    var text;
    while(el.clientHeight < el.scrollHeight) {
      text = el.innerHTML.trim();
      if(text.split(' ').length <= 1) {
        break;
      }
      el.innerHTML = text.replace(/\W*\s(\S)*$/, '...');
    }
  }

  calculateTruncation(truncationEl);

यह बहुत ही अप्रभावी कोड है। जिस तरह से "जबकि" का उपयोग कर अनंत लूप के साथ संभावित बग है।
वेबब्रॉथर

4

मेरे पास एक समाधान है जो अच्छी तरह से काम करता है लेकिन इसके बजाय एक दीर्घवृत्त यह एक ढाल का उपयोग करता है। लाभ यह है कि आपको कोई जावास्क्रिप्ट गणना करने की आवश्यकता नहीं है और यह तालिका कोशिकाओं सहित चर चौड़ाई के कंटेनरों के लिए काम करता है। यह अतिरिक्त divs के एक जोड़े का उपयोग करता है, लेकिन इसे लागू करना बहुत आसान है।

http://salzerdesign.com/blog/?p=453

संपादित करें: क्षमा करें, मुझे नहीं पता था कि लिंक पर्याप्त नहीं था। समाधान यह है कि पाठ के चारों ओर एक div डालें, और ओवरफ्लो को नियंत्रित करने के लिए div को स्टाइल करें। Div के अंदर "फीका" ढाल के साथ एक और div डालते हैं जो CSS या एक छवि (पुराने IE के लिए) का उपयोग करके बनाया जा सकता है। ढाल पारदर्शी से टेबल सेल की पृष्ठभूमि के रंग में जाती है और एक दीर्घवृत्त से थोड़ी व्यापक होती है। यदि पाठ लंबा और ओवरफ्लो होता है, तो यह "फीका" div के तहत जाता है और "फीका आउट" दिखता है। यदि पाठ छोटा है, तो फीका अदृश्य है, इसलिए कोई समस्या नहीं है। दो कंटेनरों को एक या एक से अधिक लाइनों को दिखाने के लिए समायोजित किया जा सकता है कंटेनर की ऊंचाई को कई टेक्स्ट लाइन की ऊंचाई के रूप में सेट करके। "फीका" div को केवल अंतिम पंक्ति को कवर करने के लिए तैनात किया जा सकता है।


कृपया अपने समाधान के महत्वपूर्ण भागों को साझा करें, एसओ लिंक पर केवल उत्तरों की अनुमति नहीं है।
कापा

इसका शानदार पहलू यह है कि पाठ अपने आप छोटा नहीं है, इसलिए यदि उपयोगकर्ता तालिका को कॉपी करता है तो संपूर्ण सामग्री दिखाई देती है।
प्रोटोटाइप

एक बहुत अच्छी अवधारणा। यह इस लेख में भी वर्णित है ("फीका आउट" तरीका) मेरा मानना ​​है कि css-tricks.com/line-clampin
Adrien Be

4

इसे पूरा करने का एक शुद्ध सीएसएस तरीका है: http://www.mobify.com/blog/multiline-ellipsis-in-pure-css/

यहाँ एक सारांश है:

यहां छवि विवरण दर्ज करें

<html>
<head>
<style>
    html, body, p { margin: 0; padding: 0; font-family: sans-serif;}

    .ellipsis {
        overflow: hidden;
        height: 200px;
        line-height: 25px;
        margin: 20px;
        border: 5px solid #AAA; }

    .ellipsis:before {
        content:"";
        float: left;
        width: 5px; height: 200px; }

    .ellipsis > *:first-child {
        float: right;
        width: 100%;
        margin-left: -5px; }        

    .ellipsis:after {
        content: "\02026";  

        box-sizing: content-box;
        -webkit-box-sizing: content-box;
        -moz-box-sizing: content-box;

        float: right; position: relative;
        top: -25px; left: 100%; 
        width: 3em; margin-left: -3em;
        padding-right: 5px;

        text-align: right;

        background: -webkit-gradient(linear, left top, right top,
            from(rgba(255, 255, 255, 0)), to(white), color-stop(50%, white));
        background: -moz-linear-gradient(to right, rgba(255, 255, 255, 0), white 50%, white);           
        background: -o-linear-gradient(to right, rgba(255, 255, 255, 0), white 50%, white);
        background: -ms-linear-gradient(to right, rgba(255, 255, 255, 0), white 50%, white);
        background: linear-gradient(to right, rgba(255, 255, 255, 0), white 50%, white); }
</style>
</head>
<body>
    <div class="ellipsis">
        <div>
            <p>Call me Ishmael.....</p> 
        </div>
    </div>
</body>
</html>

4

आप के -webkit-line-clampसाथ संपत्ति का उपयोग कर सकते हैं div

-webkit-line-clamp: <integer>जिसका अर्थ है कि सामग्री को रौंदने से पहले अधिकतम संख्या निर्धारित करें और फिर (…)अंतिम पंक्ति के अंत में एक दीर्घवृत्त प्रदर्शित करता है ।

div {
  width: 205px;
  height: 40px;
  background-color: gainsboro;
  overflow: hidden;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  
  /* <integer> values */
  -webkit-line-clamp: 2;
}
<div>This is a multi-lines text block, some lines inside the div, while some outside</div>


2
यकीन नहीं होता कि किसी ने इस जवाब को क्यों नकार दिया। मार्च 2020 के रूप में ब्राउज़र समर्थन सुंदर सभ्य है - 95% caniuse.com/#search=line-clamp
Yulian

2

यहां एक वेनिला जावास्क्रिप्ट समाधान है जिसका उपयोग आप चुटकी में कर सकते हैं:

// @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) + '&hellip;';
      ++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>

आप नीचे दिए गए कोडपेन में इसके साथ खेल सकते हैं। सीएसएस पैनल में फ़ॉन्ट का आकार बदलने की कोशिश करें और परिणामों को अपडेट करने के लिए HTML पैनल में एक मामूली संपादन करें (जैसे, एक अतिरिक्त स्थान जोड़ें)। फ़ॉन्ट आकार के बावजूद, मध्य पैराग्राफ को हमेशा सीमा रेखा () () में पारित दूसरे पैरामीटर में लाइनों की संख्या से कम करना चाहिए।

कोडपेन: http://codepen.io/thdoan/pen/BoXbEK


2

संपादित करें: दाढ़ी के पार आया जो कि जेएस प्लगइन है जो कि दिए गए अधिकतम ऊंचाई के आधार पर मल्टी लाइन टेक्स्ट ट्रंकेशन करता है। यह इष्टतम विराम बिंदु खोजने के लिए द्विआधारी खोज का उपयोग करता है। निश्चित रूप से जांच के लायक है।


मूल ANSWER:

मुझे इस समस्या के लिए एक वेनिला जेएस समाधान के साथ आना पड़ा। इस मामले में कि मैंने काम किया था, मुझे एक लंबे उत्पाद के नाम को सीमित चौड़ाई और दो से अधिक लाइनों में फिट करना था; यदि आवश्यक हो तो दीर्घवृत्त द्वारा काट दिया।

मैंने विभिन्न एसओ पदों के जवाबों का उपयोग कुछ ऐसी चीजों को पकाने के लिए किया जो मेरी आवश्यकताओं के अनुरूप हों। रणनीति इस प्रकार है:

  1. वांछित फ़ॉन्ट आकार के लिए फ़ॉन्ट संस्करण की औसत वर्ण चौड़ाई की गणना करें।
  2. कंटेनर की चौड़ाई की गणना करें
  3. कंटेनर में एक पंक्ति पर फिट होने वाले वर्णों की संख्या की गणना करें
  4. एक पंक्ति पर फिट होने वाले वर्णों की संख्या और पाठ को मानने वाली पंक्तियों की संख्या के आधार पर स्ट्रिंग को छोटा करने के लिए वर्णों की संख्या की गणना करें।
  5. पिछली गणना (दीर्घवृत्त द्वारा जोड़े गए अतिरिक्त वर्णों के लिए फैक्टरिंग) और अंत में "..." के आधार पर इनपुट टेक्स्ट को काटें।

कोड नमूना:

/**
 * 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);
.container{
  display: inline-block;
  width: 200px;
  overflow: hidden;
  height: auto;
  border: 1px dotted black;
  padding: 10px;
  }
<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>

पुनश्च:

  1. यदि ट्रंकेशन केवल एक लाइन पर होना है, तो टेक्स्ट-ओवरफ्लो का उपयोग करने का शुद्ध CSS तरीका: ellipsis neater है
  2. जिन फोंटों में निश्चित चौड़ाई नहीं होती है, उनमें कटाव बहुत जल्दी या बहुत देर से हो सकता है (जैसा कि विभिन्न वर्णों की अलग-अलग चौड़ाई होती है)। पैड पैरामीटर का उपयोग करना कुछ मामलों में इसे कम करने में मदद करता है लेकिन यह मूर्खतापूर्ण सबूत नहीं होगा :)
  3. लैपटॉप वापस मिलने के बाद मूल पोस्ट में लिंक और संदर्भ जोड़ दूंगा (इतिहास की आवश्यकता)

PPS: बस एहसास हुआ कि यह @DanMan और @ st.never द्वारा सुझाए गए दृष्टिकोण के समान है। कार्यान्वयन उदाहरण के लिए कोड स्निपेट चेकआउट करें।


2

बहुत ही सरल जावास्क्रिप्ट समाधान। Div को स्टाइल फेल होना चाहिए:

.croppedTexts { 
  max-height: 32px;
  overflow: hidden;
}

और जेएस:

var list = document.body.getElementsByClassName("croppedTexts");
for (var i = 0; i < list.length; i++) {
  cropTextToFit(list[i]);
}

function cropTextToFit (o) {
  var lastIndex;
  var txt = o.innerHTML;
  if (!o.title) o.title = txt;

  while (o.scrollHeight > o.clientHeight) {
    lastIndex = txt.lastIndexOf(" ");
    if (lastIndex == -1) return;
    txt = txt.substring(0, lastIndex);
    o.innerHTML = txt + "…";
  }
}

1

इस प्रश्न का सटीक उत्तर नहीं है, लेकिन मैं इस पृष्ठ पर आया था जब बहुत समान करने की कोशिश कर रहा था, लेकिन केवल एक सीधी दीर्घवृत्त के बजाय "अधिक देखने" के लिए एक लिंक जोड़ना चाहता था। यह एक jQuery फ़ंक्शन है जो एक कंटेनर में अतिप्रवाहित पाठ के लिए "अधिक" लिंक जोड़ देगा। व्यक्तिगत रूप से मैं इसे बूटस्ट्रैप के साथ उपयोग कर रहा हूं, लेकिन निश्चित रूप से यह बिना काम करेगा।

अधिक स्क्रीनशॉट उदाहरण

उपयोग करने के लिए, अपने पाठ को कंटेनर में रखें:

<div class="more-less">
    <div class="more-block">
        <p>The long text goes in here</p>
    </div>
</div>

जब निम्नलिखित jQuery फ़ंक्शन को जोड़ा जाता है, तो किसी भी divs जो एडजस्टमेंट वैल्यू से बड़े होते हैं, उन्हें छोटा कर दिया जाएगा और "अधिक" लिंक जोड़ा जाएगा।

$(function(){
    var adjustheight = 60;
    var moreText = '+ More';
    var lessText = '- Less';
    $(".more-less .more-block").each(function(){
        if ($(this).height() > adjustheight){
            $(this).css('height', adjustheight).css('overflow', 'hidden');
            $(this).parent(".more-less").append
                ('<a style="cursor:pointer" class="adjust">' + moreText + '</a>');
        }
    });
    $(".adjust").click(function() {
        if ($(this).prev().css('overflow') == 'hidden')
        {
            $(this).prev().css('height', 'auto').css('overflow', 'visible');
            $(this).text(lessText);
        }
        else {
            $(this).prev().css('height', adjustheight).css('overflow', 'hidden');
            $(this).text(moreText);
        }
    });
});

इसके आधार पर, लेकिन अपडेट किया गया: http://shakenandstirredweb.com/240/jquery-moreless-text


<sigh> मैंने सोचा कि कोई भी इसे कम कर सकता है, संभवत: क्योंकि यह प्रश्न का सटीक उत्तर नहीं है। फिर भी, मुझे आशा है कि कोई व्यक्ति इसे उपयोगी समझेगा, क्योंकि मैं यह जानकारी कहीं और नहीं कर सकता था और यह वह जगह है जहाँ मैं एक खोज के बाद समाप्त हुआ।
एंडी बेवरली

1

उल्लिखित dotdotdot jQuery प्लगइन कोणीय के साथ अच्छा काम करते हैं:

(function (angular) {
angular.module('app')
    .directive('appEllipsis', [
        "$log", "$timeout", function ($log, $timeout) {
            return {
                restrict: 'A',
                scope: false,
                link: function (scope, element, attrs) {

                    // let the angular data binding run first
                    $timeout(function() {
                        element.dotdotdot({
                            watch: "window"
                        });
                    });
                }
            }

        }
    ]);
})(window.angular);

संबंधित मार्कअप होगा:

<p app-ellipsis>{{ selectedItem.Description }}</p>

1

शुद्ध जेएस डेमो (jQuery के बिना और 'जबकि' लूप)

जब मैंने मल्टीलाइन इलिप्सिस समस्या का हल खोजा तो मुझे आश्चर्य हुआ कि jQuery के बिना कोई भी अच्छा नहीं है। इसके अलावा 'लूप' पर आधारित कुछ समाधान भी हैं, लेकिन मुझे लगता है कि अनंत लूप में आने की संभावना के कारण वे प्रभावी और खतरनाक नहीं हैं। इसलिए मैंने यह कोड लिखा है:

function ellipsizeTextBox(el) {
  if (el.scrollHeight <= el.offsetHeight) {
    return;
  }

  let wordArray = el.innerHTML.split(' ');
  const wordsLength = wordArray.length;
  let activeWord;
  let activePhrase;
  let isEllipsed = false;

  for (let i = 0; i < wordsLength; i++) {
    if (el.scrollHeight > el.offsetHeight) {
      activeWord = wordArray.pop();
      el.innerHTML = activePhrase = wordArray.join(' ');
    } else {
      break;
    }
  }

  let charsArray = activeWord.split('');
  const charsLength = charsArray.length;

  for (let i = 0; i < charsLength; i++) {
    if (el.scrollHeight > el.offsetHeight) {
      charsArray.pop();
      el.innerHTML = activePhrase + ' ' + charsArray.join('')  + '...';
      isEllipsed = true;
    } else {
      break;
    }
  }

  if (!isEllipsed) {
    activePhrase = el.innerHTML;

    let phraseArr = activePhrase.split('');
    phraseArr = phraseArr.slice(0, phraseArr.length - 3)
    el.innerHTML = phraseArr.join('') + '...';
  }
}

let el = document.getElementById('ellipsed');

ellipsizeTextBox(el);

1

हो सकता है कि काफी देर हो गई हो लेकिन SCSS का उपयोग करके आप एक फ़ंक्शन की घोषणा कर सकते हैं जैसे:

@mixin clamp-text($lines, $line-height) {
  overflow: hidden;
  text-overflow: ellipsis;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: $lines;
  line-height: $line-height;
  max-height: unquote('#{$line-height*$lines}em');

  @-moz-document url-prefix() {
    position: relative;
    height: unquote('#{$line-height*$lines}em');

    &::after {
      content: '';
      text-align: right;
      position: absolute;
      bottom: 0;
      right: 0;
      width: 30%;
      height: unquote('#{$line-height}em');
      background: linear-gradient(
        to right,
        rgba(255, 255, 255, 0),
        rgba(255, 255, 255, 1) 50%
      );
    }
  }
}

और इसका उपयोग करें:

.foo {
    @include clamp-text(1, 1.4);
}

जो पाठ को एक पंक्ति में विभाजित कर देगा और यह जानकर कि यह 1.4 है। आउटपुट की उम्मीद क्रोम के साथ ...अंत में प्रस्तुत करना है और एफएफ अंत में कुछ शांत फीका के साथ है

फ़ायरफ़ॉक्स

यहां छवि विवरण दर्ज करें

क्रोम

यहां छवि विवरण दर्ज करें


1

Adrien Be के उत्तर में यह संक्षिप्त CSS-only समाधान मिला :

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

के रूप में मार्च 2020 ब्राउज़र समर्थन है 95.3% , IE और ओपेरा मिनी में नहीं समर्थित होने के नाते। क्रोम, सफारी, फ़ायरफ़ॉक्स और एज पर काम करता है।


0

आप शायद कूरियर की तरह एक निश्चित-चौड़ाई वाले फ़ॉन्ट के बिना इसे (वर्तमान में?) नहीं कर सकते। निश्चित-चौड़ाई वाले फ़ॉन्ट के साथ प्रत्येक अक्षर समान क्षैतिज स्थान पर रहता है, इसलिए आप संभवतः अक्षरों को गिन सकते हैं और परिणाम को वर्तमान फ़ॉन्ट आकार के साथ आठ या एक्सएस में गुणा कर सकते हैं। तब आपको बस यह जांचना होगा कि एक पंक्ति में कितने अक्षर फिट हैं, और फिर इसे तोड़ दें।

वैकल्पिक रूप से, गैर-फिक्स्ड-फोंट के लिए आप सभी संभावित पात्रों (जैसे i = 2px, m = 5px) के लिए मैपिंग बनाने में सक्षम हो सकते हैं और फिर गणित कर सकते हैं। हालांकि बहुत बदसूरत काम करते हैं।


0

@ DanMan के समाधान पर विस्तार करने के लिए: उस मामले में जहां चर-चौड़ाई वाले फ़ॉन्ट का उपयोग किया जाता है, आप औसत फ़ॉन्ट चौड़ाई का उपयोग कर सकते हैं। इसकी दो समस्याएं हैं: 1) बहुत सारे डब्ल्यू के अतिप्रवाह वाला एक पाठ और 2) एक पाठ जिसमें बहुत अधिक मैं पहले से छोटा होगा।

या आप सबसे खराब स्थिति में आ सकते हैं और "W" अक्षर की चौड़ाई का उपयोग कर सकते हैं (जो मेरा मानना ​​है कि सबसे चौड़ा है)। यह समस्या 1 से ऊपर हटाता है लेकिन समस्या 2 को तीव्र करता है।

एक अलग दृष्टिकोण हो सकता है: overflow: clipdiv में छोड़ें और एक दीर्घवृत्त अनुभाग (शायद एक और div या छवि) के साथ जोड़ें float: right; position: relative; bottom: 0px;(अप्रयुक्त)। चाल पाठ के अंत के ऊपर छवि को प्रदर्शित करने के लिए है।

जब आप जानते हैं कि यह अतिप्रवाह करने जा रहा है तो आप केवल छवि प्रदर्शित कर सकते हैं (जैसे, लगभग 100 वर्णों के बाद)


क्या है overflow: clip? और आप उस सीएसएस floatसे क्या करने की उम्मीद करेंगे ?
kapa

0

इस कोड के साथ एक अतिरिक्त आवरण div की आवश्यकता नहीं है यदि तत्व में यह ऊंचाई अधिकतम ऊंचाई शैली द्वारा सीमित है।

// Shorten texts in overflowed paragraphs to emulate Operas text-overflow: -o-ellipsis-lastline
$('.ellipsis-lastline').each(function(i, e) {
    var $e = $(e), original_content = $e.text();
    while (e.scrollHeight > e.clientHeight)
        $e.text($e.text().replace(/\W*\w+\W*$/, '…'));
    $e.attr('data-original-content', original_content);
});

इसके अलावा यह मूल पाठ को एक डेटा विशेषता में बचाता है जिसे केवल शैलियों का उपयोग करके प्रदर्शित किया जा सकता है, जैसे। मूषक के ऊपर से:

.ellipsis-lastline {
    max-height: 5em;
}
.ellipsis-lastline:before {
    content: attr(data-original-content);
    position: absolute;
    display: none;
}
.ellipsis-lastline:hover:before {
    display: block;
}

1
वह अक्सर अनंत लूप होता है।
अत्तजज

0

मेरे परिदृश्य में, मुझे ऊपर बताए गए कार्यों में से कोई भी काम नहीं मिल सकता था और मुझे फंक्शन-आकार या कंटेनर आकार की परवाह किए बिना फ़ंक्शन को यह बताने की आवश्यकता थी कि कितनी लाइनें हैं।

मैं के उपयोग पर मेरी समाधान आधारित Canvas.measureText विधि (जो एक है एचटीएमएल 5 के रूप में समझाया सुविधा) यहाँ से Domi , तो यह पूरी तरह से पार ब्राउज़र नहीं है।

आप देख सकते हैं कि यह इस फिडेल पर कैसे काम करता है ।

यह कोड है:

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>

फ़ॉन्ट-परिवार प्राप्त करने के लिए कोड बल्कि सरल है, और मेरे मामले में काम करता है, लेकिन अधिक जटिल परिदृश्यों के लिए आपको इन पंक्तियों के साथ कुछ का उपयोग करने की आवश्यकता हो सकती है

इसके अलावा, मेरे मामले में मैं फ़ंक्शन को बता रहा हूं कि कितनी लाइनों का उपयोग करना है, लेकिन आप कंटेनर आकार और फ़ॉन्ट के अनुसार कितनी पंक्तियों की गणना कर सकते हैं।


0

मैंने एक संस्करण बनाया है जो html को बरकरार रखता है। jsfiddle उदाहरण

jQuery

function shorten_text_to_parent_size(text_elem) {
  textContainerHeight = text_elem.parent().height();


  while (text_elem.outerHeight(true) > textContainerHeight) {
    text_elem.html(function (index, text) {
      return text.replace(/(?!(<[^>]*>))\W*\s(\S)*$/, '...');
    });

  }
}

$('.ellipsis_multiline').each(function () {
  shorten_text_to_parent_size($(this))
});

सीएसएस

.ellipsis_multiline_box {
  position: relative;
  overflow-y: hidden;
  text-overflow: ellipsis;
}

jsfiddle उदाहरण


0

मैंने एक कोणीय घटक लिखा जो समस्या को हल करता है। यह किसी दिए गए पाठ को स्पैन तत्वों में विभाजित करता है। प्रतिपादन करने के बाद, यह सभी अतिप्रवाह तत्वों को हटा देता है और अंतिम दृश्य तत्व के ठीक बाद एलिप्सिस को रखता है।

उपयोग उदाहरण:

<app-text-overflow-ellipsis [text]="someText" style="max-height: 50px"></app-text-overflow-ellipsis>

Stackblitz डेमो: https://stackblitz.com/edit/angular-wfdqtd

घटक:

import {
  ChangeDetectionStrategy,
  ChangeDetectorRef,
  Component,
  ElementRef, HostListener,
  Input,
  OnChanges,
  ViewChild
} from '@angular/core';

@Component({
  changeDetection: ChangeDetectionStrategy.OnPush,
  selector: 'app-text-overflow-ellipsis',
  template: `
    <span *ngFor="let word of words; let i = index" [innerHTML]="word + (!endsWithHyphen(i) ? ' ' : '')"></span>
    <span #ellipsis [hidden]="!showEllipsis && !initializing" [class.initializing]="initializing" [innerHTML]="'...' + (initializing ? '&nbsp;' : '')"></span>
  `,
  styles: [`
    :host {
      display: block; 
      position: relative;
    }
    .initializing {
      opacity: 0;
    }
  `
  ]
})

export class TextOverflowEllipsisComponent implements OnChanges {
  @Input()
  text: string;

  showEllipsis: boolean;
  initializing: boolean;

  words: string[];

  @ViewChild('ellipsis')
  ellipsisElement: ElementRef;

  constructor(private element: ElementRef, private cdRef: ChangeDetectorRef) {}

  ngOnChanges(){
    this.init();
  }

  @HostListener('window:resize')
  init(){
    // add space after hyphens
    let text = this.text.replace(/-/g, '- ') ;

    this.words = text.split(' ');
    this.initializing = true;
    this.showEllipsis = false;
    this.cdRef.detectChanges();

    setTimeout(() => {
      this.initializing = false;
      let containerElement = this.element.nativeElement;
      let containerWidth = containerElement.clientWidth;
      let wordElements = (<HTMLElement[]>Array.from(containerElement.childNodes)).filter((element) =>
        element.getBoundingClientRect && element !== this.ellipsisElement.nativeElement
      );
      let lines = this.getLines(wordElements, containerWidth);
      let indexOfLastLine = lines.length - 1;
      let lineHeight = this.deductLineHeight(lines);
      if (!lineHeight) {
        return;
      }
      let indexOfLastVisibleLine = Math.floor(containerElement.clientHeight / lineHeight) - 1;

      if (indexOfLastVisibleLine < indexOfLastLine) {

        // remove overflowing lines
        for (let i = indexOfLastLine; i > indexOfLastVisibleLine; i--) {
          for (let j = 0; j < lines[i].length; j++) {
            this.words.splice(-1, 1);
          }
        }

        // make ellipsis fit into last visible line
        let lastVisibleLine = lines[indexOfLastVisibleLine];
        let indexOfLastWord = lastVisibleLine.length - 1;
        let lastVisibleLineWidth = lastVisibleLine.map(
          (element) => element.getBoundingClientRect().width
        ).reduce(
          (width, sum) => width + sum, 0
        );
        let ellipsisWidth = this.ellipsisElement.nativeElement.getBoundingClientRect().width;
        for (let i = indexOfLastWord; lastVisibleLineWidth + ellipsisWidth >= containerWidth; i--) {
          let wordWidth = lastVisibleLine[i].getBoundingClientRect().width;
          lastVisibleLineWidth -= wordWidth;
          this.words.splice(-1, 1);
        }


        this.showEllipsis = true;
      }
      this.cdRef.detectChanges();

      // delay is to prevent from font loading issues
    }, 1000);

  }

  deductLineHeight(lines: HTMLElement[][]): number {
    try {
      let rect0 = lines[0][0].getBoundingClientRect();
      let y0 = rect0['y'] || rect0['top'] || 0;
      let rect1 = lines[1][0].getBoundingClientRect();
      let y1 = rect1['y'] || rect1['top'] || 0;
      let lineHeight = y1 - y0;
      if (lineHeight > 0){
        return lineHeight;
      }
    } catch (e) {}

    return null;
  }

  getLines(nodes: HTMLElement[], clientWidth: number): HTMLElement[][] {
    let lines = [];
    let currentLine = [];
    let currentLineWidth = 0;

    nodes.forEach((node) => {
      if (!node.getBoundingClientRect){
        return;
      }

      let nodeWidth = node.getBoundingClientRect().width;
      if (currentLineWidth + nodeWidth > clientWidth){
        lines.push(currentLine);
        currentLine = [];
        currentLineWidth = 0;
      }
      currentLine.push(node);
      currentLineWidth += nodeWidth;
    });
    lines.push(currentLine);

    return lines;
  }

  endsWithHyphen(index: number): boolean {
    let length = this.words[index].length;
    return this.words[index][length - 1] === '-' && this.words[index + 1] && this.words[index + 1][0];
  }
}

0

यहां मैंने एक और लाइब्रेरी बनाई जिसमें तेज एल्गोरिथ्म था। कृपया जांचें:

https://github.com/i-ahmed-biz/fast-ellipsis

बोवर का उपयोग कर स्थापित करने के लिए:

bower install fast-ellipsis

Npm का उपयोग कर स्थापित करने के लिए:

npm install fast-ellipsis 

उम्मीद करता हु आपको आनंद मिला हो!


-2

सुनिश्चित नहीं है कि यह वही है जो आप खोज रहे हैं, यह ऊंचाई के बजाय न्यूनतम ऊंचाई का उपयोग करता है।

    <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>

4
समस्या आपके कोड में 63 नंबर है, यदि संख्या ज्ञात है, तो सब कुछ आसान हो जाता है, बस एक छोटा कार्य यह कोड आपके कोड के रूप में करता है। हालांकि, संख्या कैसे पता करें? दूसरे शब्दों में, यह कैसे पता चलेगा कि पाठ कहाँ से विखंडित होगा? यदि इस प्रश्न का उत्तर दिया जा सकता है, तो समस्या को "1, 1, 2, ट्रंकट की गणना करें" के तर्क में हल किया जा सकता है
एडवर्ड

-3

बहुत सरल दुर्गंध करेंगे।

निर्देशक:

  $scope.truncateAlbumName = function (name) {
    if (name.length > 36) {
      return name.slice(0, 34) + "..";
    } else {
      return name;
    }
  };

राय:

<#p>{{truncateAlbumName(album.name)}}<#/p>

3
जैसा कि हमने पहले ही अन्य उत्तरों के तहत चर्चा की है, आपके कोड में समस्या 36 नंबर की है। आपके कोड को एक निश्चित कंटेनर चौड़ाई के लिए विशिष्ट बनाने के अलावा, यह भी सटीक नहीं है: निश्चित-चौड़ाई वाले फोंट के साथ नहीं, अक्षरों के बीच बड़े अंतर हो सकते हैं । देखें iiiiiiiiiiबनाम MMMMMMMMMM(वर्तमान फ़ॉन्ट के साथ जो दिखाई नहीं दे रहा है: डी)।
कापा
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.