Подтвердить что ты не робот

Эллипсис в середине текста (стиль Mac)

Мне нужно реализовать эллипсис ("...") в середине текста внутри изменяемого размера элемента. Здесь то, как это могло бы выглядеть. Таким образом,

"Lorem ipsum dolor sit amet. Ut ornare dignissim ligula sed commodo."

становится

"Lorem ipsum dolor sit amet ... commodo."

Когда элемент растягивается до ширины текста, я хочу, чтобы эллипсис исчез. Как это можно сделать?

4b9b3361

Ответ 1

В HTML поместите полное значение в собственный атрибут data- *, например

<span data-original="your string here"></span>

Затем присвойте load и resize прослушиватели событий функции JavaScript, которая будет читать атрибут исходных данных и поместить его в innerHTML вашего тега span. Ниже приведен пример функции многоточия:

function start_and_end(str) {
  if (str.length > 35) {
    return str.substr(0, 20) + '...' + str.substr(str.length-10, str.length);
  }
  return str;
}

Отрегулируйте значения или, если возможно, сделайте их динамическими, если это необходимо для разных объектов. Если у вас есть пользователи из разных браузеров, вы можете украсть ссылочную ширину из текста тем же шрифтом и размером в другом месте вашего дома. Затем интерполируйте соответствующее количество символов для использования.

Совет должен также иметь abbr-тег для... или сообщение, чтобы пользователь мог получить всплывающую подсказку с полной строкой.

<abbr title="simple tool tip">something</abbr>

Ответ 2

Я хотел бы предложить мой пример решения этой проблемы.

Основная идея состоит в том, чтобы разбить текст на две четные части (или первая больше, если длина нечетная), одна из которых имеет многоточие в конце, а другая выровнена по правому краю с text-overflow: clip.

Поэтому все, что вам нужно сделать с js, если вы хотите сделать его автоматическим/универсальным - это разделить строку и установить атрибуты.

У этого есть некоторые недостатки, все же.

  1. Нет приятного переноса словами или даже буквами (text-overflow: '' в данный момент работает только в FF)
  2. Если разделение происходит между словами - пробел должен быть в первой части. В противном случае оно будет свернуто.
  3. Конец строки не должен иметь восклицательных знаков из-за direction: rtl - они будут перемещены влево от строки. Я думаю, это можно исправить, поместив правильную часть слова в тег и восклицательный знак в ::after. Но я еще не сделал это должным образом.

Но, учитывая все это, это выглядит очень круто для меня, особенно когда вы перетаскиваете границу браузера, что вы можете легко сделать на странице jsfiddle: https://jsfiddle.net/extempl/93ymy3oL/. Или просто запустите фрагмент с фиксированной максимальной шириной ниже.

Гиф под спойлер:

Gif

body {
  max-width: 400px;
}

span::before, span::after {
  display: inline-block;
  max-width: 50%;
  overflow: hidden;
  white-space: pre;
}

span::before {
  content: attr(data-content-start);
  text-overflow: ellipsis;
}

span::after {
  content: attr(data-content-end);
  text-overflow: '';
  direction: rtl;
}
<span data-content-start="Look deep into nature, and then you " 
      data-content-end=  "will understand everything better"></span>

<br>
<span data-content-start="https://www.google.com.ua/images/branding/g" 
      data-content-end=  "ooglelogo/2x/googlelogo_color_272x92dp.png"></span>

Ответ 3

Итак, мой коллега придумал решение, в котором нет дополнительных элементов dom. Мы проверяем, переполняется ли div и добавляет атрибут данных последних n символов. Остальное делается в css.

Вот несколько HTML:

<div class="box">
    <div class="ellipsis" data-tail="some">This is my text it is awesome</div>
</div>
<div class="box">
    <div class="ellipsis">This is my text</div>
</div>

И css:

.box {
    width: 200px;
}

.ellipsis:before {
    float: right;
    content: attr(data-tail);
}

.ellipsis {
    white-space: nowrap;
    text-overflow: ellipsis;
    overflow: hidden;
}

