Тег pre в HTML: для чего нужен, перенос строки и пробелы

Тег pre (от английского preformatted text, «заранее отформатированный текст») выводит содержимое так, как оно записано в исходнике: пробелы, табуляции и переносы строк остаются на своих местах, а шрифт по умолчанию моноширинный. Тег парный. Закрывающий тег обязателен: без него всё, что записано ниже, окажется внутри блока. Собственных атрибутов у него нет, работают только глобальные, а старые width, cols и wrap по данным MDN визуального эффекта не дают.

Ниже разобрано, для чего нужен тег pre в HTML, какой перенос строки в нём пропадает, откуда берутся лишние пробелы и что делать с длинными строками.

HTML
<pre>site/
  index.html
  css/
    style.css</pre>

Для чего нужен тег pre в HTML и что он сохраняет

Обычный HTML-текст браузер сжимает: схлопывание - это когда подряд идущие пробелы, табуляции и переносы строк превращаются в один пробел. Для абзаца это удобно, а для дерева папок, вывода команды, стихотворения или рисунка из символов нет: строки слипаются, отступы пропадают. Тег pre отключает схлопывание внутри себя.

Результат

Сверху та же запись в div: переносы и отступы схлопнулись в пробелы. Снизу она в pre: строки и отступы на месте.

Чаще всего в pre записывают дерево папок, как в примере выше, вывод программы, лог, стихи, рисунок из символов (ASCII-арт) и многострочный код. Для кода внутрь pre добавляют code, для вывода программы - samp: сам pre отвечает только за пробелы и переносы, а смысл задают соседние теги.

Кроме сохранения пробелов тег меняет ещё три вещи: он выводится блоком, шрифт по умолчанию monospace, а сверху и снизу браузер добавляет поля по 13 px. Размер шрифта тоже меньше обычного: почему так получается, подробно написано на странице тега code, у pre поправка та же.

Перенос строки в теге pre: какой пропадает, а какой остаётся

Внутри pre переносы записывают обычным Enter в исходнике, тег br не нужен: строка заканчивается там, где она закончилась в файле. Но у правила есть три исключения, о которых в справочниках почти не пишут.

Первое: перенос строки сразу после открывающего <pre> браузер отбрасывает. Так сделано для удобства: содержимое можно начать с новой строки и не получить пустую строку сверху. Чтобы пустая строка всё-таки появилась, нужны два переноса подряд. Запись переноса кодом &#10; не помогает: браузер отбрасывает и её.

Второе: перенос перед закрывающим </pre> лишней строки не даёт. Третье: комментарий HTML внутри pre в выводе исчезает, а переносы вокруг него остаются, поэтому на месте комментария получается пустая строка.

HTML
<pre>
строка 1
строка 2</pre>

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

Пример: что получит браузер из вашей записи

Результат

Поле уже заполнено, его можно менять, а кнопки записывают в поле готовые варианты. В первом блоке видно, что именно получил браузер: точка - пробел, стрелка - табуляция, знак абзаца - конец строки. Во втором блоке тот же текст так, как его покажет pre.

Тег br внутри pre тоже даёт перенос, и при копировании получится обычный перенос строки, но он лишний: переносы из исходника и так сохраняются.

Табуляция в теге pre: ширина tab-size и копирование

Символ табуляции (клавиша Tab в редакторе) pre сохраняет и выводит как сдвиг до ближайшей позиции, кратной восьми знакам. За ширину отвечает свойство tab-size: по умолчанию оно равно 8, а значение tab-size: 2 сдвигает знаки к позициям, кратным двум.

CSS
pre {
  tab-size: 4;
}

В обычном тексте табуляция схлопывается в пробел, и tab-size ничего не меняет, поэтому свойство нужно блокам с сохранением пробелов. Если отступы в исходнике сделаны пробелами, оно на них не влияет.

При выделении и копировании из pre в буфер попадает настоящий символ табуляции, а не пробелы. Код, скопированный из такого блока, сохранит отступы табуляцией, как в исходном файле.

Лишние пробелы в теге pre: отступы из исходника попадают в текст

Раз pre сохраняет всё, он сохраняет и отступы, которыми выровнен сам HTML-файл. Если блок находится внутри вложенных div, а его содержимое записано с тем же отступом, эти пробелы окажутся в тексте: строки сдвинутся вправо, а перед закрывающим тегом появится строка из одних пробелов, то есть лишняя пустая строка внизу.

Поэтому содержимое pre записывают вплотную к левому краю, как бы глубоко ни был вложен сам тег. Закрывающий тег записывают сразу за последней строкой, без переноса.

Пример: сколько пробелов попадёт в текст

Результат

Кнопки меняют, сколько блоков div окружает pre (каждый уровень - два пробела отступа), и способ записи содержимого. В блоке «Запись в файле» видна разметка, ниже - что вывел pre, и подсчёт лишних пробелов и строк.

Тег pre и CSS: white-space со значениями pre, pre-wrap и pre-line

Сохранение пробелов - не свойство самого тега, а значение CSS-свойства white-space: pre, которое браузер по умолчанию задаёт блоку pre. Тот же вид даст и div с white-space: pre, только без моноширинного шрифта и без полей: их добавляет именно тег.

