Оформление длинных блоков кода
Длинный код нельзя оценивать только по тому, помещается ли он в красивую карточку. Читатель должен различить структуру строк, увидеть окончание выражения и сопоставить пример с соседним объяснением. В старом уроке LINQ это особенно важно: XML и цепочки запросов занимают значительно больше места, чем короткая демонстрационная команда.
В этом уроке вы оформите листинг reading-lab так, чтобы его ширина не растягивала страницу, а длинная строка оставалась доступной внутри собственного блока. Продолжайте состояние шестого урока. Все функции в учебном листинге остаются условными; мы изучаем отображение, а не создаём исполняемый генератор.
Выбираем поведение строки
Обычное предложение переносится по словам, потому что его смысл сохраняется при смене ширины колонки. В коде перенос может влиять на восприятие структуры: читатель видит новую экранную строку, хотя в исходнике она относится к одному выражению. Поэтому нужно различать исходный перевод строки и визуальный перенос.
Для нашего основного варианта сохраним строки и добавим локальную горизонтальную прокрутку. Это подходит для примеров, в которых важно сопоставлять отступы и окончания выражений. Такой выбор не означает, что перенос кода всегда вреден. Для коротких команд или текстового вывода можно дать отдельный режим, если его назначение объяснено.
Особенно опасно исправлять длинную строку уменьшением размера до едва различимого. На большом экране это может скрыть полосу прокрутки, но на телефоне строка опять не поместится. Причина остаётся прежней, а точность чтения ухудшается. Ширина технического выражения должна решаться внутри его компонента.
Не прячьте горизонтальное переполнение всей страницы. Если глобальный стиль просто обрезает всё за правым краем, читатель лишается последней части примера. Хорошее оформление делает границу локального блока понятной и сохраняет возможность добраться до всех символов. Это самостоятельная задача, отличная от ограничения ширины статьи.
Листинг с подписью и своей прокруткой
Следующий листинг — полный файл lesson-07.css, добавляемый после предыдущих:
.reading-lab .lab-code { max-width: 100%; min-width: 0; overflow: hidden; }
.reading-lab .lab-code pre {
max-width: 100%; overflow-x: auto; overflow-y: auto;
white-space: pre; padding: 1rem 1.25rem; tab-size: 4;
}
.reading-lab .lab-code code { display: block; min-width: 0; }
.reading-lab .lab-code-label { border-radius: var(--lab-radius) var(--lab-radius) 0 0; }
.reading-lab .lab-prose :not(pre) > code {
background: var(--lab-soft); padding: .1em .25em; border-radius: .2em;
}
Ожидается цельная поверхность с короткой подписью и отдельно прокручиваемым кодом. Внешний overflow: hidden принадлежит рамке компонента и не удаляет содержимое pre: само pre получает доступную прокрутку. Не переносите скрытие на листинг без внутреннего прокручиваемого элемента, иначе получится уже описанное обрезание.
white-space: pre сохраняет пробелы и переводы строк исходника и не выполняет обычный перенос по ширине. Различие режимов описано в MDN. tab-size: 4 задаёт визуальный размер табуляции, но не меняет текст файла. Если автор вставил смешанные пробелы и табуляцию, компонент не исправит редакционную несогласованность автоматически.
Встроенный код в абзаце получает небольшую поверхность, но остаётся частью строки. Его не нужно оформлять так же крупно, как самостоятельный листинг. Иначе предложение с четырьмя именами свойств превратится в цепочку отдельных тяжёлых меток. Скромное выделение помогает увидеть техническую запись, сохраняя темп чтения объяснения.
Подпись не должна обещать лишнего
В предоставленном HTML подпись говорит «Учебный фрагмент Python». Она описывает язык и статус. Не заменяйте её на «Рабочий код», если пример намеренно условный или ещё не был выполнен. Дизайн должен поддерживать точность содержания, поэтому яркая метка не может служить доказательством результата.
В реальном уроке полезна краткая подпись с назначением фрагмента: исходный запрос, изменённое условие или получаемый текстовый вывод. Это позволяет сопоставить соседние листинги без обязательного чтения каждой строки. При этом подпись не заменяет объяснение параметров в основном тексте. У неё другая плотность и роль.
Номера строк тоже не являются обязательными. Они помогают, когда автор ссылается на конкретные строки или пример достаточно велик. Но нумерация требует согласования с копированием, масштабом и переносом. В данной серии оставим листинг без номеров, чтобы не строить новый инструмент отображения кода ради оформления.
Кнопку копирования можно добавить позже к готовому компоненту, но нельзя рисовать её как действие без поведения. На статическом макете декоративная кнопка создаёт неверное ожидание. Если вы рассматриваете вариант в дизайн-системе, явно обозначьте его как прототип и опишите состояния отдельно. Здесь работающий компонент читает код без такой кнопки.
Высоту листинга пока не ограничиваем. Большой пример может занимать значительную часть страницы, но это честное отражение его объёма. Внутренняя вертикальная прокрутка иногда удобна, однако создаёт второй маршрут движения и способна спрятать важное окончание. Если вы решите добавить максимальную высоту, объясните, почему читателю нужен такой вариант, и оставьте явный доступ ко всему фрагменту. Автоматическое обрезание длинного примера не является сокращением содержания.
Сравните также начало блока с абзацем перед ним. Подпись должна помогать узнать назначение, а первая строка не должна прятаться под отдельной панелью. Слишком высокий заголовок языка делает короткую команду визуально тяжёлой. Для длинного примера разумнее сохранить компактную верхнюю область и дать место самому коду. Так компонент остаётся учебным объектом, а не имитацией окна редактора со множеством декоративных кнопок.
Когда нужен режим переноса
Представьте короткий вывод программы с длинным адресом файла. В нём позиция символов менее важна, чем возможность прочитать всё сразу. Можно добавить к существующему контейнеру класс lab-code-wrap и отдельно определить вариант. Это дополнительный фрагмент, а не замена основного режима:
.reading-lab .lab-code-wrap pre { white-space: pre-wrap; overflow-wrap: anywhere; }
Такой блок сохраняет исходные пробелы и переводы строк, но допускает визуальное продолжение длинной строки. У добавленного класса есть собственное определение, а основное правило по-прежнему действует для обычных листингов. В сохранённом базовом HTML этот вариант не включён; для сравнения добавьте класс только выбранному техническому фрагменту.
Смысл выбора должен оставаться явным. Не используйте перенос для таблицы исходных данных, где пробелы формируют колонки, не посмотрев на результат. Также не вставляйте ручные переводы строк в исходник исключительно под текущую ширину окна. После изменения размера такие переводы могут дать короткие обрывки и исказить копируемый пример.
Для оценки возьмите длинную строку, многострочный XML и короткую команду. У каждого случая есть своё ограничение. В первом важен доступ к окончанию выражения, во втором — отступы дерева, в третьем — компактность. Один вариант компонента может покрыть большинство примеров, но решение должно основываться на содержании, а не на стремлении избавиться от любого скролла.
После этого урока листинг отделён от объяснения, сохраняет текстовую структуру и не назначает ширину всей страницы. При будущем просмотре ожидайте, что основная статья остаётся неподвижной по горизонтали, а перемещение внутри длинного кода доступно отдельно. В следующем уроке перенесём принцип локального переполнения на сравнение с несколькими колонками.