Thanks @jasssonpet for his solution!
I ran into a problem that Vue JS can't v-bind
to css
outside of root
, like this
@media print {
@page {
size: A4 v-bind(printSize); // <-- doesn't work!
}
}
I need to manage orientation & margins independently, maybe more rules at future.
Therefore, I rewrote and updated that code for embedding in other code and frameworks.
at utils/customizePageStyle.js
let pageStyle;
const pageRules = {};
const pageHasRules = () => !!Object.keys(pageRules).length;
const addCustomCssStylesheet = async () => {
pageStyle = document.createElement('style');
document.head.appendChild(pageStyle);
};
export const cleanPageRules = () => pageStyle.innerHTML = `@page {}`;
const writePageRules = async () => {
if (!pageStyle) await addCustomCssStylesheet();
if (!pageHasRules) {
cleanPageRules();
return;
}
let styleTxt = '@media print { @page {';
Object.keys(pageRules).forEach(ruleName => {
const ruleTxt = pageRules[ruleName];
styleTxt += `${ruleName}: ${ruleTxt} !important; `;
});
styleTxt += '} } ';
pageStyle.innerHTML = styleTxt;
};
const addPageRule = ({ruleName, ruleValue}) => pageRules[ruleName] = ruleValue;
const asyncAddPageRule = async rule => {
addPageRule(rule);
await writePageRules();
};
const addPageRules = async rules => {
rules.forEach(rule => addPageRule(rule));
await writePageRules();
};
const delPageRule = ruleName => pageRules[ruleName] = null;
const asyncDelPageRule = async ruleName => {
delPageRule(ruleName);
await writePageRules();
};
const delPageRules = async ruleNames => {
ruleNames.forEach(ruleName => delPageRule(ruleName));
pageHasRules ? await writePageRules() : cleanPageRules();
};
export const setPageRules = {
add: asyncAddPageRule,
adds: addPageRules,
del: asyncDelPageRule,
dels: delPageRules,
clean: cleanPageRules
};
Vue Js using example:
<script setup>
import { setPageRules } from '@/utils/customizePageStyle.js';
const printSize = computed(()=> yourCondition1 ? 'A4 portrait' : 'A4 landscape');
const printMargin = computed(()=> yourCondition2 ?
'1cm 1cm 1cm 2cm' : '24pt 24pt auto 18pt');
onMounted(()=> {
window.addEventListener('beforeprint', async e => {
await setPageRules.adds([
{ruleName: 'size', ruleValue: printSize.value},
{ruleName: 'margin', ruleValue: printMargin.value},
]);
});
window.addEventListener('afterprint', e => setPageRules.clean());
}
</script>
<style>
@media print {
body {
margin: 0px; // don't work with it, I don't know why
}
}