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

с момента перехода от компоновки таблицы к DIV-компоновке остается одна общая проблема:

: вы заполняете свой DIV динамическим текстом, и неизбежно есть сверхдлинное слово, которое простирается над краем столбца div и делает ваш сайт непрофессиональным.

РЕТРО-НЫТЬЕ: это никогда это произошло с использованием таблиц. Ячейка таблицы всегда будет красиво расширяться до ширины самого длинного слова.

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

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

26 ответов


мягкий перенос

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

averyvery­longword

может быть представлен как

averyverylongword

или

averyvery-
длинное

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

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

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


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

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

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

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

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

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

Edit 2 (чтобы обратиться к вашему комментарию ниже):

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

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

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

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


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

в некоторых работах, выполненных с HTML-сообщениями, где использовался пользовательский контент, но скрипт недоступен( и даже 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, - использовать сценарий хеджера Вана, найденный здесь: http://www.hedgerwow.com/360/dhtml/css-word-break.html

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

бессвязный лепет "архив блога" эмуляция CSS word-wrap для 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


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+ */
}

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


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

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

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

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


только что проверил 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;
}

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


Я только что узнал о правила переносов С этот вопрос. Это может решить проблему.


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

.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 отступ для меня.


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

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

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

например, так:

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

...результаты в этом:

abcde&shy;12345678901234

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

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

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

abcde&shy;12345&shy;67890&shy;1234

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

word-wrap: break-word;

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

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

overflow: hidden;

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


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

мы решили сначала использовать regex для замены поставить нулевой ширины пространства () после каждого 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, '&#8203;') // put a zero-width space every requested number of chars that's not whitespace or a special char
                .replace(makeWrappable.SPECIAL_CHARS_REGEX, '&#8203;'); // 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 = {};

необходимо установить "таблица-макет: исправлено" для word-wrap для работы


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

обновление: По состоянию на декабрь 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


для совместимости с 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 с заданной шириной.


использовать

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

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

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

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

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

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


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

    -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


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


p {
    overflow-wrap: break-word;
}


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

"word-wrap: break-word" работает в Firefox 3.5 http://hacks.mozilla.org/2009/06/word-wrap/


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


после всех обертываний и разрывов слова, сохраните переполнение и посмотрите, решит ли это вашу проблему. просто измените дисплей div на:display: inline;


простая функция (требуется подчеркивание.js) -- based off of @porneL answer

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

Я написал функцию, которая отлично работает там, где она вставляет &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);

}