Как не дать длинным словам сломать мой div? - PullRequest
146 голосов
/ 26 ноября 2008

После перехода с TABLE-макета на DIV-макет остается одна общая проблема:

ПРОБЛЕМА : вы заполняете свой DIV динамическим текстом, и неизбежно появляется сверхдлинное слово, которое простирается через край столбца div и делает ваш сайт непрофессиональным.

RETRO-WHINING : Это никогда не происходило с макетами таблиц. Ячейка таблицы всегда будет расширяться до ширины самого длинного слова.

SEVERITY : я вижу эту проблему даже на самых крупных сайтах, особенно на немецких сайтах, где даже такие распространенные слова, как «ограничение скорости», очень длинные («Geschwindigkeitsbegrenzung»).

У кого-нибудь есть работоспособное решение этой проблемы?

Ответы [ 26 ]

4 голосов
/ 28 июня 2011

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

Наше решение состояло в том, чтобы сначала использовать замену регулярных выражений, чтобы поставить пробел нулевой ширины () после каждых 15 (скажем) символов, которые не являются пробелами или одним из специальных символов, где мы бы предпочли разрывы. Затем мы делаем другую замену, чтобы поставить пробел нулевой ширины после этих специальных символов.

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

В настоящее время используются специальные символы разрыва: точка, косая черта, обратная косая черта, запятая, подчеркивание, @, | и дефис. Вы бы не подумали, что вам нужно что-то делать, чтобы поощрять разрывы после дефисов, но Firefox (по крайней мере, 3.6 и 4) не разрывается сам по себе в дефисах, окруженных номерами (например, номерами телефонов).

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

Вот код; вы, вероятно, назвали бы пространство функций в пакете утилит:

makeWrappable = function(str, position)
{
    if (!str)
        return '';
    position = position || 15; // default to breaking after 15 chars
    // matches every requested number of chars that's not whitespace or one of the special chars defined below
    var longRunsRegex = cachedRegex('([^\\s\\.\/\\,_@\\|-]{' + position + '})(?=[^\\s\\.\/\\,_@\\|-])', 'g');
    return str
                .replace(longRunsRegex, '$1​') // put a zero-width space every requested number of chars that's not whitespace or a special char
                .replace(makeWrappable.SPECIAL_CHARS_REGEX, '$1​'); // and one after special chars we want to allow breaking after
};
makeWrappable.SPECIAL_CHARS_REGEX = /([\.\/\\,_@\|-])/g; // period, forward slash, backslash, comma, underscore, @, |, hyphen


cachedRegex = function(reString, reFlags)
{
    var key = reString + (reFlags ? ':::' + reFlags : '');
    if (!cachedRegex.cache[key])
        cachedRegex.cache[key] = new RegExp(reString, reFlags);
    return cachedRegex.cache[key];
};
cachedRegex.cache = {};

Тест, подобный этому:

makeWrappable('12345678901234567890 12345678901234567890 1234567890/1234567890')

Обновление 2: Похоже, что пробелы нулевой ширины на самом деле включены в скопированный текст по крайней мере в некоторых обстоятельствах, вы просто не можете их видеть. Очевидно, что поощрение людей к копированию текста со скрытыми символами в нем - это приглашение к вводу подобных данных в другие программы или системы, даже в ваши собственные, где это может вызвать проблемы. Например, если он попадает в базу данных, поиск по нему может завершиться неудачно, и такие строки поиска, скорее всего, тоже потерпят неудачу. Использование клавиш со стрелками для перемещения по таким данным требует (справедливо) дополнительного нажатия клавиши для перемещения по символу, который вы не видите, для пользователей это несколько странно, если они заметят.

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

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

Обновление 3: Наличие этого символа в данных больше не является теоретической возможностью, это наблюдаемая проблема. Пользователи отправляют данные, скопированные с экрана, они сохраняются в БД, поиск прерывается, все странно сортируется и т. Д.

Мы сделали две вещи:

  1. Написал утилиту для удаления их из всех столбцов всех таблиц во всех источниках данных для этого приложения.
  2. Добавлена ​​фильтрация для удаления его в нашем стандартном процессоре ввода строк, так что он исчезает к тому времени, когда код его видит.

