I am creating a stylesheet for print media that includes an inline SVG as the content of an element's pseudo-class (i.e., ::before
, ::after
).
When testing in Chrome, it seems to work just fine, but when the page is first loaded in Firefox and Safari, the SVG element does not appear in the print preview. It then appears on all subsequent attempts.
I am not exactly sure what is going on, but if I had to guess, my conjecture would be: when page hasn't been cached there is latency rendering the pseudo-element that is happening concurrently to the browser creating the print page.
I am very curious to know why this is happening, and if there is any solution where an SVG pseudo-element can be used reliably.
Here is a stripped down code example. Please see if you can reproduce this issue:
var button = document.querySelector('button');
button.addEventListener('click', function () {
window.print();
});
div {
text-align: center;
}
button {
margin: 2em;
padding: 1em 2em;
}
@media print {
button {
display: none;
}
div::before {
content: 'Pseudo-elements';
font-weight: bold;
margin-top: 1em;
}
div::after {
position: relative;
display: block;
margin-top: 1em;
content: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='100' height='100'><circle cx='50' cy='50' r='50' /></svg>");
}
}
<div>
<button>
print
</button>
</div>
I can repro.
It seems to be a bug with the loading of the svg, I guess it would be the same with any image.
One workaround is to load it outside of your @print rules with display: none
:
var button = document.querySelector('button');
button.addEventListener('click', function() {
window.print();
});
div {
text-align: center;
}
button {
margin: 2em;
padding: 1em 2em;
}
div::after {
display: none;
content: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='100' height='100'><circle cx='50' cy='50' r='50' /></svg>");
}
@media print {
button {
display: none;
}
div::before {
content: 'Pseudo-elements';
font-weight: bold;
margin-top: 1em;
}
div::after {
opacity: 1;
position: relative;
display: block;
margin-top: 1em;
}
}
<div>
<button>
print
</button>
</div>
An other one would be to preload it via js before hand.