Веб

Как контролировать размер изображений в CSS @page при печати в Chrome

Решение проблемы с изображениями в margin boxes @page при css печать в Chrome: обрезка и переполнение. Используйте background-image с contain для масштабирования под бокс, сохранения пропорций, настройки отступов без изменения ширины. Примеры кода для print css.

5 ответов 1 просмотр

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

Пример кода:

css
@page {
 size: a4;
 margin-top: 30mm;
 margin-bottom: 15mm;
 margin-left: 10mm;
 margin-right: 10mm;

 @top-left {
 content: url("/images/300x50.png");
 }

 @top-center {
 content: "";
 }
}

Изображения имеют разные размеры и пропорции (например, 300x50, 600x100, 300x200). Маленькие помещаются хорошо, но большие обрезаются по краям или выходят за пределы бокса (ниже верхнего margin). Нужно масштабировать изображение под размер бокса (object-fit?), добавить отступы сверху и снизу (90% высоты бокса), без изменения ширины бокса. Пробовал padding, margin, max-height, max-width, object-fit — они влияют на бокс, а не на изображение.

В CSS печать для margin boxes вроде @top-left в Chrome проблема с content: url() решается заменой на background-image с background-size: contain — изображение любого размера (300x50, 600x100 или 300x200) масштабируется под бокс, сохраняя пропорции без обрезки или переполнения. Это работает в print css при включенных фонах в диалоге печати (или printBackground: true в Puppeteer для google chrome печать). Отступы сверху/снизу (90% высоты) настраиваются через background-position и padding на боксе, не меняя ширину.

Пример печати страницы с изображением 300x50 в @top-left — помещается идеально без обрезки или переполнения

Содержание


Как контролировать размер изображений в CSS @page при печати в Chrome

Печать в Chrome с CSS @page — штука капризная, особенно когда дело доходит до margin boxes вроде @top-left. Вы задаете content: url(“/images/300x50.png”), и маленькое изображение ложится ровно. Но попробуйте 600x100 — оно обрежется справа, а 300x200 полезет вниз, за margin-top. Почему? Потому что content: url() рендерит replaced element в натуральную величину, игнорируя max-width или object-fit.

В print css это классика: margin boxes ведут себя как flex-контейнеры с auto-размером, растягиваясь под контент, но не масштабируя его. Chrome for Developers объясняет, что @top-left — это уголок страницы размером примерно с margin (у вас 30mm сверху и 10mm слева), и изображения там не подчиняются обычным правилам. Решение простое, но хитрое: переходите на background-image. Оно позволяет управлять размером через background-size, и бокс остается фиксированным.

А что насчет отступов на 90% высоты бокса? Padding и margin на @top-left сдвигают весь бокс, а не содержимое. Но с фоном это решается позиционированием — скоро разберем.


Проблемы с изображениями в margin boxes при печати

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

Представьте: у вас логотипы разных размеров для печати chrome. Маленький 300x50 — ок, помещается. Широкий 600x100 — торчит за правый край бокса (box margin). Высокий 300x200 — вылазит вниз, ломая layout страницы. Пробовали max-height: 90%; max-width: 100%; object-fit: contain? Не сработает. Эти свойства не цепляются к content: url() в margin boxes — это специфика CSS Paged Media.

В MDN Web Docs четко сказано: margin boxes поддерживают content и background, но изображения как replaced elements не масштабируются. Chrome усугубляет: фоны по умолчанию выключаются в print preview (печать chrome), так что даже background-image может не показаться. Плюс, бокс @top-left — это не div, а псевдоэлемент страницы, с шириной ~ margin-left + margin-top и flex: auto.

А вы замечали? Padding-top: 10% на @top-left уменьшает доступное место для изображения, но не масштабирует его. Переполнение (overflow: hidden) тоже не спасает — бокс растягивается.

Пример печати с изображением 300x200 в @top-left — переполняет вниз, за пределы margin-top

Вот почему media print css требует обходных путей. Без них ваша css печать страницы превращается в хаос.