Это работает хорошо, как и сама техника, но это предостерегающая история.

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

Исправлено добавление амперсанда в список символов, над которыми мы не разбиваемся, например:

var longRunsRegex = cachedRegex('([^&\\s\\.\/\\,_@\\|-]{' + position + '})(?=[^&\\s\\.\/\\,_@\\|-])', 'g');
4 голосов
/ 26 ноября 2008

Решение, которое я обычно использую для этой проблемы, состоит в том, чтобы установить 2 различных правила CSS для IE и других браузеров:

word-wrap: break-word;

отлично работает в IE, но перенос слов не является стандартным свойством CSS. Это свойство Microsoft и не работает в Firefox.

Для Firefox лучше всего использовать только CSS, чтобы установить правило

overflow: hidden;

для элемента, содержащего текст, который вы хотите обернуть. Текст не переносится, но скрывает часть текста, которая выходит за пределы контейнера . Это может быть хорошим решением, если вам не нужно отображать весь текст (т.е. если текст находится внутри тега <a>)

4 голосов
/ 10 июня 2011

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

Например, это:

'abcde12345678901234'.replace(/([^\s-]{5})([^\s-]{5})/g, '$1&shy;$2')

... приводит к этому:

abcde&shy;12345678901234

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

.replace(/([^\s-]{5})(?=[^\s-])/g, '$1&shy;')

... с таким результатом:

abcde&shy;12345&shy;67890&shy;1234
3 голосов
/ 11 августа 2010

Необходимо установить «макет таблицы: исправлено» для работы с переносом слов

2 голосов
/ 07 января 2016

Используйте это

word-wrap: break-word;
overflow-wrap: break-word;
word-break: break-all;
2 голосов
/ 13 июля 2013

Для совместимости с IE 8+ используйте:

-ms-word-break: break-all;
     word-break: break-all;

     /* Non standard for webkit */
     word-break: break-word;

-webkit-hyphens: auto;
   -moz-hyphens: auto;
        hyphens: auto;

См. Здесь http://css -tricks.com / snippets / css / предотвращение выхода из контейнера длинных URL-адресов /

Все, что мне нужно было сделать, это применить это к стилю контейнера div с заданной шириной.

2 голосов
/ 26 ноября 2008

ГИФЕНАТОР - правильный ответ (приведенный выше). Настоящая проблема, стоящая за вашим вопросом, заключается в том, что веб-браузеры по-прежнему (в 2008 году) крайне примитивны, поскольку у них нет функции переноса слов. Послушайте, мы все еще находимся на ранних этапах использования компьютера - мы должны быть терпеливыми. Пока дизайнеры правят веб-миром, нам будет трудно ждать каких-то действительно полезных новых функций.

UPDATE: По состоянию на декабрь 2011 года у нас появился еще один вариант с появлением поддержки этих тегов в FF и Safari:

p {
    -webkit-hyphens: auto;
    -moz-hyphens: auto;
    hyphens: auto;
}

Я провел некоторое базовое тестирование, и, похоже, оно работает на последних версиях Mobile Safari и Safari 5.1.1.

Таблица совместимости: https://developer.mozilla.org/en/CSS/hyphens#AutoCompatibilityTable

1 голос
/ 20 ноября 2014
p {
    overflow-wrap: break-word;
}


@-moz-document url-prefix() { 
    p {
        white-space: -moz-pre-wrap;
        word-wrap: break-word;
    }
}
1 голос
/ 11 июня 2014

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

    -moz-white-space: pre-wrap;
white-space: pre-wrap;        
    hyphens: auto;
    -ms-word-break: break-all;
    -ms-word-wrap: break-all;
    -webkit-word-break: break-word;
    -webkit-word-wrap: break-word;
word-break: break-word;
word-wrap: break-word;
    -webkit-hyphens: auto;
    -moz-hyphens: auto;
    -ms-hyphens: auto;
hyphens: auto;

Первоначально опубликовано Enigmo: https://stackoverflow.com/a/14191114

1 голос
/ 01 апреля 2009

Да, если это возможно, установка абсолютной ширины и установка overflow : auto работают хорошо.

...