Масштабирование изображений в CSS @page margin boxes при печати
Как вписать логотип любого размера в @top-left бокс при CSS печать в Chrome с сохранением пропорций и отступами (90% высоты). Решение через background-image, object-fit contain и print css. Примеры кода и скриншоты проблем.
Как контролировать размер изображения в CSS @page margin boxes при печати в Chrome, чтобы оно масштабировалось под размер бокса с сохранением пропорций?
Пример кода:
<html>
<head>
<style>
@page {
size: a4;
margin-top: 30mm;
margin-bottom: 15mm;
margin-left: 10mm;
margin-right: 10mm;
@top-left {
content: url("/images/300x50.png");
background-color: thistle;
}
@top-center {
content: "";
background-color: red;
}
@top-right {
content: "First line of text in the header\A Second line of text in the header\A Third line of text in the header";
white-space: pre;
background-color: yellow;
}
}
</style>
</head>
<body>
<p>Document content starts here</p>
</body>
</html>
В боксе @top-left используется логотип различного размера и пропорций. Если изображение больше бокса (например, 600x100 или 300x200), оно обрезается или выходит за пределы. Как применить max-width, max-height, object-fit или другие свойства к изображению (не к боксу), чтобы оно помещалось в бокс, сохраняя aspect ratio, с отступами сверху и снизу (например, 90% высоты бокса)? padding, margin влияют на бокс, а не на изображение.
В CSS печать для margin boxes правила @page в Chrome стандартный content: url() вставляет изображение в натуральную величину, без масштабирования — оно просто обрезается. Чтобы логотип вписывался в бокс @top-left с сохранением пропорций и отступами (например, 90% высоты), замените на background-image с background-size: contain или auto 90vh, background-position: center. Это работает надежно в Chrome при печати, если включить отображение фонов (в настройках или через Puppeteer).
Содержание
- CSS печать и margin boxes в @page: основы и ограничения
- Проблема масштабирования изображений в print css
- Решение с object fit css через background-image в margin boxes
- Альтернативы: transform scale и object fit cover для Chrome
- Настройка отступов и сохранения aspect ratio в media print css
- Практические примеры и код для css для печати
- Источники
- Заключение
CSS печать и margin boxes в @page: основы и ограничения
CSS печать — это не просто @media print, а целая система paged media по спецификации W3C CSS Paged Media. Правило @page определяет layout страницы, включая size: A4 и отступы вроде margin-top: 30mm. А margin boxes вроде @top-left, @top-center — это именованные области в этих отступах, где можно разместить контент: текст, изображения или даже многострочные строки с \A.
Размер бокса @top-left фиксирован — он занимает пересечение margin-top и margin-left (в вашем примере ~30mm × 10mm минус padding). Chrome с версии 81 поддерживает это хорошо, как описано в блоге Chrome Developers. Но вот засада: свойства вроде max-width, max-height или object-fit не цепляются к content: url(). Изображение рендерится как замена контента в 1:1 масштабе, без подгонки. Хотите отступы? padding на боксе сожмет сам бокс, а не изображение. Звучит знакомо?
Почему так? Спецификация не предусматривает object-fit: contain для content: url() — это за пределами бокса. А Chrome строг к print CSS, чтобы избежать сюрпризов на бумаге.
Проблема масштабирования изображений в print css
Представьте: логотип 600×100 в боксе 30×10mm. Chrome просто обрежет справа, как на скриншоте выше. Или 300×200 — вылезет вниз, наложившись на контент. object-fit: cover? Не сработает, потому что img нет — это псевдоэлемент с content. box-sizing: border-box меняет размер бокса, но изображение все равно full-size.
В обсуждении на Stack Overflow разработчики PaulH567 и другие подтверждают: прямое управление через width/height на боксе искажает пропорции или ломает layout. padding: 10% добавит отступы, но сожмет бокс, и логотип все равно вылезет. А в Chrome при печати фоны по умолчанию скрыты — проверьте “Дополнительно > Фоны” в диалоге Print.
Это не баг, а фича paged media. Но решение есть, и оно элегантное.
Решение с object fit css через background-image в margin boxes
Главный хак: забудьте content: url(). Используйте content: ""; background-image: url("/images/300x50.png");. Теперь применяйте background-size: contain — изображение вписывается целиком, сохраняя aspect ratio, с отступами по бокам/сверху/снизу. Для вашего случая 90% высоты бокса: background-size: auto 90%;.
Почему это работает? background-size — это аналог object-fit: contain для фонов, поддерживается в print CSS Chrome идеально. Добавьте background-repeat: no-repeat; background-position: center; — и логотип центрируется с отступами.
Вот обновленный код на базе вашего примера:
@page {
size: A4;
margin-top: 30mm;
margin-bottom: 15mm;
margin-left: 10mm;
margin-right: 10mm;
@top-left {
content: "";
background-image: url("/images/300x50.png"); /* Или любой размер */
background-size: contain; /* Масштабирует под бокс с пропорциями */
/* Или для 90% высоты: background-size: auto 90%; */
background-repeat: no-repeat;
background-position: center;
background-color: thistle; /* Для отладки */
}
@top-center {
content: "";
background-color: red;
}
@top-right {
content: "First line of text in the header\A Second line of text in the header\A Third line of text in the header";
white-space: pre;
background-color: yellow;
}
}
Тестируйте в Chrome: Ctrl+P, “Дополнительно > Фоны”. Логотип любого размера (600×100, 300×200) впишется. В Puppeteer добавьте { printBackground: true }.
Альтернативы: transform scale и object fit cover для Chrome
Если background не подходит (редко), попробуйте transform: scale(). Оставьте content: url(), но добавьте:
@top-left {
content: url("/images/300x50.png");
transform: scale(0.8); /* Подгоните под бокс */
transform-origin: top left;
background-color: thistle;
}
Масштабирует с пропорциями, но требует ручного расчета (из Stack Overflow). Плюс translate() для позиционирования. Работает в Chrome, но менее гибко — отступы через padding на боксе.
object-fit: cover? Только если обернуть в div вне @page, но для margin boxes — нет. В обычном @media print img { object-fit: contain; max-height: 90%; } это огонь, как в классическом ответе по object-fit.
Но background — король для print CSS.
Настройка отступов и сохранения aspect ratio в media print css
Отступы в 90% высоты? background-size: auto 90%; — высота 90% бокса, ширина по пропорциям. Центрирование: background-position: center center;. Если бокс меняется (динамические margins), используйте background-size: 90% auto для ширины.
Aspect ratio сохраняется всегда в contain/cover. Для cover (обрезка): background-size: cover; — заполнит бокс, но может подрезать края. В Chrome aspect-ratio из атрибутов img учитывается автоматически.
Добавьте @media print { body { -webkit-print-color-adjust: exact; } } — фоны точно напечатаются. Тестируйте на реальном принтере: PDF-экспорт в Chrome часто отличается.
А если логотип SVG? background-image поддерживает, масштабирование идеальное.
Практические примеры и код для css для печати
Полный HTML с разными логотипами:
<!DOCTYPE html>
<html>
<head>
<style>
@media print {
@page {
size: A4;
margin: 30mm 10mm 15mm 10mm;
@top-left {
content: "";
background-image: url("https://via.placeholder.com/600x100/FF0000/FFFFFF?text=Logo+600x100"); /* Большой */
background-size: auto 90%; /* 90% высоты */
background-repeat: no-repeat;
background-position: center;
background-color: thistle;
}
@top-center { content: ""; background-color: red; }
@top-right {
content: "Строка 1\AСтрока 2\AСтрока 3";
white-space: pre;
background-color: yellow;
}
}
* { -webkit-print-color-adjust: exact; }
}
</style>
</head>
<body>
<p>Контент документа. Логотип любого размера вписан!</p>
</body>
</html>
Замените URL на свой PNG/SVG. Работает для box-sizing border-box margin — бокс остается стабильным. Масштабируйте под A3? Измените size и margins.
Проблемы в Chrome? Обновитесь до 120+ и проверьте флаги chrome://flags/#print-with-background.
Источники
- Controlling size of image in CSS page margin boxes — Решение с background-image и contain для print CSS в Chrome: https://stackoverflow.com/questions/79897790/controlling-size-of-image-in-css-page-margin-boxes
- How to force image resize and keep aspect ratio — Применение object-fit contain и max-height для изображений: https://stackoverflow.com/questions/12991351/how-to-force-image-resize-and-keep-aspect-ratio
- CSS Paged Media Module Level 3 — Спецификация margin boxes и ограничения content в @page: https://www.w3.org/TR/css-page-3/
- CSS @page margin at-rule image — Масштабирование через transform scale в margin boxes: https://stackoverflow.com/questions/77669560/css-page-margin-at-rule-image
- Print margins — Поддержка margin boxes в Chrome и отладка print CSS: https://developer.chrome.com/blog/print-margins
Заключение
В CSS печать margin boxes — background-image с background-size: contain или auto 90% решает все: логотип масштабируется, пропорции целы, отступы есть. Забудьте content: url() — оно для простых случаев. Тестируйте в Chrome Print Preview, и ваша отчетность/инвойсы засияют. Если динамические изображения — подумайте о JS-генерации стилей. Готово к печати!
В margin boxes @page при CSS печать используйте background-image вместо content: url() для масштабирования изображения с object-fit: contain. Установите content: "", background-size: contain, background-repeat: no-repeat, background-position: center. Это сохраняет aspect ratio, вписывая изображение в бокс (масштабирует вверх маленькие изображения). В Chrome включите “Показывать фоновые изображения” или используйте Puppeteer с printBackground: true. Фон thistle поможет визуализировать бокс.

