Как предотвратить длинные слова от разрыва моего div?

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

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

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

БЕЗОПАСНОСТЬ. Я вижу эту проблему даже на самых крупных сайтах, особенно на немецких сайтах, где даже обычные слова, такие как "ограничение скорости", очень длинны ( "Geschwindigkeitsbegrenzung" ).

Есть ли у кого-нибудь подходящее решение?

Ответ 1

Мягкий дефис

Вы можете указать браузерам, где нужно разбить длинные слова, вставив мягкий дефис (­):

averyvery­longword

может отображаться как

averyverylongword

или

averyvery-
    длинное слово

Хорошее регулярное выражение может гарантировать, что вы не будете вставлять их, если это необходимо:

/([^\s-]{5})([^\s-]{5})/ → $1­$2

Браузеры и поисковые системы достаточно умны, чтобы игнорировать этот символ при поиске текста, а Chrome и Firefox (не проверял других) игнорируют его при копировании текста в буфер обмена.

<wbr> элемент

Другой вариант - ввести <wbr>, прежний IE-ism, который теперь в HTML5:

averyvery<wbr>longword

Перерывы без дефиса:

averyvery
    длинное слово

Вы можете достичь того же символа пробела с нулевой шириной &#8203; (или &#x200B).


FYI там также CSS hyphens: auto, поддерживаемый последними IE, Firefox и Safari (но в настоящее время не Chrome):

div.breaking {
  hyphens: auto;
}

Однако эта перенос основан на словаре переносов, и он не гарантирует сломать длинные слова. Однако он может сделать оправданный текст более приятным.

Ретро-нытье решение

<table> для макета плохо, но display:table для других элементов отлично. Он будет таким же изворотливым (и эластичным), как таблицы старой школы:

div.breaking {
   display: table-cell;
}

overflow и white-space: pre-wrap ответы ниже тоже хороши.

Ответ 2

Два исправления:

  • overflow:scroll - это гарантирует, что ваш контент можно увидеть за счет дизайна (полосы прокрутки уродливы)
  • overflow:hidden - просто отсекает любое переполнение. Это означает, что люди не могут читать контент.

Если (в примере SO) вы хотите остановить перекрытие отступов, вам, вероятно, придется создать еще один div внутри прокладки, чтобы сохранить ваш контент.

Изменить: как утверждают другие ответы, существует множество методов для усечения слов, будь то обработка ширины визуализации на стороне клиента (никогда не пытайтесь сделать эту серверную сторону, поскольку она никогда не будет работать надежно, перекрестится платформу) через JS и вставку символов break или использование нестандартных и/или дико несовместимых CSS-тегов (word-wrap: break-wordне работает в Firefox).

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

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

Изменить 2 (чтобы ответить на ваш комментарий ниже):

Начать с использования свойства CSS overflow не является идеальным, но он останавливает разрывы конструкций. Сначала приложите overflow:hidden. Помните, что переполнение может не сломаться при заполнении, так что либо гнездо div, либо использовать границу (что лучше всего подходит для вас).

Это скроет переполненный контент, и поэтому вы можете потерять смысл. Вы можете использовать полосу прокрутки (используя overflow:auto или overflow:scroll вместо overflow:hidden), но в зависимости от размеров div и вашего дизайна это может не выглядеть или работать отлично.

Чтобы исправить это, мы можем использовать JS, чтобы отбросить вещи и сделать некоторую форму автоматизированного усечения. Я был на полпути, выписав для вас какой-то псевдо-код, но на полпути он серьезно усложняется. Если вам нужно показать как можно больше, дайте hyphenator посмотреть (как указано ниже).

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

Ответ 3

Это сложная проблема, как мы знаем, и не поддерживаемая каким-либо общим способом между браузерами. Большинство браузеров вообще не поддерживают эту функцию.

В некоторых работах, выполненных с электронными письмами HTML, где использовался пользовательский контент, но script недоступен (и даже CSS не поддерживается очень хорошо), следующий бит CSS в оболочке вокруг вашего несмещенного блока содержимого должен наименьшая помощь:

.word-break {
  /* The following styles prevent unbroken strings from breaking the layout */
  width: 300px; /* set to whatever width you need */
  overflow: auto;
  white-space: -moz-pre-wrap; /* Mozilla */
  white-space: -hp-pre-wrap; /* HP printers */
  white-space: -o-pre-wrap; /* Opera 7 */
  white-space: -pre-wrap; /* Opera 4-6 */
  white-space: pre-wrap; /* CSS 2.1 */
  white-space: pre-line; /* CSS 3 (and 2.1 as well, actually) */
  word-wrap: break-word; /* IE */
  -moz-binding: url('xbl.xml#wordwrap'); /* Firefox (using XBL) */
}

