Frontender Magazine

Советы и приемы по подготовке стилей для печати

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

Что бы перешагнуть через пропасть между дизайном для печати и экрана веб-разработчики могут:

Разрабатывайте дизайн для печати, а не для экрана

Для начала, давайте рассмотрим основы. Современные стили для печати обычно размещаются внутри медиа-выражения:

@media print {

}

Вам не нужно создавать заново весь CSS, потому что стили по умолчанию будут полностью унаследованы медиа-выражением для печати – необходимо указать только различия. Большинство браузеров автоматически инвертируют цвета при печати в целях сохранения тонера, но для получения качественного результата вам придется явно указать изменяемые цвета. В итоге, простейшее медиа-выражение для печати должно выглядеть вот так:

@media print {
    body {
        color: #000;
        background: #fff;
    }
}

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

/* Стили по умолчанию */

h1 {
    color: #fff;
    background: url(banner.jpg);
}

@media print {
    h1 {
        color: #000;
        background: none;
    }

    nav, aside {
        display: none;
    }
}

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

@media print {
    h1 {
        color: #000;
        background: none;
    }

    nav, aside {
        display: none;
    }

    body, article {
        width: 100%;
        margin: 0;
        padding: 0;
    }

    @page {
        margin: 2cm;
    }
}

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

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

h2, h3 {
    page-break-after: avoid;
}

Во-вторых, что бы предотвратить печать изображений, превышающих по ширине печатный лист:

img {
    max-width: 100% !important;
}

В-третьих, убедимся, что статьи всегда начинаются с новой страницы:

article {
    page-break-before: always;
}

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

ul, img {
    page-break-inside: avoid;
}

Несмотря на то, что эти не все необходимые правило, это хорошее начало.

Принудительная печатать фоновых изображений и цвета

На некоторых сайтах, например портфолио, фоновые изображения и цвет являются важными визуальными компонентами. Если пользователь печатает страницу из браузера на основе WebKit (Google Chrome или Safari), мы можем заставить принтер отобразить цвета так, как мы видим их на экране (то есть заставить браузер распечатать фоновые изображения и цвета на странице). В общем-то, мы сделаем это только для цветных принтеров, которые можем определить с помощью медиа-выражения:

@media print and (color) {
    * {
        -webkit-print-color-adjust: exact;
        print-color-adjust: exact;
    }
}

К сожалению, в настоящее время Firefox, Opera или Internet Explorer не поддерживают аналогичные свойства.

Покажите URL внешних ссылок при печати

На сегодняшний день мы (еще) не можем переходить по ссылкам на печатных страницах, поэтому URL ссылок необходимо показывать при печати страницы. Чтобы не захламлять страницу, я предпочитаю показывать в статьях только ссылки на внешние ресурсы, а внутренние ссылки скрывать. Если вы используете на сайте относительные URL для внутренних ссылок, вы можете легко сделать это с помощью селектора по атрибуту и псевдо-элемента :after, не допустив печати внутренних ссылок и ссылок с изображениями внутри:

@media print {
    article a {
        font-weight: bolder;
        text-decoration: none;
    }

    article a[href^=http]:after {
        content:" <" attr(href) "> ";
    }
}

Рассмотрим следующий фрагмент HTML:

<p>Вы уже исследовали этот <a href="/blog">сайт</a>; настало время <a href="http://www.webplatform.org/">прочесть другие статьи о веб-разработке</a>.</p>

Так выглядит распечатанный результат:

Скиншот

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

article a[href^="#"]:after {
    content: "";
}

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

$a:after > img {
    content: "";
}

С приходом CSS4 показать только внешние ссылки будет значительно проще:

a:not(:local-link):after {
    content:" <" attr(href) "> ";
}

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

Распечатайте QR-коды для упрощения работы со ссылками

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

Страница с распечатанным QR-кодом, ведущим на веб-версию

Страница с распечатанным QR-кодом, ведущим на веб-версию. Увеличенное изображение.

Для создания соответствующего QR-кода мы используем Google’s Chart API, который имеет 4 обязательных параметра:

Обычно URL стоит привязать к заголовку в верхней части страницы:

<header>
<h1>Lizabeth’s Salon</h1>
<h2>Providing Intellectual Stimulation Online Since 2001</h1>
</header>

При печати мы оставим поле справа от заголовка h1, и разместим в этой области QR-код:

header h1 {
    margin-right: 200px;
    margin-bottom: 2rem;
    line-height: 1.5;
}

Так как QR-код будет уникальным для каждой страницы, его стоит добавлять прямо на страницу с помощью элемента <style>:

