Реализация печати страниц сайта (Print CSS)
Страница выглядит хорошо на экране и ужасно при печати — типичная ситуация. Навигация, рекламные баннеры, чат-виджеты, sticky-хедеры и фоновые картинки превращают распечатку в мусор. Решается отдельным набором CSS-правил и минимальным JavaScript.
Базовая структура print media query
/* Основной файл стилей */
@media print {
/* Скрываем всё лишнее */
header,
footer,
nav,
aside,
.sidebar,
.cookie-banner,
.chat-widget,
.share-buttons,
.advertisement,
.back-to-top,
[data-noprint],
.no-print {
display: none !important;
}
/* Контент на всю ширину */
.container,
.wrapper,
main,
article {
width: 100% !important;
max-width: 100% !important;
margin: 0 !important;
padding: 0 !important;
float: none !important;
}
/* Убираем тени и скругления */
* {
box-shadow: none !important;
text-shadow: none !important;
border-radius: 0 !important;
}
}
Типографика для печати
Экранные шрифты и print-шрифты — разные вещи. Для бумаги предпочтительны serif-шрифты:
@media print {
body {
font-family: Georgia, 'Times New Roman', serif;
font-size: 12pt;
line-height: 1.5;
color: #000;
background: #fff;
}
h1 { font-size: 24pt; margin-bottom: 12pt; }
h2 { font-size: 18pt; margin-bottom: 8pt; }
h3 { font-size: 14pt; margin-bottom: 6pt; }
p, li {
font-size: 12pt;
orphans: 3; /* минимум 3 строки перед разрывом страницы */
widows: 3; /* минимум 3 строки после разрыва */
}
/* Ссылки: показываем URL */
a[href]:after {
content: ' (' attr(href) ')';
font-size: 10pt;
color: #555;
}
/* Не показывать URL для якорей и javascript: */
a[href^='#']:after,
a[href^='javascript:']:after {
content: '';
}
/* Изображения */
img {
max-width: 100% !important;
page-break-inside: avoid;
}
}
Управление разрывами страниц
@media print {
/* Заголовки не отрываются от следующего абзаца */
h1, h2, h3, h4, h5, h6 {
page-break-after: avoid;
break-after: avoid;
}
/* Элементы, которые должны быть на одной странице */
.no-break,
table,
figure,
blockquote {
page-break-inside: avoid;
break-inside: avoid;
}
/* Принудительный разрыв перед разделом */
.page-break-before,
section.chapter {
page-break-before: always;
break-before: page;
}
/* Принудительный разрыв после */
.page-break-after {
page-break-after: always;
break-after: page;
}
}
Параметры страницы через @page
@page {
size: A4 portrait;
margin: 2cm 2.5cm 2cm 2.5cm;
}
@page :first {
margin-top: 3cm; /* больше места на первой странице */
}
@page :left {
margin-left: 3cm; /* для двусторонней печати: переплёт слева */
}
@page :right {
margin-right: 3cm;
}
/* Колонтитулы через @page (поддерживается в Chrome/Edge) */
@page {
@top-right {
content: 'ООО «Компания» — конфиденциально';
font-size: 9pt;
color: #999;
}
@bottom-center {
content: 'Стр. ' counter(page) ' из ' counter(pages);
font-size: 9pt;
}
}
Таблицы: повторяющийся заголовок
@media print {
thead {
display: table-header-group; /* повторять шапку на каждой странице */
}
tfoot {
display: table-footer-group;
}
tr {
page-break-inside: avoid;
}
table {
border-collapse: collapse;
width: 100%;
}
th, td {
border: 1px solid #999;
padding: 4pt 6pt;
text-align: left;
}
th {
background: #eee !important;
-webkit-print-color-adjust: exact;
print-color-adjust: exact;
}
}
Фоновые цвета и изображения
По умолчанию браузеры не печатают фоны. Для брендированных документов:
@media print {
.brand-block {
background-color: #1e40af !important;
color: #fff !important;
-webkit-print-color-adjust: exact;
print-color-adjust: exact; /* стандартное свойство */
}
/* Логотип через img, не через background-image */
.logo-bg {
background-image: none !important;
}
.logo-bg::before {
content: '';
display: block;
background-image: url('/logo-print.png');
background-size: contain;
background-repeat: no-repeat;
width: 120px;
height: 40px;
-webkit-print-color-adjust: exact;
print-color-adjust: exact;
}
}
JavaScript: кнопка печати и подготовка
function printPage(selector?: string) {
if (selector) {
// Печатаем только выбранную область
const content = document.querySelector(selector)
if (!content) return
const printWindow = window.open('', '_blank')
if (!printWindow) return
printWindow.document.write(`
<!DOCTYPE html>
<html>
<head>
<title>${document.title}</title>
<link rel="stylesheet" href="/css/app.css">
</head>
<body class="print-only">
${content.innerHTML}
</body>
</html>
`)
printWindow.document.close()
printWindow.focus()
printWindow.onload = () => {
printWindow.print()
printWindow.close()
}
return
}
window.print()
}
// Кнопка печати только в браузере, не для скринридеров
document.querySelectorAll('[data-print-btn]').forEach(btn => {
const selector = btn.getAttribute('data-print-target')
btn.addEventListener('click', () => printPage(selector ?? undefined))
})
before/after print события
window.addEventListener('beforeprint', () => {
// Раскрываем все аккордеоны — скрытый контент не печатается
document.querySelectorAll('.accordion-content[hidden]').forEach(el => {
el.removeAttribute('hidden')
el.setAttribute('data-was-hidden', 'true')
})
// Форсируем загрузку lazy-изображений
document.querySelectorAll('img[loading="lazy"]').forEach(img => {
const image = img as HTMLImageElement
if (image.dataset.src) {
image.src = image.dataset.src
}
})
})
window.addEventListener('afterprint', () => {
// Возвращаем состояние
document.querySelectorAll('[data-was-hidden]').forEach(el => {
el.setAttribute('hidden', '')
el.removeAttribute('data-was-hidden')
})
})
Чеклист перед сдачей
Обязательно проверить в Chrome → Ctrl+P: навигация скрыта, URL ссылок отображаются, таблицы не разрываются посередине строки, изображения не выходят за поля, нет пустых первых страниц из-за margin-top на body, шрифт читаем (не меньше 10pt).
Сроки
Базовый print.css для лендинга или блога — 2–4 часа. Для сложной страницы с таблицами, условной видимостью блоков и брендированными цветами — 1 день.