В случае браузеров на основе Mozilla упомянутый выше файл XBL содержит:

<?xml version="1.0" encoding="utf-8"?>
<bindings xmlns="http://www.mozilla.org/xbl" 
          xmlns:html="http://www.w3.org/1999/xhtml">
  <!--
  More information on XBL:
  http://developer.mozilla.org/en/docs/XBL:XBL_1.0_Reference

  Example of implementing the CSS 'word-wrap' feature:
  http://blog.stchur.com/2007/02/22/emulating-css-word-wrap-for-mozillafirefox/
  -->
  <binding id="wordwrap" applyauthorstyles="false">
    <implementation>
      <constructor>
        //<![CDATA[
        var elem = this;

        doWrap();
        elem.addEventListener('overflow', doWrap, false);

        function doWrap() {
          var walker = document.createTreeWalker(elem, NodeFilter.SHOW_TEXT, null, false);
          while (walker.nextNode()) {
            var node = walker.currentNode;
            node.nodeValue = node.nodeValue.split('').join(String.fromCharCode('8203'));
          }
        }
        //]]>
      </constructor>
    </implementation>
  </binding>
</bindings>

К сожалению, Opera 8+, похоже, не нравится ни одному из вышеперечисленных решений, поэтому JavaScript должен быть решением для этих браузеров (например, Mozilla/Firefox.) Еще одно кросс-браузерное решение (JavaScript), которое включает в себя более поздние версии издания Opera могли бы использовать Hedger Wang script, найденный здесь: http://www.hedgerwow.com/360/dhtml/css-word-break.html

Другие полезные ссылки/мысли:

Incoherent Babble "Архив блога" Эмуляция CSS-обложки для Mozilla/Firefox
http://blog.stchur.com/2007/02/22/emulating-css-word-wrap-for-mozillafirefox/

[OU] Нет обертки слов в Opera, отображается отлично в IE
http://list.opera.com/pipermail/opera-users/2004-November/024467.html
http://list.opera.com/pipermail/opera-users/2004-November/024468.html

Ответ 4

CSS-перекрестный браузер Word Wrap

.word_wrap
{
    white-space: pre-wrap; /* css-3 */
    white-space: -moz-pre-wrap; /* Mozilla, since 1999 */
    white-space: -pre-wrap; /* Opera 4-6 */
    white-space: -o-pre-wrap; /* Opera 7 */
    word-wrap: break-word; /* Internet Explorer 5.5+ */
}

Ответ 5

Вы имеете в виду, что в браузерах, которые его поддерживают, word-wrap: break-word не работает?

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

Если переполнение не является хорошим решением, только пользовательский javascript может искусственно разбить длинное слово.

Примечание: есть также <wbr> Тег разрыва Word. Это дает браузеру место, где он может разделить линию вверх. К сожалению, тег <wbr> не работает во всех браузерах, только Firefox и Internet Explorer (и Opera с трюком CSS).

Ответ 6

Используйте стиль word-break:break-all;. Я знаю, что это работает на таблицах.

Ответ 7

Просто проверено IE 7, Firefox 3.6.8 Mac, Firefox 3.6.8 Windows и Safari:

word-wrap: break-word;

работает для длинных ссылок внутри div с заданной шириной и без переполнения, объявленных в css:

#consumeralerts_leftcol{
    float:left;
    width: 250px;
    margin-bottom:10px;
    word-wrap: break-word;
}

Я не вижу проблем с несовместимостью

Ответ 9

После долгих боев это то, что сработало для меня:

.pre {
    font-weight: 500;
    font-family: Courier New, monospace;
    white-space: pre-wrap;
    word-wrap: break-word;
    word-break: break-all;
    -webkit-hyphens: auto;
    -moz-hyphens: auto;
    hyphens: auto;
}

Работает в последних версиях Chrome, Firefox и Opera.

Обратите внимание, что я исключил многие из свойств white-space, которые другие предложили, - которые действительно нарушили отступ pre для меня.

Ответ 10

Для меня на div без фиксированного размера и с динамическим контентом он работал с помощью:

display:table;
word-break:break-all;

Ответ 11

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

word-wrap: break-word;

woks отлично работает в IE, но word-wrap не является стандартным свойством CSS. Это специфическое свойство Microsoft и не работает в Firefox.

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

overflow: hidden;

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

Ответ 12

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

Ответ 13

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

