Пользователь
0,0
рейтинг
1 декабря 2012 в 23:45

Разработка → CSS печатной версии страницы



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

Основными проблемами при распечатке документа становится плохая типографика, наличие лишней информации (например, элементы интерфейса) и неправильные цвета. Для стилизации можно использовать правило @media:

@media print {
}


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

h1, div#header, div#sidebar, div#footer { display: none; }


Правила страницы для печати


1. Современные браузеры умеют удалять фоновое изображение. Однако желательно добавлять background-image: none, чтобы старые браузеры тоже умели это.

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

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

a:after {content:" <" attr(href) ">";


Немного модифицировав код, можно добавить отображение URL только внешним ссылкам:

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


4. Для больших текстов иногда будет уместно разделение на части. Следующий код разбивает контент на каждом заголовке H3, печатая на новой странице:

h3 { page-break-before: always; }


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

article + article { page-break-before: always; }


5. Желательно переназначить стили сайтов с темным или ярким дизайном в стандартную цветовую схему — черный текст на белом фоне. Это удобно и для читабельности, и для экономии расходнвх материалов в принтере пользователя.

Корректное отображение


Как уже сказано выше, современные браузеры умеют удалять  ненужные элементы при печати, однако это не всегда требуется. В Firefox пользователь может сам контролировать внешний вид результата, в Chrome и Safari можно использовать код, приведенный ниже для отображения исходного стиля:

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


Как это выглядит в действии:



Качество печати


Зачастую результат печати сильно отличается от исходного на экране в худшую сторону. Одну из частых причин этого разберем на простом примере. Есть светлый текст на темном фоне:



Со следующим CSS:

header { background: #000; color: #fff; padding: 1rem;
font-family: Avenir, Arial, sans-serif; }


Браузер попытается привести версию для печати в нормальный вид:



Если на странице есть изображение, например логотип, то браузер его никак не корректирует, и получается ужасно:



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



Избежать этого ужаса можно при использовании CSS3 Filter:

@media print  {
header { background: none; color: #000; }
header img { -webkit-filter: invert(100%);
filter: invert(100%); }
}


Получается:



Для 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>


CSS:

@media print  {
header { background: none; color: #000; }
header img { filter: url(inverse.svg#negative);
-webkit-filter: invert(100%); filter: invert(100%); }
}


Для IE9 решение от Lea Verou:

<!--[if IE 9]>
      <style>
      @media print { 
            header:after { content:""; display: block;
   height: 1px; width: 1px; position: absolute; top: 100px; right: 100px; 
   outline: 100px solid invert; } 
      }
      </style>
   <![endif]-->


Использованные материалы:
@grokru
карма
407,0
рейтинг 0,0

Похожие публикации

Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Спецпроект

Самое читаемое Разработка

Комментарии (27)

  • +6
    Увы, page-break далеко не везде работает.
    Так и не решил эту проблему.
    • 0
      Бо́льшая проблема, что браузеры не дают контроля над размером печатаемых страниц. Ну и page-break-inside: avoid и page-break-before: avoid поддерживаются чуть менее чем нигде. В результате, page-break'и удобны разве что для красивостей, типа начала раздела с новой страницы.

      На моём опыте надо было решить проблему печати больших таблиц без разрывов посреди ячеек. Никакого осмысленного решения, помимо угадывания по браузеру и прогнозу погоды заведомо влезающей в страницу высоты (с сопутствующими большими пробелами в ряде случаев) и вставки разрывов через js, не представляю.
      • +1
        page-break-inside'а осталось только в Firefox'е 19-ом дождаться. Реальную работу в других браузерах не проверял.
    • 0
      Аналогично. Тогда, правда, ко мне пришла такая мысль, что ежели CSS начнет двигаться в сторону печатной верстки, то остановится уже будет сложно и нужно будет описать все плюшки верстки печатных изданий.
  • +13
    grokru
    a[href^=http]:after {content:" <" attr(href) ">";

    Где вы научились этой магии? Я если чесно впервые такое использование CSS вижу
    • НЛО прилетело и опубликовало эту надпись здесь
    • –1
      Странный вопрос, это же просто перевод.
  • НЛО прилетело и опубликовало эту надпись здесь
    • +2
      Проблема проверить? Собственно, что и следовало ужидать. Все работает, как и описано в статье, ибо пока Firefox не понимает свойства filter со значением не из SVG, он его и не применит. В этом и смысл всего кода.
      • НЛО прилетело и опубликовало эту надпись здесь
  • +12
    Вот знаете за что я люблю Хабр? Вот ты такой весь классный, постоянно учишь что-то, совершенствуешься, думаешь: «пусть я не идеален, но я думаю, что знаю достаточно, что бы делать что-то качественно». И вдруг тебе попадается статья на такую тему, о которой ты не задумывался, не использовал, но которая раскрывает тебе глаза и натягивает веки на затылок. Я конечно не крутой мега-верстальщик, но меня прямо дрож берет, когда все выглядит и делается и объясняется так «чисто» (не могу подобрать лучшее слово). Спасибо большое за статью.

    PS Мне так понравилось, что у меня просто синдром какой-то, мне хочется все странички с тольками текста перевести в версии для печати :) Могли бы Вы объяснить, когда это стоит делать, а когда нет? Я понимаю что например на документах, договорах-офертах и любой информации, которую пользователь теоретически захочет распечатать. Но нужно ли например подобное делать для страниц контактов и т.п. Где будет «хорошим тоном» добавить версию для печати?
    • +1
      Договора и другие документы лучше предоставлять в PDF, или в крайнем случае в том виде, в котором они должны быть распечатаны, без магии с CSS.
  • 0
    Спасибо за статью, как раз вчера озадачился этим вопросом, и тут оп и статья.
  • +1
    Где же были буквально 3 недели назад, когда я мучался с Safari и Chrome, которые нагло скрывали нужные мне элементы при печати? Огромное спасибо за статью и за
    * { -webkit-print-color-adjust: exact; }
    

    в частности!
  • +2
    Честно говоря, думал под катом будет впрыск для начинающих, а «вон оно как, Михалыч»… После 11 лет в вебе бывают и такие открытия. В избранное и спасибо!
  • 0
    Ребят, а как кнопку сделать, запускающую печать страницы?
    • 0
      var btn = document.getElementById('printbtn'); btn.onclick = function(){ document.print(); }

      Ну или как вам удобнее
  • 0
    Возможность сделать версию для печати радикально отличной от «нормальной» версии открывает простор для злоупотреблений.

    Из недавнего — вакансии яндекса при распечатывании теряют секцию с тестом для соискателей.
  • 0
    Спасибо за статью. Делал в своем веб приложении возможность печатать информацию сразу в виде бланка (для печати выводились дополнительные поля). Некоторые элементы были по-умолчанию с атрибутом display=hidden, а для @media print элементы показываются
  • 0
    Недавно разбирался с css версии для печати, так для себя и не смог решить следующие проблемы:
    1) Необходимо задать формат страницы равным A6.
    2) Необходимо задать отступы от края страницы и убрать все лишние колонтитулы.

    Видимо, проблема в том, что эти параметры задаются в настройках самого браузера, и не зависят от содержимого таблицы. Можно ли как то управлять этими настройками?
  • +1
    Сложил в копилку, спасибо.
  • 0
    Для простых сайтов, где стили помещаются в один файл 300 строк всё хорошо, но если их больше…

    Подскажите, как отлаживать страницу печати? На сайте множество стилей, одни переопределят другие, поэтому чтобы правильно написать заглушики нужно знать, какой стиль на верхнем уровне. Без средств отладки не обойтись.
    Мне не удалось воспользоваться ни Developer Tools в хроме, ни Firebug в фф. Как быть?
  • 0
    > div#header, div#sidebar, div#footer
    давно хотел спросить, зачем перед хэшем ставят название тега? Ведь достаточно просто указать сам айдишник:
    #header, #sidebar, #footer
    Может, есть какой-то смысл в этом, но мне этот смысл не даётся?..
    • 0
      Может быть потому, что header, sidebar и footer в другой разметке (шаблоне) могут быть не div'ами?
      Например — браузер не поддерживает HTML5 элементы ну вообще никак, для элементов header, sidebar и footer заданы свои стили, а для div'ов с такими ID для старых браузеров заданы свои. И шаблон выбирается по User Agent.
      Это всё из разряда предположений. Условия всегда разные.
      • +1
        >для элементов header, sidebar и footer заданы свои стили, а для div'ов с такими ID для старых браузеров заданы свои
        По идее, не должно быть других элементов с таким же id. Если уже есть <div id=header>, то <header id=header> уже не может быть. А если на другой странице элемент с id=header не является div, то на него этот селектор (div#header) не будет применим. Что мне кажется странным.
        • 0
          По идее, не должно быть других элементов с таким же id. Если уже есть <div id=header>, то <header id=header> уже не может быть.
          Он может быть в другой вёрстке (другом шаблоне) и может отличаться по стилю.
  • 0
    @media print {
    }


    Мне это очень помогло, т.к. ie11 в отличие от firefox при печать просто отказался применять имеющиеся на странице стили. Другая проблема, если есть inline стили, то они не переопределяются. Какие тут могут быть пути решения?

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