@media print {
    header h1:after {
        content: url(https://chart.googleapis.com/chart?cht=qr&amp;chs=150x150&amp;chl=http://yourdomain.com&amp;choe=UTF-8);
        position: absolute;
        right: 0;
        top: 0;
    }
}

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

@media print {
    h1:after {
        content: url(https://chart.googleapis.com/chart?cht=qr&amp;chs=150x150&amp;chl=http://<?=$_SERVER["SERVER_NAME"].$_SERVER["REQUEST_URI"];?>&amp;choe=UTF-8);
        position: absolute;
        right: 0;
        top: 0;
    }
}

Для WordPress:

@media print {
    h1:after {
        content: url(https://chart.googleapis.com/chart?cht=qr&amp;chs=150x150&amp;chl=http://<?php the_permalink();?>&amp;choe=UTF-8);
        position: absolute;
        right: 0;
        top: 0;
    }
}

Очевидно, что оба предложенных выше решения будут работать только для страниц на PHP и WordPress.

Используйте CSS3-фильтры для улучшения качества печати

При печати логотипов браузеры зачастую испытывают проблемы, особенно, если светлый логотип расположен на темном фоне страницы:

Изображение логотипа с заливкой Распечатанная версия
Логотип на темном фоне Распечатанный логотип на темном фоне
Логотип в виде PNG с альфа-каналом Распечатанная версия
Логотип на темном фоне Распечатанный логотип на темном фоне с альфаканалом

Теоретически, вы можете использовать CSS-спрайт для переключения между версиями логотипа для вывода на экран и для печати, но это означает увеличение размера файла вдвое при потенциально небольшой выгоде. Вместо этого я рекомендую использовать CSS-фильтры (и их SVG-эквиваленты в Firefox) для инвертирования изображения непосредственно при печати:

@media print {
    header {
       background: none;
        color: #000;
    }

    header img {
        filter: url(inverse.svg#negative);
        -webkit-filter: invert(100%);
        filter: invert(100%);
    }
}

CSS3-фильтры делают именно то, что вы и ожидаете – инвертируют цвета изображения в заголовке, делая белое черным, и наоборот – но они работают только в Chrome и Safari. Для того, чтобы инвертировать изображения в Firefox, нам необходим другой подход – аналогичный фильтр, записанный в виде отдельного SVG-файла:

<svg xmlns="http://www.w3.org/2000/svg">
<filter id="negative">
<feColorMatrix values="-1 0 0 0 1
0 -1 0 0 1
0 0 -1 0 1
0 0 0 1 0" />
</filter>
</svg>

Принцип работы SVG-фильтра feColorMatrix слишком сложен, чтобы раскрывать его в рамках этой статьи. Подробнее о его работе вы можете прочесть в статье «Тонирование веб-страниц с помощью SVG-фильтров и JavaScript» на Dev.Opera.

Результат печати любого из типов логотипа (PNG с альфа-каналом или логотипа с заливкой фона) выглядит так:

Инвертированный логотип при печати

Заключение

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

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

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

Ссылки для дальнейшего чтения

A List Apart имеет объемный и заслуживающий похвалы архив статей и руководств по поддержке стилей для печати. Несмотря на то, что многие из материалов опубликованы достаточно давно, они по-прежнему остаются полезными для тех, кто готов рассматривать печать как равноценную часть веб-дизайна.

Если вы заметили ошибку, вы всегда можете отредактировать статью, создать issue или просто написать об этом Антону Немцеву в skype ravencry.

Dudley Storey
Автор:
Dudley Storey
Twitter:
@dudleystorey
Facebook:
dudley.storey
Сaйт:
http://demosthenes.info/
LinkedIn:
dudley-storey
Сергей Смольников
Переводчик:
Сергей Смольников
Мой Круг:
http://sergey-smolnikov.moikrug.ru/
Twitter:
@smolnikov
GitHub:
smolnikov

Комментарии (7 комментариев, если быть точным)

Автар пользователя
smolnikov

Больше всего мне понравился прием с QR-кодом. URL ссылок уже давно многие раскрывают при печати, но вот набирать их вручную, например, на смартфоне — иногда врагу не пожелаешь :)

Автар пользователя
SilentImp

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

Автар пользователя
smolnikov

Думаю, ход с одним QR-кодом, ведущим на текущую страницу, вполне себя оправдывает — всегда можно открыть веб-версию, найти в ней интересующую ссылку и перейти по ней.

В качестве альтернативы можно предложить, например, оставлять поля 3-4 см справа на странице и располагать QR-код там для каждой ссылки, если это оправдано. В списках литературы, как, например, в конце этой статьи, можно выводить QR-код непосредственно под ссылкой в том же пункте списка.

В целом, интересен сам прием с выводом QR-кода, а конкретная его реализация может изменяться от проекта к проекту.

Автар пользователя
sentyakov

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

Автар пользователя
iamstarkov

@sentyakov, я не понял вашей проблемы

Автар пользователя
smolnikov

@sentyakov, спецификация CSS3 вернула нам свойство size для @page, поэтому можно использовать @media print {@page {size: landscape;}}, правда это сработает только для всех страниц сразу.

Если нужно применить только для одной конкретной страницы, можно попробовать повернуть контент на 90 градусов с помощью #landscape_page {transform: rotate(90deg);} в стилях для печати, но тогда надо еще позаботиться о ширине элемента.

Автар пользователя
tegora

Прошу прощения, а свойство page-break-after: avoid; у Вас работает на Chrom и остальных выкбкитах? У меня стоит задача автоматически собирать html и из него конвертировать в pdf, не могу победить проблему чтобы текст подзаголовка всегда был приклеен к самому подзаголовку ( чтобы заголовок не оставался без текста в конце страницы). С одной стороны это свойство как раз подходит для решения этой задачи, но параметр avoid не поддерживается.