Тег pre (от английского preformatted text, «заранее отформатированный текст») выводит содержимое так, как оно записано в исходнике: пробелы, табуляции и переносы строк остаются на своих местах, а шрифт по умолчанию моноширинный. Тег парный. Закрывающий тег обязателен: без него всё, что записано ниже, окажется внутри блока. Собственных атрибутов у него нет, работают только глобальные, а старые width, cols и wrap по данным MDN визуального эффекта не дают.
Ниже разобрано, для чего нужен тег pre в HTML, какой перенос строки в нём пропадает, откуда берутся лишние пробелы и что делать с длинными строками.
<pre>site/
index.html
css/
style.css</pre>
В этой статье
- Для чего нужен тег pre в HTML и что он сохраняет
- Перенос строки в теге pre: какой пропадает, а какой остаётся
- Табуляция в теге pre: ширина tab-size и копирование
- Лишние пробелы в теге pre: отступы из исходника попадают в текст
- Тег pre и CSS: white-space со значениями pre, pre-wrap и pre-line
- Длинные строки в теге pre: прокрутка, перенос и фокус с клавиатуры
- Теги pre и code вместе: что можно записывать внутри pre
- Частые ошибки с тегом pre
Для чего нужен тег pre в HTML и что он сохраняет
Обычный HTML-текст браузер сжимает: схлопывание - это когда подряд идущие пробелы, табуляции и переносы строк превращаются в один пробел. Для абзаца это удобно, а для дерева папок, вывода команды, стихотворения или рисунка из символов нет: строки слипаются, отступы пропадают. Тег pre отключает схлопывание внутри себя.
Сверху та же запись в div: переносы и отступы схлопнулись в пробелы. Снизу она в pre: строки и отступы на месте.
Чаще всего в pre записывают дерево папок, как в примере выше, вывод программы, лог, стихи, рисунок из символов (ASCII-арт) и многострочный код. Для кода внутрь pre добавляют code, для вывода программы - samp: сам pre отвечает только за пробелы и переносы, а смысл задают соседние теги.
Кроме сохранения пробелов тег меняет ещё три вещи: он выводится блоком, шрифт по умолчанию monospace, а сверху и снизу браузер добавляет поля по 13 px. Размер шрифта тоже меньше обычного: почему так получается, подробно написано на странице тега code, у pre поправка та же.
Перенос строки в теге pre: какой пропадает, а какой остаётся
Внутри pre переносы записывают обычным Enter в исходнике, тег br не нужен: строка заканчивается там, где она закончилась в файле. Но у правила есть три исключения, о которых в справочниках почти не пишут.
Первое: перенос строки сразу после открывающего <pre> браузер отбрасывает. Так сделано для удобства: содержимое можно начать с новой строки и не получить пустую строку сверху. Чтобы пустая строка всё-таки появилась, нужны два переноса подряд. Запись переноса кодом не помогает: браузер отбрасывает и её.
Второе: перенос перед закрывающим </pre> лишней строки не даёт. Третье: комментарий HTML внутри pre в выводе исчезает, а переносы вокруг него остаются, поэтому на месте комментария получается пустая строка.
<pre>
строка 1
строка 2</pre>
Этот блок выведет две строки, пустой строки сверху не будет. Проверьте на своей записи в примере ниже.
Пример: что получит браузер из вашей записи
Поле уже заполнено, его можно менять, а кнопки записывают в поле готовые варианты. В первом блоке видно, что именно получил браузер: точка - пробел, стрелка - табуляция, знак абзаца - конец строки. Во втором блоке тот же текст так, как его покажет pre.
Тег br внутри pre тоже даёт перенос, и при копировании получится обычный перенос строки, но он лишний: переносы из исходника и так сохраняются.
Табуляция в теге pre: ширина tab-size и копирование
Символ табуляции (клавиша Tab в редакторе) pre сохраняет и выводит как сдвиг до ближайшей позиции, кратной восьми знакам. За ширину отвечает свойство tab-size: по умолчанию оно равно 8, а значение tab-size: 2 сдвигает знаки к позициям, кратным двум.
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 для них не нужен, достаточно класса.
.address {
white-space: pre-line;
}
Оформляют pre как обычный блок: шрифт списком, поля и фон.
pre {
font-family: Consolas, "Courier New", monospace;
padding: 12px;
background: #f1eee7;
}
Длинные строки в теге pre: прокрутка, перенос и фокус с клавиатуры
Тег pre не переносит строки по ширине колонки: длинная строка выходит за край блока. На телефоне колонка около двухсот пикселей, поэтому это случается постоянно. Если ничего не задать, вместе со строкой расширяется вся страница, и у неё появляется горизонтальная прокрутка.
Способов два: оставить строку целой и дать блоку прокрутку или разрешить перенос. Прокрутку включает overflow-x: auto. Перенос включает white-space: pre-wrap, но он разрывает строку только по пробелам: слово без пробелов, например длинное название функции, останется целым и снова выйдет за край. Помогает overflow-wrap: anywhere: он разрывает слово в любом месте.
pre {
overflow-x: auto;
}
pre {
white-space: pre-wrap;
overflow-wrap: anywhere;
}
Пример: как уместить длинную строку в узкой колонке
Колонка узкая. Верхние кнопки выбирают строку, нижние - способ записи блока. Число измерено в кадре: на сколько строка шире колонки и сколько строк получилось.
У блока с прокруткой есть ещё одна особенность: в Chrome он получает фокус с клавиатуры. Нажмите Tab: фокус остановится на pre с прокруткой, и строку можно будет листать стрелками. У блока, где всё помещается, такой остановки нет. В других браузерах поведение может отличаться, поэтому для надёжности блоку с прокруткой можно прописать tabindex="0".
Теги pre и code вместе: что можно записывать внутри pre
Многострочный код оборачивают в pre, а внутрь него записывают code: pre сохраняет форму, code сообщает, что это код. Порядок один: pre снаружи, code внутри.
<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 оставит, но они разорвут строки, а проверка разметки сообщит об ошибке.
<pre><code>margin: 0;
<mark>padding: 0;</mark>
color: red;</code></pre>
Так одну строку блока можно подсветить, не ломая его форму.
Если внутри pre не код, а рисунок из символов или схема, сам по себе тег не объясняет, что нарисовано: для поисковика и для программ, читающих текст, это набор знаков. Поэтому блок оборачивают в figure, а смысл записывают словами в figcaption.
<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 |