Наше решение состояло в том, чтобы сначала использовать замену регулярного выражения, чтобы поместить пространство с нулевой шириной (& # 8203;) после каждых 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 not whitespace or one of the special chars defined below
    var longRunsRegex = cachedRegex('([^\\s\\.\/\\,[email protected]\\|-]{' + position + '})(?=[^\\s\\.\/\\,[email protected]\\|-])', 'g');
    return str
                .replace(longRunsRegex, '$1&#8203;') // put a zero-width space every requested number of chars that not whitespace or a special char
                .replace(makeWrappable.SPECIAL_CHARS_REGEX, '$1&#8203;'); // and one after special chars we want to allow breaking after
};
makeWrappable.SPECIAL_CHARS_REGEX = /([\.\/\\,[email protected]\|-])/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: Наличие этого символа в данных больше не является теоретической возможностью, это наблюдаемая проблема. Пользователи передают данные, скопированные с экрана, они сохраняются в db, поисковые запросы, вещи сортируются странно и т.д.

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

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

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

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

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

var longRunsRegex = cachedRegex('([^&\\s\\.\/\\,[email protected]\\|-]{' + position + '})(?=[^&\\s\\.\/\\,[email protected]\\|-])', 'g');

Ответ 14

Необходимо установить "table-layout: fixed" для работы с word-wrap для работы

Ответ 15

HYPHENATOR - правильный ответ (см. выше). Реальная проблема, стоящая за вашим вопросом, заключается в том, что веб-браузеры по-прежнему (в 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

Ответ 16

Для совместимости с 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/prevent-long-urls-from-breaking-out-of-container/

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

Ответ 17

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

word-wrap: break-word;
overflow-wrap: break-word;
word-break: break-all;

Ответ 18

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

Ответ 19

Если у вас есть это -

  <style type="text/css">
      .cell {
            float: left;
            width: 100px;
            border: 1px solid;
            line-height: 1em;
      }
  </style>

  <div class="cell">TopLeft</div>
  <div class="cell">TopMiddlePlusSomeOtherTextWhichMakesItToLong</div>
  <div class="cell">TopRight</div>
  <br/>
  <div class="cell">BottomLeft</div>
  <div class="cell">BottomMiddle</div>
  <div class="cell">bottomRight</div>

просто переключитесь в вертикальный формат с помощью div и используйте min-width в CSS вместо ширины -

  <style type="text/css">
      .column {
            float: left;
            min-width: 100px;
      }
      .cell2 {
            border: 1px solid;
            line-height: 1em;
      }
  </style>

  <div class="column">
      <div class="cell2">TopLeft</div>
      <div class="cell2">BottomLeft</div>
  </div>
  <div class="column">
      <div class="cell2">TopMiddlePlusSomeOtherTextWhichMakesItToLong</div>
      <div class="cell2">BottomMiddle</div>
  </div>
  <div class="column">
      <div class="cell2">TopRight</div>
      <div class="cell2">bottomRight</div>
  </div>
  <br/>

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

Ответ 20

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

    -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: fooobar.com/questions/15269/...

Ответ 21

p {
    overflow-wrap: break-word;
}


@-moz-document url-prefix() { 
    p {
        white-space: -moz-pre-wrap;
        word-wrap: break-word;
    }
}

Ответ 23

после того, как все слово обернется и сломается, сохраните свое переполнение и посмотрите, решит ли это вашу проблему. просто измените отображение div на: display: inline;

Ответ 24

Добавьте это в css вашего div: word-wrap: break-word;

Ответ 25

Простая функция (требует underscore.js) - основана на ответе @porneL

    String.prototype.shyBreakString = function(maxLength) {
        var shystring = [];
        _.each(this.split(' '), function(word){
            shystring.push(_.chop(word, maxLength).join('&shy;'));
        });
        return shystring.join(' ');
    };

Ответ 26

Я написал функцию, которая отлично работает там, где она вставляет &shy; x буквы в слово для хорошего разрыва строки. Все ответы здесь не поддерживали все браузеры и устройства, но это хорошо работает с использованием PHP:

/**
 * Add line-break to text x characters in
 * @param  string  $text          
 * @param  integer $characters_in 
 * @return string                 
 */
function line_break_text($text, $characters_in = 10) {

    $split = explode(' ', $text);

    if ( ! empty($split)) {

        foreach ($split as $key => $var) {

            if ( strlen($var) > $characters_in ) {

                $split[$key] = substr_replace($var, '&shy;', $characters_in, 0);

            }

        }

    }

    return implode(' ', $split);

}