Что делает конвертер HTML в PDF
Конвертер HTML в PDF берёт любой HTML, который у тебя есть — вставленную разметку, загруженный .html или публичный URL — и превращает в скачиваемый PDF. Страница рендерится в скрытый canvas через html2canvas, плиткой укладывается на страницы PDF через jsPDF и отдаётся одним файлом. Выбери A4 или Letter, книжную или альбомную ориентацию и поля. Всё происходит в браузере. Ничего не загружается.
Будем честны про сделку. html2canvas реализует подмножество CSS на JavaScript — читает вычисленные стили с DOM и рисует их на canvas. Частое берёт хорошо: цвета, шрифты, отступы, рамки, фоны, простое позиционирование, базовый flexbox. Спотыкается на крайних случаях: сложные grid-раскладки, subgrid, выравнивание по baseline, gap в процентах внутри flex-контейнеров, некоторые вычисления вёрстки на кастомных свойствах. Для пиксель-в-пиксель встроенное «Печать → Сохранить как PDF» в браузере выигрывает — там настоящий движок. Наш инструмент — для случая, когда сырой HTML на руках и нужен PDF без открытия вкладки.
Как пользоваться
У виджета три режима ввода. Бери тот, что подходит твоей ситуации.
- Выбери режим. «Вставить HTML» подходит для любой разметки, которая у тебя уже есть. «Загрузить .html» принимает локальный файл. «Из URL» забирает публичную страницу (большинство упадёт на CORS — см. ниже).
- Задай размер страницы (A4 или Letter), ориентацию (книжная или альбомная) и поля (0, 10, 20 или 40 мм). По умолчанию A4 / книжная / 20 мм.
- Нажми «Конвертировать в PDF». HTML рендерится в скрытый div, html2canvas снимает его на 2× для резкости, jsPDF выкладывает результат на нужное количество страниц.
- Нажми «Скачать». Имя файла выводится из источника: вставленный HTML →
webpage.pdf, загруженный файл → его имя, URL → из хоста (example.com→example-com.pdf).
Ничего из твоего HTML не попадает на сервер, который мы контролируем. Режимы «Вставить» и «Загрузить» полностью локальны — открой вкладку Network во время конвертации и увидишь ноль исходящих запросов. Режим URL делает ровно один запрос: твой браузер забирает указанный URL, ответ остаётся в памяти браузера.
Три режима ввода и когда брать какой
Каждый режим решает свою задачу. Правильный выбор сразу экономит время.
| Режим | Что принимает | Работает на | Лучше для |
|---|---|---|---|
| Вставить HTML | Любая разметка в текстовой области | Всё (разметка уже локальна) | Email-шаблоны, фрагменты CMS, выгруженные отчёты, всё, что можно скопировать-вставить |
| Загрузить .html | Локальный .html файл | Всё (файл уже локален) | Самостоятельные HTML-отчёты, сгенерированные счета, выгруженные ноутбуки |
| Из URL | Публичный URL с разрешающим CORS | Примерно 5% публичных URL (CORS-разрешающие точки, dev-окружения, свои сайты) | Быстрые fetch из API, отдающих HTML, или со своих сайтов, где ты управляешь заголовками |
Если ты попробовал режим URL и получил ошибку, ты упёрся в Cross-Origin Resource Sharing — это защитная функция браузера, а не баг, который мы можем починить. Универсальный обход: открой URL в обычной вкладке, правый клик → «Просмотр кода страницы» (или DevTools → Elements → «Скопировать outerHTML» с тега <html>, если страница строится JS), вставь в «Вставить HTML». HTML теперь локальный, CORS неприменим, конверсия идёт.
Разбор примера с реальными цифрами
Допустим, у тебя HTML-шаблон email — маркетинговое объявление, 1200 слов основного текста, две картинки в шапке, кнопка призыва к действию, подвал со ссылками на соцсети. Примерно 18 КБ HTML и 240 КБ встроенных картинок, всё в одном .html с одним блоком <style> в начале.
При A4 / книжной / 20 мм: конверсия — 2,5 секунды. На выходе 1,3 МБ на 3 страницах. Геро-картинка резкая, основной текст читается чисто, кнопка сохраняет форму и цвет, логотипы подвала рендерятся в нужном размере. Единственная видимая разница от исходника: hover-состояние кнопки не захвачено (мы рендерим покоящийся DOM, hover не симулируется), и flex-wrap подвала перенёс одну иконку на вторую строку, потому что html2canvas немного по-другому измерил flex-gap.
При A4 / альбомной / 10 мм: то же содержимое, 2 страницы вместо 3, чуть шире строки. 1,1 МБ. Letter / книжная / 20 мм: 3 страницы, 1,3 МБ, строки переносятся на тех же словах, что и A4 — колонка почти такой же ширины.
Переверни вход: одностраничное SPA-приложение, отрендеренное React и поданное с localhost:3000. Режим URL забирает загрузочный HTML и пропускает каждый компонент, который React должен был смонтировать — на выходе пустой PDF со спиннером загрузки. Правильный ход: открой приложение во вкладке, дай ему отрендериться, скопируй outerHTML с отрендеренного DOM, вставь в «Вставить HTML». PDF теперь совпадает с тем, что было на экране.
Как это сравнивается с Adobe Acrobat, SmallPDF, iLovePDF
Известные сервисы HTML в PDF — веб-версия Adobe Acrobat, URL-to-PDF от SmallPDF, HTML-to-PDF от iLovePDF, PDFCrowd, DocRaptor — все работают на сервере, что правильная архитектура для верности, но неправильная для приватности и скорости.
Эти сервисы обычно запускают headless Chromium у себя на сервере. Ты даёшь им URL или HTML; они поднимают браузер, переходят к контенту, гоняют JS, ждут шрифтов и картинок, потом вызывают print API Chrome. Выход пиксель-в-пиксель, потому что вышел из настоящего браузера. Минусы: твой HTML и любые данные в нём улетают в их инфраструктуру и оседают в логах; ждёшь в очереди вместе с чужими задачами рендера; обычно есть дневная бесплатная квота и платный тариф от $9–15/мес; и большинство просит аккаунт после второго файла.
Мы делаем меньше, в твоём браузере, бесплатно. Сделка честная: сложный CSS может рендериться неидеально, JS не выполнится (скрипты в контейнере off-screen рендера мы не запускаем), веб-шрифты, которым нужен CORS-разрешённый fetch, могут упасть на дефолтные, а очень длинные страницы могут давать большой выход. Для email-шаблона, выгруженного отчёта, превью CMS или сгенерированного счёта — частых задач HTML-в-PDF — наш инструмент в самой точке. Для отшлифованного маркетингового сайта, который надо архивировать байт в байт, бери «Печать → Сохранить как PDF» в Chrome или один из серверных сервисов, если скриптование того стоит.
Что html2canvas умеет и не умеет
html2canvas — движок, делающий визуальную работу, и знание его границ экономит головную боль.
Работает хорошо:
- Стандартные свойства CSS. Color, background, font, padding, margin, border, border-radius, box-shadow, opacity — рендерятся так же, как в настоящем браузере.
- Инлайновые стили и теги <style> в том же документе. Если CSS внутри HTML, который ты вставляешь, всё работает. Всегда встраивай CSS в единый блок <style> в начале — для лучших результатов.
- Базовый flexbox. Раскладки в строку и колонку, простое выравнивание, gap, базовые justify-content и align-items — нормально для подавляющего большинства раскладок.
- Inline- и block-картинки. JPEG и PNG, встроенные в HTML или по абсолютному URL с серверов, разрешающих CORS, рендерятся правильно.
Работает неидеально:
- CSS Grid. Простые сетки с явными треками обычно рендерятся. Авторазмещение, subgrid, именованные области и grid-template-areas часто нет.
- CSS-переменные. Учитываются при прямом чтении, но некоторые цепочки вычисленных значений ломаются.
- Крайние случаи flexbox. flex-wrap с детьми разной высоты, выравнивание по baseline, gap в процентах, flex-basis: 0% — иногда раскладка чуть другой размерности.
- Веб-шрифты с внешних доменов. Если CORS-заголовки шрифта разрешают кросс-домен, рендерится; иначе падает на системный serif.
Не работает:
- JavaScript. Скрипты в контейнере рендера не выполняются. Если HTML полагается на JS для вставки контента (графики, SPA, что угодно динамическое), сначала захвати отрендеренный DOM в DevTools и вставь его.
- iframe. Содержимое iframe живёт в другом контексте документа, который html2canvas прочитать не может.
- Состояния :hover, :focus, :active. DOM захватывается в покое. Hover-эффекты не симулируются.
- Анимации. Снимается один кадр. CSS-переходы и keyframe-анимации не появляются.
Когда встроенное «Печать → Сохранить как PDF» в браузере — правильный ответ
В Chrome, Firefox, Safari и Edge встроенная опция «Сохранить как PDF» в диалоге печати. Использует настоящий движок рендера (Blink, Gecko, WebKit), отсюда идеальная верность по grid, flexbox, веб-шрифтам, JS-контенту. Также обрабатывает твои куки авторизации — страницы за логином рендерятся правильно, потому что диалог печати в том же контексте, что страница.
Загвоздка: надо открыть страницу во вкладке и пройти диалог печати. Нормально для одного-двух PDF. Утомительно для пакетных задач или для HTML, полученного через API или экспорт CMS. Наш инструмент — для них: сырой HTML на руках, нужен PDF, не хочется поднимать вкладку. Встроенное «Печать → Сохранить как PDF» — правильный инструмент для всего остального.
Дерево решений: пиксель-в-пиксель, страница открыта во вкладке → «Печать → Сохранить как PDF». Сырой HTML на руках, «достаточно хороший» выход, без загрузки → этот инструмент. Пиксель-в-пиксель и надо скриптовать на сотнях URL → headless Chromium через Puppeteer или один из платных сервисов.
Похожие PDF-инструменты
Конвертер HTML в PDF пары с несколькими другими по пути к готовому документу:
- Изображения в PDF — собрать папку картинок в один PDF. Часто правильный инструмент, если твой «HTML» на самом деле пачка скриншотов.
- Объединить PDF — соединить выход HTML-в-PDF с другими PDF (титульное письмо, приложение, подписанная страница) в один файл.
- Сжатие PDF — если выход неожиданно большой (длинные страницы и куча картинок могут дать 5–10 МБ), прогони через сжатие.
- PDF в PNG — отрисовать каждую страницу PDF как картинку, когда PDF уже на руках.
- Word в PDF — если на самом деле у тебя .docx и ты случайно зашёл к HTML-инструменту, это правильный сосед.
Microapp шипит каждый PDF-инструмент в браузере. 10% от каждого доллара выручки идут на благотворительность — сверху, с аудитом раз в квартал — значит, инструменты должны эти 10% заработать, то есть реально работать без зарывания пользователя в апселл.
Частые вопросы
Почему мой URL не работает?
Cross-Origin Resource Sharing (CORS). Когда браузер забирает URL из JavaScript на другом домене, целевой сервер должен явно это разрешить через заголовки. Почти ни один публичный сайт этого не делает. Это защитная функция браузера, а не то, что мы можем обойти на странице. Надёжный путь: открой URL в обычной вкладке, посмотри исходник (правый клик → «Просмотр кода страницы»), скопируй HTML и вставь в режим «Вставить HTML». Это полностью обходит CORS, потому что HTML теперь локальный. Страницы под логином тоже не сработают через URL — им нужны твои сессионные куки, которые наш fetch одолжить не может.
Сохраняется ли CSS?
В основном да, но не всё. html2canvas читает вычисленные стили с отрендеренного DOM и рисует их на canvas. Стандартные цвет, шрифт, отступы, рамка, фон и базовое позиционирование работают. Инлайновые стили, теги <style> внутри HTML и стили, применённые через классы из твоего стайлшита, — всё участвует. Загвоздка: если HTML ссылается на внешние стайлшиты на других доменах, они могут быть заблокированы CORS как и fetch URL — тогда отрендеренный результат использует дефолтные стили для этих правил. Для лучших результатов встрой CSS в блок <style> в начале HTML, который вставляешь.
А flexbox и grid?
Flexbox: в основном работает для частых случаев (раскладки в строку/колонку, базовое выравнивание). Крайние случаи — flex-wrap со смешанным содержимым, выравнивание по baseline, gap в процентах — иногда рендерятся с неверными размерами. Grid: частичная поддержка. Простые сетки с явными треками строк/колонок обычно работают; авторазмещение, subgrid и именованные области — часто нет. CSS-переменные (--my-var) учитываются при прямом чтении, но ломают некоторые расчёты вёрстки. Если документ сильно зависит от современной вёрстки, бери встроенное «Печать → Сохранить как PDF» (Chrome, Firefox, Safari поддерживают) — там настоящий движок рендера, а не JS-реализация.
А JavaScript?
Не выполняется. Мы ничего не вырезаем, но html2canvas снимает DOM, как он есть в момент передачи, а скрипты в контейнере off-screen рендера мы не запускаем. Если HTML полагается на JS для вставки контента, сначала прогони этот JS в обычной вкладке, посмотри код отрендеренного DOM (DevTools → Elements → правый клик на <html> → «Скопировать outerHTML») и вставь сюда пост-JS версию. Графики, SPA, всё, что строит себя через JS — снимай отрендеренный DOM, потом конвертируй.
Чем это отличается от встроенного «Печать → Сохранить как PDF» в браузере?
«Печать → Сохранить как PDF» использует настоящий движок раскладки браузера (Blink в Chrome, WebKit в Safari, Gecko в Firefox), поэтому идеально берёт всё: flexbox, grid, веб-шрифты, JS-контент, аккуратную типографику. Загвоздка: надо сначала открыть страницу во вкладке и пройти диалог печати. Наш инструмент — для случая, когда у тебя сырой HTML на руках (тестируемый email-шаблон, выгруженный отчёт, фрагмент из CMS) и нужен PDF без открытия в браузере. Печать — для верности, мы — для скорости и автоматизации со входом сырым HTML.
Мой HTML правда не загружается?
Верно для «Вставить HTML» и «Загрузить .html» — оба работают полностью в браузере без исходящих запросов. Для «Из URL» есть ровно один исходящий запрос: твой браузер забирает URL, который ты ввёл, и всё; полученный HTML остаётся в памяти и до наших серверов не доходит. Проверь во вкладке Network. PDF строится локально и скачивается через blob-URL.
Почему выход больше, чем я ожидал?
Потому что страница растрируется в canvas, затем перекодируется в JPG при попадании в PDF. Длинная страница с кучей картинок легко превращается в многомегабайтный PDF из нескольких килобайт исходного HTML. Если размер важен, прогони результат через наше «Сжатие PDF» — для картинок-heavy выхода часто срезает 50–70%.
Можно ли конвертировать страницу под паролем или за логином?
Не через режим URL — наш fetch не имеет доступа к твоим кукам и заголовкам авторизации. Обход: открой страницу в обычной вкладке (где ты залогинен), открой DevTools → Elements, правый клик на <html> → «Скопировать → outerHTML», вставь в «Вставить HTML». Так захватывается полностью отрендеренная авторизованная страница, включая любой DOM, который JS построил после логина.