Вот обязательный jsfiddle для этого: http://jsfiddle.net/r96vB/1/

Ответ 4

Следующая функция Javascript выполняет среднее усечение, такое как OS X:

function smartTrim(string, maxLength) {
    if (!string) return string;
    if (maxLength < 1) return string;
    if (string.length <= maxLength) return string;
    if (maxLength == 1) return string.substring(0,1) + '...';

    var midpoint = Math.ceil(string.length / 2);
    var toremove = string.length - maxLength;
    var lstrip = Math.ceil(toremove/2);
    var rstrip = toremove - lstrip;
    return string.substring(0, midpoint-lstrip) + '...' 
    + string.substring(midpoint+rstrip);
}       

Он заменит символы в середине на многоточие. Мои юнит-тесты показывают:

var s = '1234567890';
assertEquals(smartTrim(s, -1), '1234567890');
assertEquals(smartTrim(s, 0), '1234567890');
assertEquals(smartTrim(s, 1), '1...');
assertEquals(smartTrim(s, 2), '1...0');
assertEquals(smartTrim(s, 3), '1...90');
assertEquals(smartTrim(s, 4), '12...90');
assertEquals(smartTrim(s, 5), '12...890');
assertEquals(smartTrim(s, 6), '123...890');
assertEquals(smartTrim(s, 7), '123...7890');
assertEquals(smartTrim(s, 8), '1234...7890');
assertEquals(smartTrim(s, 9), '1234...67890');
assertEquals(smartTrim(s, 10), '1234567890');
assertEquals(smartTrim(s, 11), '1234567890');

Ответ 5

Вы не можете сделать это с помощью CSS. Проблема заключается в том, что HTML и CSS должны работать в различных браузерах и шрифтах, и почти невозможно вычислить ширину строки согласованным образом. Это идея, которая может вам помочь. Однако вам нужно будет делать это несколько раз, пока не найдете строку с соответствующей шириной.

Ответ 6

Это может быть немного поздно в игре, но я искал, чтобы найти решение этого, и коллега предложил очень элегантный, который я поделюсь. Это требует некоторых JS, но не много.

Представьте, что у вас есть div размера, необходимого для размещения вашей метки:

<div style="width: 200px; overflow: hidden"></div>

Теперь у вас есть функция, которая примет два параметра: строку с меткой и элемент DOM (этот div), чтобы поместить его в:

function setEllipsisLabel(div, label) 

Первое, что вы делаете, это создать span с этим ярлыком и поместить его в div:

var span = document.createElement('span');
span.appendChild(document.createTextNode(label));
span.style.textOverflow = 'ellipsis';
span.style.display = 'inline-block';
div.appendChild(span);

Мы устанавливаем свойство text-overflow в значение "эллипсис", так что, когда текст отрубается, в конце добавляется приятное "...", чтобы проиллюстрировать это. Мы также устанавливаем display как "встроенный блок", чтобы эти элементы имели реальные размеры пикселей, с которыми мы можем манипулировать позже. До сих пор мы ничего не могли сделать с чистым CSS.

Но мы хотим, чтобы эллипсис посередине. Во-первых, мы должны выяснить, нужна ли нам вообще... Это можно сделать, сравнивая div.clientWidth с span.clientWidth - эллипсис необходим, только если span шире div.

Если нам понадобится многоточие, начнем с того, что мы хотим, чтобы фиксированное количество символов было показано в конце слова - скажем 10. Итак, давайте создадим пролет, содержащий только последние 10 символов метки, и придерживаемся он в div:

var endSpan = document.createElement('span');
endSpan.style.display = 'inline-block';
endspan.appendChild(document.createTextNode(label.substring(label.length - 10)));
div.appendChild(endSpan);

Теперь переопределите ширину оригинала span для размещения нового:

span.style.width = (div.clientWidth - endSpan.clientWidth) + 'px';

В результате этого у нас теперь есть структура DOM, которая выглядит примерно так:

<div style="width: 200px; overflow: hidden">
   <span style="display: inline-block; text-overflow: ellipsis; width: 100px">
      A really long label is shown in this span
   </span>
   <span style="display: inline-block"> this span</span>
</div>

Поскольку первый span имеет text-overflow, установленный на "эллипсис", он будет показывать "..." в конце, а затем 10 символов второго пролета, в результате чего многоточие отображается примерно в середине div.

Вам также не нужно жестко кодировать длину символа 10 для endSpan: это может быть аппроксимировано путем вычисления отношения начальной ширины span к значению div, вычитая соответствующую пропорцию из длины метки и деления на два.

Ответ 7

После некоторого исследования на flex-коробках я нашел это чистое решение для CSS, которое, я считаю, довольно круто.

<div style="width:100%;border:1px solid green;display:inline-flex;flex-wrap:nowrap;">
   <div style="flex: 0 1 content;text-overflow: ellipsis;overflow:hidden;white-space:nowrap;"> Her comes very very very very very very very very very very very very very very very very very very very long </div>
   <div style="flex: 1 0 content;white-space:nowrap;"> &nbsp;but flexible line</div>
</div>

Ответ 8

Здесь самый короткий бит, который я мог найти, который заменяет 3 символа посередине....

function shorten(s, max) {
  return s.length > max ? s.substring(0, (max / 2) - 1) + '...' + s.substring(s.length - (max / 2) + 2, s.length) : s
}

Ответ 9

Я только что создал функцию, которая может обрезать в середине, nearEnd и End, но havent была проверена еще, потому что я, наконец, нуждался в ней на стороне сервера

//position acceptable values : middle, end, closeEnd
function AddElipsis(input, maxChars, position) {
    if (typeof input === 'undefined') {
        return "";
    }
    else if (input.length <= maxChars) {
        return input;
    }
    else {
        if (position == 'middle') {
            var midPos = Math.floor(maxChars / 2) - 2;
            return input.substr(0, midPos) + '...' + input.substr(input.length - midPos, input.length);
        }
        else if (position == 'closeEnd') {
            var firstPart = Math.floor(maxChars * 0.80) - 2;
            var endPart = Math.floor(maxChars * 0.20) - 2;
            return input.substr(0, firstPart) + '...' + input.substr(input.length - endPart, input.length);
        }
        else {
            return input.substr(0, maxChars - 3) + '...';
        }
    }
}

Ответ 10

Еще один удар:

function truncate( str, max, sep ) {
    max = max || 10;
    var len = str.length;
    if(len > max){
        sep = sep || "...";
        var seplen = sep.length;
        if(seplen > max) { return str.substr(len - max) }

        var n = -0.5 * (max - len - seplen);
        var center = len/2;
        return str.substr(0, center - n) + sep + str.substr(len - center + n);
    }
    return str;
}

console.log( truncate("123456789abcde") ); // 123...bcde (using built-in defaults) 
console.log( truncate("123456789abcde", 8) ); // 12...cde (max of 8 characters) 
console.log( truncate("123456789abcde", 12, "_") ); // 12345_9abcde (customize the separator) 

Ответ 11

Это даст вам немного больше контроля над положением многоточия и текста заполнителя:

function ellipsis(str, maxLength, ellipsisLocationPercentage,placeholder) {
    /*
    ARGUMENTS:
    str - the string you want to maninpulate
    maxLength -  max number of characters allowed in return string
    ellipsisLocationPercentage (optional) - How far (percentage wise) into the return string you want the ellipses to be placed
        Examples:
        .85 : This is a very long string. This is a very long string. This is a very long string. This is a ver[...]very long string.
        .25 : This is a very long string. [...]g. This is a very long string. This is a very long string. This is a very long string.
    placeholder (optional) - this will be used to replace the removed substring. Suggestions : '...', '[..]', '[ ... ]', etc....
    */
    if(ellipsisLocationPercentage == null || isNaN(ellipsisLocationPercentage) || ellipsisLocationPercentage >= 1 || ellipsisLocationPercentage <= 0){
        //we've got null or bad data.. default to something fun, like 85% (that fun, right??)
        ellipsisLocationPercentage = .85;
    }
    if(placeholder == null || placeholder ==""){
        placeholder = "[...]";
    }

    if (str.length > (maxLength-placeholder.length)) {
        //get the end of the string
        var beginning = str.substr(0, (maxLength - placeholder.length)*ellipsisLocationPercentage );
        var end = str.substr(str.length-(maxLength - placeholder.length) * (1-ellipsisLocationPercentage));
        return beginning + placeholder + end;
    }
    return str;
}