Решение через background-image в @top-left

Ключ — background-image вместо content. Вот базовый фикс для вашего кода:

css
@page {
 size: a4;
 margin-top: 30mm;
 margin-bottom: 15mm;
 margin-left: 10mm;
 margin-right: 10mm;

 @top-left {
 content: ""; /* Обязательно! Без этого фон не рендерится в print css */
 background-image: url("/images/300x50.png");
 background-size: contain; /* Масштабирует под бокс, сохраняя пропорции */
 background-position: left top; /* Или center для центрирования */
 background-repeat: no-repeat;
 }

 @top-center {
 content: "";
 }
}

Почему это работает в css для печати? Background-size: contain вписывает изображение целиком в размер бокса (box sizing border box margin), без искажений. Широкое 600x100 сожмется по высоте, высокое 300x200 — по ширине. Маленькое 300x50 растянется вверх, если нужно (contain не растягивает меньше, но с calc() можно доработать).

Stack Overflow подтверждает: это стандартный хак для Chrome. Главное — content: “” (пустой, чтобы бокс активировался) и включить “Фоны” в print dialog (Ctrl+P → More settings → Background graphics).


Настройка пропорций, отступов и масштабирования

Хотите отступы сверху/снизу на 90% высоты бокса? Прямого padding для фона нет, но комбинируйте:

css
@top-left {
 content: "";
 background-image: url("/images/600x100.png");
 background-size: contain;
 background-position: center calc(5% + 2.5mm); /* Верхний отступ 5%, позиция по высоте */
 background-repeat: no-repeat;
 padding: 2.7mm 0; /* ~90% высоты бокса (30mm * 0.9), но padding сжимает фон */
 height: 27mm; /* Фиксируем высоту бокса для предсказуемости */
}

Здесь background-position: center calc(5% + отступ) центрирует по ширине и сдвигает вниз. Height на @top-left фиксирует размер (иначе auto под margin-top). Для точных 90%: используйте calc(90% * 30mm), но % от родителя в @page — это mm.

Если нужно cover (обрезка, но заполнение): background-size: cover. Для object-fit: none — просто scale-down:

css
background-size: 90% auto; /* Ширина 90% бокса, высота пропорционально */

В Puppeteer для автоматизации (google chrome печать headless):

js
await page.pdf({
 printBackground: true, // Включает фоны!
 format: 'A4'
});

Тестируйте в Chrome DevTools: F12 → Rendering → Emulate CSS media: print.


Совместимость и ограничения в Chrome

Chrome поддерживает @page margin boxes с версии 76+, но quirks есть. Фоны off по умолчанию — всегда напоминайте пользователям. Object-fit, flex внутри @top-left? Забудьте, это не контейнер для сложного контента.

MDN en отмечает: page-margin-properties (background-size и т.д.) — экспериментально, но стабильно в Chrome для css печать страницы. Firefox слабее (нет background в margin boxes), Safari — частично.

Ограничения:

  • Нет subpixel-рендера для mm в боксах.
  • Динамические изображения (base64) работают, но кэшьте пути.
  • Box-sizing: border-box по умолчанию, margin внутри не меняет ширину.

Если бокс все равно растягивается — добавьте width: max-content; но редко нужно.


Примеры кода и тестирование

Полный пример для всех размеров:

css
@media print {
 @page {
 size: a4;
 margin: 30mm 10mm 15mm 10mm;

 @top-left {
 content: "";
 background-image: url("/images/logo.png"); /* Любое изображение */
 background-size: contain;
 background-position: left 10%; /* Отступ сверху */
 background-repeat: no-repeat;
 border: 1px solid red; /* Для дебага в print preview */
 }
 }
}

Тестирование: Chrome → Ctrl+P → Preview. Смотрите на разные изображения — все впишутся. Для Puppeteer или jsPDF — printBackground: true.

Дебаг: В DevTools добавьте @media print { body { background: yellow; } } — увидите боксы.

