Веб

Масштабирование изображений в CSS @page margin boxes при печати

Как вписать логотип любого размера в @top-left бокс при CSS печать в Chrome с сохранением пропорций и отступами (90% высоты). Решение через background-image, object-fit contain и print css. Примеры кода и скриншоты проблем.

6 ответов 2 просмотра

Как контролировать размер изображения в CSS @page margin boxes при печати в Chrome, чтобы оно масштабировалось под размер бокса с сохранением пропорций?

Пример кода:

html
<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).

Скриншот проблемы: логотип 600x100 обрезается справа в @top-left при печати

Содержание


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, чтобы избежать сюрпризов на бумаге.

Скриншот проблемы: логотип 300x200 выходит за нижнюю границу @top-left, перекрывая контент

Проблема масштабирования изображений в 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; — и логотип центрируется с отступами.

Вот обновленный код на базе вашего примера:

css
@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 }.

Скриншот верха страницы A4 при печати: логотип 300x50 идеально вписан в @top-left (фиолетовый фон), пустой @top-center (красный), текст в @top-right (жёлтый)

Альтернативы: transform scale и object fit cover для Chrome

Если background не подходит (редко), попробуйте transform: scale(). Оставьте content: url(), но добавьте:

css
@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 с разными логотипами:

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.


Источники

  1. 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
  2. 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
  3. CSS Paged Media Module Level 3 — Спецификация margin boxes и ограничения content в @page: https://www.w3.org/TR/css-page-3/
  4. CSS @page margin at-rule image — Масштабирование через transform scale в margin boxes: https://stackoverflow.com/questions/77669560/css-page-margin-at-rule-image
  5. 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-генерации стилей. Готово к печати!

P

В 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 поможет визуализировать бокс.

Успешный результат: логотип идеально вписан в @top-left бокс при печати Проблема обрезки логотипа 600x100 справа в @top-left
S

Для масштабирования изображений с сохранением пропорций примените 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.

W3C / Портал стандартов

Спецификация 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.

  • Ограничения: Нет автоматического масштабирования.
  • Совет: Используйте фоновые изображения для контроля.
H

В margin boxes @page примените transform: scale(2.2) и width: 68mm к боксу с content: url() для масштабирования в print CSS. Добавьте translate(42mm,13mm), margin-top/bottom для позиционирования. Это работает в форматтерах вроде Antennahouse, но в Chrome может требовать тестирования. Сохраняет aspect ratio, позволяет отступы; поместите изображение в папку HTML для локального доступа.

Пример кода:

css
@top-left {
 content: url(logo.png);
 transform: scale(2.2) translate(42mm,13mm);
 width: 68mm;
}
Rachel Andrew / Специалист по CSS и веб-стандартам

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% высоты с отступами.
Авторы
P
Разработчик
S
Разработчик
H
Технический писатель
Rachel Andrew / Специалист по CSS и веб-стандартам
Специалист по CSS и веб-стандартам
Источники
W3C / Портал стандартов
Портал стандартов
Проверено модерацией
НейроОтветы
Модерация
Масштабирование изображений в CSS @page margin boxes при печати