Многоточие в середине текста (стиль Mac)

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

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

становится

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

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

12 ответов


в 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;
}

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

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

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

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

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

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

он имеет некоторые недостатки.

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

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

Gif под спойлером:

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: clip;
  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>

Итак, мой коллега придумал решение, которое не использует дополнительных элементов 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/


следующая функция 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');

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


это может быть немного поздно в игре, но я искал решение этого, и коллега предложил очень элегантный, который я поделюсь. Это требует некоторого 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 to 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's начальная ширина к тому из div, вычитание соответствующей пропорции из длины этикетки и деление на два.


после некоторых исследований на гибких коробках я нашел это чистое решение 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>

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

//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) + '...';
        }
    }
}

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

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) 

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

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

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

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>

вот самый короткий бит, который я мог найти, который заменяет 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
}