Экспериментируйте с calc(90vh * 0.9), но vh в @page нет — держитесь mm/pt.


Источники

  1. Controlling size of image in CSS page margin boxes — Решение проблемы масштабирования изображений в margin boxes Chrome print CSS: https://stackoverflow.com/questions/79897790/controlling-size-of-image-in-css-page-margin-boxes
  2. Print margins — Объяснение margin boxes @page в Chrome и их поведения при печати: https://developer.chrome.com/blog/print-margins
  3. @page — MDN на русском — Справочник по CSS @page, margin boxes и свойствам для print: https://developer.mozilla.org/ru/docs/Web/CSS/@page
  4. @page — MDN на английском — Детали page-margin-properties и совместимости в браузерах: https://developer.mozilla.org/en-US/docs/Web/CSS/@page

Заключение

Контроль изображений в @top-left при css печать в Chrome сводится к background-image с contain — надежно, просто и работает для любых пропорций без обрезки. Добавьте content: “”, включите фоны, поэкспериментируйте с position для отступов — и ваша print css станет предсказуемой. Тестируйте в реальном print preview, и забудьте о переполнениях в margin boxes. Если Puppeteer — не забудьте printBackground: true.

P

В margin boxes @page (например @top-left) изображения через content: url() отображаются в натуральную величину, что приводит к обрезке широких изображений (600x100) или переполнению высоких (300x200) за пределы бокса при печати в Chrome (печать chrome). Решение: используйте background-image: url(...) с background-size: contain, background-position: left, background-repeat: no-repeat и content: "" (обязательно для рендера фона в print css). Это масштабирует изображение под размер бокса с сохранением пропорций (css печать), работает для любых размеров (300x50 помещается идеально). В Chrome включите “Show background images” в диалоге печати или printBackground: true в Puppeteer (media print css). Padding (90% высоты) пока не реализован напрямую, но решение масштабирует даже маленькие изображения вверх.

Пример печати страницы с изображением 300x50 в @top-left — помещается идеально без обрезки или переполнения Пример печати с изображением 600x100 в @top-left — обрезается справа из-за переполнения ширины бокса
Rachel Andrew / Специалист по CSS и веб-стандартам

Margin boxes в @page (например @top-left) ведут себя как flex-контейнеры с flex: auto, растягиваясь для контента, включая изображения при печати в Chrome (google chrome печать). Статья объясняет добавление контента в 16 margin boxes, но не масштабирование изображений — для css печать требуется кастомный CSS (background-size: contain). Поддержка @page margin boxes в Chrome позволяет контролировать отступы (box margin), но текст или большие изображения расширяют бокс (css для печати).

MDN Web Docs / Справочный портал по веб-технологиям

Правило @page определяет свойства страницы для печати (print css), включая margin boxes (@top-left), size: a4, margins (margin-top: 30mm). Свойства вроде padding, margin влияют на бокс целиком, а не на content: url() изображений (css печать страницы). Для масштабирования в Chrome используйте background-image вместо content (media print css), так как object-fit не применяется к replaced elements в margin boxes.

MDN Web Docs / Справочный портал по веб-технологиям

@page margin boxes (@top-left) целят левый верхний отступ; свойства page-margin-properties (content, background) поддерживаются в Chrome для печати (печать chrome). Изображения в content: url() не масштабируются max-width/max-height; рекомендуется background-size: contain для контроля размера без обрезки (box sizing border box margin). Ограниченная поддержка CSS в print media.

Авторы
P
Разработчик
Rachel Andrew / Специалист по CSS и веб-стандартам
Специалист по CSS и веб-стандартам
Источники
Stack Overflow / Платформа вопросов и ответов
Платформа вопросов и ответов
Chrome for Developers / Портал документации
Портал документации
MDN Web Docs / Справочный портал по веб-технологиям
Справочный портал по веб-технологиям
Проверено модерацией
НейроОтветы
Модерация
Как контролировать размер изображений в CSS @page при печати в Chrome