🍘
ブラウザPDF印刷 + CSS調整で改ページ指定等のメモ
概要:
ブラウザ印刷でPDF出力する場合で。CSSで印刷領域の指定や、
改ページ位置の指定の例となります。
-
一般的なブラウザ仕様らしいので、CSS調整以外は不要で PDFレイアウト調整ができるそうでしたので
試してみました。 -
印刷時に、web画面の、共通ヘッダ、サイドバー、広告バナー等を対象外にして。
主要コンテンツのみ印刷する調整ができそうでした。 -
改ページは、カスタムタグのようなルール決めて、画面表示に div, hrタグ変換、クラス名指定後。
CSS適用する手順としました -
テストは、Next.js / SSGを、cloudflare.pages にデプロイ後、印刷テストしました。
構成
- chrome : 96以上
- CSS
- next.js 12
- node: 16
- cloudflare.pages
参考
- 関連URL
https://developer.mozilla.org/ja/docs/Web/CSS/page-break-before
https://developer.mozilla.org/ja/docs/Web/CSS/@media
プリント範囲の設定
- 下記の、青枠内を印刷する例です。(枠外は印刷しない)
印刷範囲設定、@media print
- 印刷時のみ。ヘッダ部分、ボタン等を非表示
class= hidden_print を、@media print の条件で。非表示(display: none)
@media print {
.hidden_print{
display: none;
}
}
- pdf印刷すると、ヘッダ等が非表示になり。コンテンツ部分が出力できました。
改ページ:page-break-before
- こちらは、自動で改行できません。
- 手動でカスタムタグを定義し、画面表示時に、page-break-beforeを適用
.pdf_next_page {
page-break-before: always;
}
- カスタム定義(例) 下記を、改ページ位置に設定
:::nextpage
- HRタグ等に、変換(next.js)
- 上記の page-break-before が適用され印刷時のみ。改ページ処理
<hr class="pdf_next_page" />
- 改ページのPDF出力例
手動で追加した改ページ位置で、ページ追加できました
- 参考の詳細画面コード: next.js
/src/pages/posts/[id].tsx
[id].tsx
/* pdf print css add */
import Head from 'next/head'
import React from 'react'
import Link from 'next/link';
import marked from 'marked'
import Layout from '../../components/layout'
import LibCommon from '../../libs/LibCommon'
import LibCms from '../../libs/LibCms'
//
export default function Page({ blog }) {
//console.log(blog)
return (
<Layout>
<Head><title key="title">{blog.title}</title></Head>
<div className="container bg-light">
<div className="hidden_print">
<Link href="/home" >
<a className="btn btn-light btnx-outline-orange mt-2">Back</a>
</Link>
<hr className="mt-2 mb-2" />
<div className="show_head_wrap">
<i className="bi bi-house-fill mx-2"></i> >
{blog.title}
</div>
</div>
<div className="card shadow-sm my-2">
<div className="card-body">
<h1>{blog.title}</h1>
Date: {blog.created_at}<br />
Category : {blog.category.name }
</div>
</div>
<div className="shadow-sm bg-white p-4 mt-2 mb-4">
<div id="post_item" dangerouslySetInnerHTML={{__html: `${blog.content}`}}>
</div>
</div>
</div>
<style>{`
div#post_item img{
max-width : 100%;
height : auto;
}
.show_head_wrap{ font-size: 1.4rem; }
.pdf_next_page {
page-break-before: always;
background-color: green;
border: none;
}
@media print {
.hidden_print{
display: none;
}
}
`}</style>
</Layout>
)
}
//
export const getStaticPaths = async () => {
const dt = LibCommon.formatDate( new Date(), "YYYY-MM-DD_hhmmss");
const url = process.env.MY_JSON_URL+ '?' + dt
const req = await fetch( url );
const json = await req.json();
const items = json.items
const paths = []
items.map((item, index) => {
let row = { params:
{ id: item.save_id }
}
paths.push(row)
})
//console.log(paths)
return {
paths: paths,
fallback: false
}
};
export const getStaticProps = async context => {
const id = context.params.id
//console.log(id)
const dt = LibCommon.formatDate( new Date(), "YYYY-MM-DD_hhmmss");
const url = process.env.MY_JSON_URL+ '?' + dt
const req = await fetch( url );
const json = await req.json();
let items = json.items
items = LibCommon.convert_items( items )
let item = LibCms.get_show_item( items, String(id) )
item.content = marked(item.content)
item = LibCms.get_post_itemOne(item , json.category_items)
//console.log(json.category_items )
return {
props: {
blog: item,
},
}
};
....
Discussion