ЗначениеПробелы и табуляцииПереносы из исходникаПеренос по ширине колонки
normalСхлопываютсяСхлопываютсяЕсть
preСохраняютсяСохраняютсяНет
pre-wrapСохраняютсяСохраняютсяЕсть, по пробелам
pre-lineСхлопываютсяСохраняютсяЕсть

Значение pre-line подходит для текста, где переносы строк нужны, а отступы из пробелов нет: например, адрес или стихотворение, пришедшие из базы данных. Тег pre для них не нужен, достаточно класса.

CSS
.address {
  white-space: pre-line;
}

Оформляют pre как обычный блок: шрифт списком, поля и фон.

CSS
pre {
  font-family: Consolas, "Courier New", monospace;
  padding: 12px;
  background: #f1eee7;
}

Длинные строки в теге pre: прокрутка, перенос и фокус с клавиатуры

Тег pre не переносит строки по ширине колонки: длинная строка выходит за край блока. На телефоне колонка около двухсот пикселей, поэтому это случается постоянно. Если ничего не задать, вместе со строкой расширяется вся страница, и у неё появляется горизонтальная прокрутка.

Способов два: оставить строку целой и дать блоку прокрутку или разрешить перенос. Прокрутку включает overflow-x: auto. Перенос включает white-space: pre-wrap, но он разрывает строку только по пробелам: слово без пробелов, например длинное название функции, останется целым и снова выйдет за край. Помогает overflow-wrap: anywhere: он разрывает слово в любом месте.

CSS
pre {
  overflow-x: auto;
}
CSS
pre {
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

Пример: как уместить длинную строку в узкой колонке

Результат

Колонка узкая. Верхние кнопки выбирают строку, нижние - способ записи блока. Число измерено в кадре: на сколько строка шире колонки и сколько строк получилось.

У блока с прокруткой есть ещё одна особенность: в Chrome он получает фокус с клавиатуры. Нажмите Tab: фокус остановится на pre с прокруткой, и строку можно будет листать стрелками. У блока, где всё помещается, такой остановки нет. В других браузерах поведение может отличаться, поэтому для надёжности блоку с прокруткой можно прописать tabindex="0".

Теги pre и code вместе: что можно записывать внутри pre

Многострочный код оборачивают в pre, а внутрь него записывают code: pre сохраняет форму, code сообщает, что это код. Порядок один: pre снаружи, code внутри.

HTML
<pre><code>if (ready) {
  start();
}</code></pre>

Угловые скобки и амперсанд внутри pre записывают так же, как в code: как это делать и почему без замены тег пропадает, объяснено в разделе про угловые скобки. Там же написано, как убрать двойной фон у pre code: раздел про фон и отступы.

Внутри pre можно записывать строчные теги: code, samp, kbd, mark, b, i, span, a, а также img, small и sup: в проверке они работают. Старые справочники повторяют запрет на img, object, big, small, sub и sup внутри pre, но он действовал в HTML 4, а сейчас MDN допускает любой фразовый контент. Блочные div и p браузер внутри pre оставит, но они разорвут строки, а проверка разметки сообщит об ошибке.

HTML
<pre><code>margin: 0;
<mark>padding: 0;</mark>
color: red;</code></pre>

Так одну строку блока можно подсветить, не ломая его форму.

Если внутри pre не код, а рисунок из символов или схема, сам по себе тег не объясняет, что нарисовано: для поисковика и для программ, читающих текст, это набор знаков. Поэтому блок оборачивают в figure, а смысл записывают словами в figcaption.

HTML
<figure>
  <pre>браузер  ---запрос--->  сервер
браузер  <---ответ----  сервер</pre>
  <figcaption>Схема обмена: браузер отправляет запрос, сервер возвращает ответ.</figcaption>
</figure>

Частые ошибки с тегом pre

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

ОшибкаЧто происходитКак исправить
Пустую строку сверху ждут от одного переноса после <pre>Первый перенос отбрасывается, пустой строки нетЗаписать два переноса подряд
Содержимое записано с отступом вложенных блоковПробелы отступа попадают в текст, внизу появляется лишняя строкаЗаписывать содержимое вплотную к левому краю, а закрывающий тег сразу за последней строкой
Комментарий внутри preКомментария не видно, а на его месте остаётся пустая строкаУбрать комментарий из блока или записать его выше
Таблица из пробелов и табуляций в preСтолбцы съезжают, стоит сменить шрифт или ширину колонкиНастоящая table
pre для одной команды в середине предложенияБлок разрывает строку и добавляет поляcode для кода или kbd для клавиш
Длинная строка без прокрутки и без переносаСтраница становится шире, у неё появляется горизонтальная прокруткаoverflow-x: auto или white-space: pre-wrap вместе с overflow-wrap: anywhere
Абзац p перед pre не закрытАбзац закрывается сам, а после блока остаётся пустой абзацЗакрывать p до pre
div или p внутри preСтроки рвутся, проверка разметки сообщает об ошибкеСтрочные теги: span, mark, b
Рисунок из символов или схема в pre без описанияВнутри блока просто набор знаков: поисковик и программы, читающие текст, не поймут, что нарисованоОбернуть блок в figure и записать описание словами в figcaption, пример - в разделе про pre и code
Категория
Поделиться в социальных сетях

Отправить комментарий

0 Комментарии

Отправить комментарий (0)

#buttons=(Хорошо) #days=(20)

Мы используем файлы cookie для улучшения работы сайта. Подробнее
Хорошо
×