Аарон Густафсон недавно обратился через твиттер к Indiegogo , в котором он указал, что их страницы детального заказа непригодны к использованию в напечатанном виде.

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

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

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

Я забросил домашние принтеры очень давно, так как мне всегда казалось, что они ломаются после 10 минут работы. Но не все такие, как я. — Хейдон Пикеринг (Inclusive Design Patterns)

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

1. Подключение стилей для печати

Лучшим способом подключения стилей для печати является объявление директивы @media в вашем CSS.

body {
    font-size: 18px;
}

@media print {
    /* print styles go here */
    body {
        font-size: 28px;
    }
}

Альтернативно вы можете подключить стили в HTML, но это потребует дополнительного запроса HTTP.

<link media="print" href="print.css" />

2. Тестирование

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

Для отладки стилей для печати в Firefox откройте панель разработки (Shift + F2 или меню Tools > Web Developer > Developer Toolbar), введите в поле ввода media emulate print и нажмите enter. Активная вкладка до перезагрузки будет работать так, как будто типом медиа является print.

Активация эмуляции в Firefox

Эмуляция стилей для печати в Firefox

В Chrome откройте инструменты разработчика (CMD + Opt + I (macOS) или Ctrl + Shift + I (Windows) или меню View > Developer > Developer Tools) и вывести консоль, открыть панель рендеринга и в меню Emulate CSS Media выбрать Print.

Активация эмуляции в Chrome

Эмуляция стилей для печати в Chrome

3. Абсолютные единицы измерения

Абсолютные единицы измерения это плохо на экране, но отлично для печати. В стилях для печати их использование совершенно безопасно и даже рекомендовано использовать такие единицы как cm, mm, in, pt или pc.

section {
    margin-bottom: 2cm;
}

4. Специфические правила для страниц

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

@media print {
     @page {
        margin: 1cm;
    }
}

Директива @page это часть спецификации Paged Media Module, в которой есть такие замечательные вещи, как возможность выбрать первую печатаемую страницу или пустые страницы, позиционировать элементы в углу страницы и многое другое. Это можно использовать даже для печати книг.

5. Управление разрывами страниц

Так как печатные страницы, в отличие от веб-страниц, не являются бесконечными, контент будет разбиваться между страницами. У нас есть 5 свойств для управления тем, как это происходит.

Разрыв страницы перед элементом.

Если мы хотим, чтобы элемент всегда был в начале страницы, мы можем задать принудительный разрыв страницы с помощью правила page-break-before.

section {
    page-break-before: always;
}

page-break-before на MDN

Разрыв страницы после элемента.

Правило page-break-after позволяет нам форсировать или запрещать разрывы страниц после элемента.

h2 {
    page-break-after: always;
}

page-break-after на MDN

Разрыв страницы внутри элемента

Это свойство удобно, если вам надо избежать разрыва страницы внутри элемента.

ul {
    page-break-inside: avoid;
}

page-break-inside на MDN

Вдовы и сироты (висячие строки)

Иногда вам не нужен контроль над разрывом страницы, но важен контроль над тем, сколько строчек будет выведено на текущей, а сколько на следующей странице. Например, если последняя строка параграфа не помещается на текущей странице, на следующую страницу она будет перенесена вместе с предпоследней. Это потому, что соответствующее свойство widows по умолчанию равно 2. Мы можем изменить его.

p {
    widows: 4;
}

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

p {
    orphans: 3;
}

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

Вот демо на Codepen с несколькими примерами (отладочная версия для тестирования).

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

6. Сброс стилей

Имеет смысл сбросить для печати некоторые стили типа background-color, box-shadow и color.

Вот выдержка из стилей для печати HTML5 Boilerplate:

*,
*:before,
*:after,
*:first-letter,
p:first-line,
div:first-line,
blockquote:first-line,
li:first-line {
    background: transparent !important;
    color: #000 !important;
    box-shadow: none !important;
    text-shadow: none !important;
}

Стили для печати это одно из тех немногих исключений, когда использование ключевого слова !important вполне нормально.

7. Удаление необязательного контента

Чтобы избежать излишней траты чернил, вы должны удалить ненужное — оформительские элементы, рекламу, навигацию и т.п. с помощью свойства display: none.

Вы, в принципе, можете показать только основной контент и спрятать все остальное:

body > *:not(main) {
    display: none;
}

8. Печать адресов ссылок

Распечатанные ссылки бесполезны, если вы не знаете, куда они ведут.

Печать адреса ссылки рядом с ее текстом делается совершенно легко:

a[href]:after {
    content: " (" attr(href) ")";
}

Конечно, так будут показано все: относительные ссылки, абсолютные ссылки, якоря и прочее. Следующий вариант будет работать лучше:

a[href^="http"]:not([href*="mywebsite.com"]):after {
    content: " (" attr(href) ")";
}

Смотрится безумно, я знаю. Эти строчки работают так: выводится значение атрибута href рядом с любой ссылкой, у которой он есть, если он начинается с http, но не ведет на наш mywebsite.com.

9. Печать расшифровок аббревиатур

Аббревиатуры должны оборачиваться элементом <abbr> с указанием расшифровки в атрибуте title. Имеет смысл вывести это на печать.

abbr[title]:after {
    content: " (" attr(title) ")";
}

10. Печать фона

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

header {
    -webkit-print-color-adjust: exact;
    print-color-adjust: exact;
}

11. Медиазапросы

Если вы пишете медиазапросы как в следующем примере, имейте в виду, что стили в этом медиазапросе не будут применяться при печати.

@media screen and (min-width: 48em) {
    /* screen only */ 
}

Вы спросите, почему? Потому что правила CSS применяются только при выполнении обоих условий: min-width равен 48em, media-typescreen. Если избавиться от ключевого слова screen, то медиазапрос будет учитывать только значение min-width.

@media (min-width: 48em) {
    /* all media types */ 
}

12. Печать карт

Текущие версии Firefox и Chrome способны печатать карты, а вот Safari нет. Некоторые сервисы предоставляют статические карты, которые можно печатать вместо оригинала.

.map {
    width: 400px;
    height: 300px;
    background-image: url('http://maps.googleapis.com/maps/api/staticmap?center=Wien+Floridsdorf&zoom=13&scale=false&size=400x300&maptype=roadmap&format=png&visual_refresh=true');
    -webkit-print-color-adjust: exact;
    print-color-adjust: exact;
}

13. QR-коды

В статье от Smashing Magazine есть несколько полезных советов. Один из них заключается в создании QR-кодов для распечатываемых страниц, чтобы пользователям не приходилось набирать полный URL для доступа к странице.

Дополнение: печать неоптимизированных страниц

В ходе моего исследования, я нашел отличный инструмент, помогающий при печати неоптимизированных страниц. С Printliminator вы можете удалить ненужные элементы, просто нажав на них.

Вот демо на YouTube и сам проект на GitHub.

Дополнение 2: Gutenberg

Если вы ищете фреймворк, то вам может понравиться Gutenberg, делающий оптимизацию страниц немного проще.

Дополнение 3: Hartija

Это еще один фреймворк для создания стилей для печати от Владимира Каррера.