Вы можете вызвать эту функцию, вызвав:

ellipsis("This is a very long string. Be Scared!!!!", 8);//uses default values
ellipsis("This is a very long string. Be Scared!!!!", 8,.5);//puts ellipsis at half way point
ellipsis("This is a very long string. Be Scared!!!!", 8,.75,'<..>');//puts ellipsis at 75% of the way into the string and uses '<..>' as the placeholder

Ответ 12

Чтобы сделать чистый разрез и иметь целое слово в конце сокращенного текста, я использовал следующую функцию.

function prepareText(text){
  var returnString = text;
  var textLimit = 35;
  if(text.length > textLimit){
    var lastWord = text.slice( text.lastIndexOf(' ')+1 );
    var indexFromEnd = lastWord.length;
    var ellipsis = '... ';

    returnString = text.slice(0, textLimit - indexFromEnd - ellipsis.length);
    returnString = returnString + ellipsis + lastWord;
  }
  return returnString;
}

$('#ex1Modified').html( prepareText( $('#ex1').html() ) );

$('#ex2Modified').html( prepareText( $('#ex2').html() ) );

$('#ex3Modified').html( prepareText( $('#ex3').html() ) );
body{color:#777; font-family: sans-serif;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<h2>Shortened Quotes from Albert Einstein</h2>

<div id="ex1">"The true sign of intelligence is not knowledge but imagination."</div>
<div id="ex1Modified"></div>
<br>
<div id="ex2">"Look deep into nature, and then you will understand everything better."</div>
<div id="ex2Modified"></div>
<br>
<div id="ex3">"You can't blame gravity for falling in love."</div>
<div id="ex3Modified"></div>

Ответ 13

Это решение представляет собой смесь вышеуказанных решений и помещает последнее целое слово в конце сокращенного текста. Однако, если последнее слово длиннее трети доступного пространства, оно также сокращается слева. Если черта ("-") найдена, отрежьте ее там, если нет, отрежьте ее в любом случае.

function truncate(text, textLimit) {
    if (!text) return text;
    if (textLimit < 1) return string;
    if (text.length < textLimit) return text;
    if (textLimit === 1) return text.substring(0,1) + '...';
    /* extract the last word */
    var lastPart = text.slice( string.lastIndexOf(' ')+1 );
    /* if last word is longer then a third of the max available space
       cut it from the left */
    var lastPartLimit = Math.ceil(textLimit / 3);
    if(lastPart.length > lastPartLimit) {
        var truncatedLastPart = lastPart;
        /* Try to find a dash and cut the last word there */
        var lastDashPart = text.slice( text.lastIndexOf('-')+1 );
        if(lastDashPart.length < lastPartLimit){
            truncatedLastPart = lastDashPart;
        }
        /* If the last part is still to long or not available cut it anyway */
        if(truncatedLastPart.length > lastPartLimit) {
            var lastIndex = lastPart.length - lastPartLimit;
            truncatedLastPart = lastPart.substring( lastIndex );
        }
        lastPart = truncatedLastPart;
    }
    var dots = '... ';
    var firsPartLength = textLimit - lastPart.length - dots.length;
    return text.substring(0, firstPartLength) + dots + lastPart;
}

console.log( truncate("New York City", 10) ); // Ne... City (max of 10 characters)
console.log( truncate("New York Kindergarden", 14) ); // Ne...ergarden (max of 14 characters, last word gets cut from the left by a third)
console.log( truncate("New York Kinder-garden", 14) ); // Ne...garden (max of 14 characters, last word gets cut by the dash from the left)