Для масштабирования изображений с сохранением пропорций примените object-fit: contain, max-width: 100%, max-height: 100%, width: auto, height: auto. В print CSS это работает для обычных <img>, но не напрямую в margin boxes @page. Альтернатива — background-size: contain в родительском контейнере или <div class="image"> с background-image и background-position: center. В Chrome 79+ учитывается aspect-ratio из атрибутов width/height для предотвращения скачков layout.
Спецификация CSS Paged Media не поддерживает max-width, object-fit или свойства object-fit CSS для content: url() в margin boxes @page — изображение вставляется в натуральную величину и обрезается. Размер боксов определяется margin @page (например, top-left — пересечение margin-top/left). Для print CSS в Chrome управляйте размером бокса через padding или высоту, но изображение не масштабируется автоматически. Рекомендуется предобработать изображение или использовать background-image.
- Ограничения: Нет автоматического масштабирования.
- Совет: Используйте фоновые изображения для контроля.
В margin boxes @page примените transform: scale(2.2) и width: 68mm к боксу с content: url() для масштабирования в print CSS. Добавьте translate(42mm,13mm), margin-top/bottom для позиционирования. Это работает в форматтерах вроде Antennahouse, но в Chrome может требовать тестирования. Сохраняет aspect ratio, позволяет отступы; поместите изображение в папку HTML для локального доступа.
Пример кода:
@top-left {
content: url(logo.png);
transform: scale(2.2) translate(42mm,13mm);
width: 68mm;
}
Margin boxes в @page определяются размерами margin (например, top: 30mm). В Chrome с версии 81+ поддержка print CSS полная, но масштабирование изображений в боксах требует CSS-свойств внутри @top-left. Нет прямой поддержки object-fit: cover; используйте background-size или размеры бокса для box-sizing: border-box. Тестируйте в диалоге печати Chrome.
- Угловые боксы: Фиксированный размер.
- Совет:
background-size: auto 90%для 90% высоты с отступами.