Load external images in print media - css

A heading should have an image to the right of it only when a page is printed.
I declared following stylesheet:
#media print {
h1::after {
content: url( IMAGE_URL_HERE );
position: absolute;
top: 0;
right: 0;
}
}
The problem is that image won't appear in print preview (of any browser). If I, however, print preview dialog is closed and re-opened, image will then appear just fine.
You can try to reproduce it youself: http://jsbin.com/gevefivi
Is there anything I'm doing wrong or is it an expected behaviour?
UPDATE: I think it is related to race condition inside engine's print layout rendering because when I refer to a local image it is always displayed in Print Preview and is printed just fine.
UPDATE: Looks like print engine really doesn't wait before external resource in content: url() is loaded but generates PDF file for preview and that's why there is no image there if image fetch takes some time to finish. But it does send HTTP request and saves it locally for the next time. So that explains why it usually works fine when Print Preview is opened for the second time.
I tested it with following PHP file as an external resource:
<?php
sleep(5);
// Create a blank image and add some text
$im = imagecreatetruecolor(120, 20);
$text_color = imagecolorallocate($im, 233, 14, 91);
imagestring($im, 1, 5, 5, 'A Simple Text String', $text_color);
// Set the content type header - in this case image/jpeg
header('Content-Type: image/jpeg');
header("Cache-Control: no-store, no-cache, must-revalidate, max-age=0");
header("Cache-Control: post-check=0, pre-check=0", false);
header("Pragma: no-cache");
// Output the image
imagejpeg($im);
// Free up memory
imagedestroy($im);
It only returns an image in 5 seconds. To reproduce this issue make sure PHP file above is located on your local server or at worst in your local network. Refer to it in content: url() and open the Print Preview dialog. You'll not see the image. Close the dialog. Open the dialog and you'll still not see the image. Wait 2-3 seconds. Open it and you'll see the image as it is fetched and cached. If you remove the sleep(5); line you should see the image from the first time you open Print Preview dialog.
Still eager to know whether this is a bug or whether this is an expected behavior and if there is a working solution at the moment.

After hours of experimenting I came to conclusion that as of today web browsers just don't wait for any external resources specified in print-specific stylesheets to be fully downloaded before rendering the print-ready document.
So, seems like the only way to display external resources in print version of the page is to at least download them (either via html tags, screen stylesheets or javascript, doesn't really matter how) before user decides to print that page.
And, no, seems like this is not a bug, but rather a standard accepted by current major vendors.

Good point op,
I was in the same situation, I found a trick to preload image via CSS :
it is not the best way because I load images every time :/
If I take your code :
print.css
.h1:before {
content: url(IMAGE_URL_HERE);
}
screen.css
h1 {
background: url(IMAGE_URL_HERE) no-repeat -9999px -9999px;
//img not displayed but loaded
}
regards

Related

CSS Variable loading svg file multiple times

I am using variables in CSS/SCSS. I want to set a background (using an SVG file), but it is re-loading every time I navigate or perform some other action.
My -Variables.scss file:
:root {
--backgroundTheme: url('triangle-dark.svg') no-repeat;
}
$variables: (
--backgroundTheme: var(--backgroundTheme)
);
My styles.scss file:
#import "~assets/_variable";
body:before {
background-size: cover;
background: var(--backgroundTheme);
}
How can I avoid multiple times loading of this file?
PS: This is an Angular 8 project.
I had the same problem recently. It was caused by the inspector - "Disable cache" was enabled:
You just need to uncheck it and it will stop making new requests.
To use the image multiple times in the DOM with only one request from the CSS you should use the content property of your pseudo element target to render the image:
body::before {
content: var(--backgroundTheme, 'alt text');
}
Although you'll probably need another approach in handling the image. It might not work for you.
I have two possible idea, not sure if they works for you but it's an easy check:
If you can, don't use css variables, use scss instead. My general approach is to have a settings.scss file and import it whenever needed in the other files. It's a personal preference, I find it easier to manage like that.
It could as well be something wrong in the backend, are the caching headers set right? You can check that in Chrome itself, by clicking on tringle-dark.svg, Headers tab, then Response Headers.

How to preload images with PhoneGap?

I've come to believe that there's two things happening. Firstly, if you want to preload a url, you can do this:
body:after{
content: url(http://www.example.com/img/img_1.png) display:none;
}
But as far as I know, this doesn't help in this case:
body:after{
content: url(../img/img_1.png) display:none;
}
In this latter case, the image is already local, so it doesn't have to "download" it? Is that true? Or will the first bit of code cache the image even more?
I ask, because even though I do this, and I then transition to another page, using jquery mobile, the next page still takes a few seconds to load the background image. Even though it's a local asset.
How do I get around this?
From the tests I've done, it seems that two things can cause a delay when loading an image:
When the image needs to be loaded from a URL, or
When the image is locally located, but needs to be placed on the display screen
What i didn't realise is that with PhoneGap, even with the images local, it might take a little while to load. This is what was causing issues for me. Well, this and the fact that I was loading from URLs. So in my case I used the "CSS3 Caching Plugin" like so:
jQuery(function($) {
$.preload.images(document)
});
This solved my problem of loading images that was in the CSS file. But then for my own convenience, I added a section to the css file for locally cached files. Like so:
#cacheMe1 { background: #ffffff url('../img/img1.png') 50% 50% repeat-x; }
#cacheMe2 { background: #ffffff url('../img/img2.png') 50% 50% repeat-x; }
#cacheMe3 { background: #ffffff url('../img/img3.png') 50% 50% repeat-x; }
#cacheMe4 { background: #ffffff url('../img/img4.png') 50% 50% repeat-x; }
etc
This solved caching for most images, plus it allowed me to still keep URLs as loading in the app (i have a gallery section where its currently acceptable to see the images load, rather than on display).
What I also did that seems to be working, is that I use the "InAppBrowser" plugin to preload entire pages by opening them in a hidden window:
var ref = window.open('http://www.example.com', '_blank', 'hidden=yes');
If you open a bunch of files on load of the app, it seems when you either open these URLs again, or switch to the window with:
ref.show();
So there's two decent ways I've found to cache files that works perfectly for my scenario. Hope it helps someone else!
I do not know if I understood well, but maybe it can useful for you:
<img src="my.png" onerror="this.src = 'image-not-found.png';" />
When I was facing problems with preloading images I had to abandon an idea of using display:none; cause it didn't work properly (as long as I remember the browser refuses to load content of invisible elements in order to speed page load up and reducing the traffic). Instead I created a div that in browser's opinion was visible, but it had zero width and height. Required images I load as background-image for this block. The whole trick is that background-image property can take multiple values. The CSS will look like this:
#preload {
height: 0;
width: 0;
background-image: url(image-1.png), url(image-2.png);
}
So you don't get mess in the markup. Hope this trick will work in your case.
You don't need to attach the image to the DOM directly, therefor there is no need to use css to hide it. Use JavaScript to preload images.
var image = new Image();
image.src = "yourfile.jpg"
you can then provide a longer term solution using appcache.

CSS background will not reset. It is haunted

I can not explain this at all, but I've put a theme selector on my site. A javascript dropdown box that changes the CSS the site is using.
Theme 7 is a theme that had an image of lights in the background. I didn't think it worked with the rest of it so I changed it to a different image using cPanel on my hoster, hit save, and it saved and changed like any other file.
I refreshed multiple times to get the changes, and scrolled down to Theme 7 to see how the new image looked.
Same image as before.
I tried a new image. Same thing.
....I deleted the line background-image altogether, and then quit out of the browser and restarted it.
The lights are still there.
What is going on??? I'm using Chrome btw. In Safari the image was just straight black. I think I've stumbled on a cursed picture.
Here's the css
body {
font-family: Calibri, Arial;
text-align:center;
*/background-repeat:repeat-y;
background-size: 100%;*/
}
input {
padding: 3px;
font-size: 22px;
}
select {
padding: 4px;
}
/*-----CLASSES-------*/
More stuff here
Try pressing ctrl+r to clear Chrome's cache.
It probably cached the css you were using before in your browser (and possibly the image too?) That's the only answer that makes much sense. You can force-clear the browser's cache of the css by changing the call to the file my-styles.css?abcdefghijkl in your html (or wherever it is you are loading up the styles from).... but manually clearing your cache will work too.
You may want to incorporate a dynamic Cache Control... every time you change the theme with javascript, have it change or reload the cache so your users won't have to continuously clear their own cached files when they change the theme... Depending on what server you are using, you can do this with php and .htaccess or .NET and web.config, im not sure if there is a way to do it with javascript directly..?

Images being requested multiple times from CSS

Any idea what would make a stylesheet(s) load images multiple times? The images are the same URL, nothing fancy going on.
EDIT: Only happens in safari (5.0.3) in both iPhone "mode" and default "mode" - i cannot reproduce the problem in FF or IE.
Apache_access_log says that the image is indeed being accessed multiple times.
When adding styles that call the image back in one-by-one, they don't seem to follow any pattern as to when they will start to double up.
I also tried making the image significantly smaller to see if it was a cache issue. Didn't change anything.
Not sure what the deal is with Safari, but apparently:
If the CSS rules that reference the same sprite-sheet are not grouped together, it will request the image more than once. (Although not the full number of times the call appears).
#divOne, #divTwo, #divThree {
background-image: url('IMGURLHERE');
}
This would request the image one time.
#divOne {
background-image: url('IMGURLHERE');
}
#divTwo {
background-image: url('IMGURLHERE');
}
This would request the image twice.
No idea as to why this happens.

Extra blank page when converting HTML to PDF using abcPDF

I have an HTML report, with each print page contained by a <div class="page">. The page class is defined as
width: 180mm;
height: 250mm;
page-break-after: always;
background-position: centre top;
background-image: url(Images/MainBanner.png);
background-repeat: no-repeat;
padding-top: 30mm;
After making a few changes to my report content, when I call abcPDF to convert the report to PDF, suddenly I'm getting a blank page inserted after every real report page. I don't want to roll back the changes I've just made to remove this problem, so I'm hoping someone may know why the extra pages are being inserted.
I have experienced the same exact problem. the empty page is due to the page-break-after: always; in the CSS. Not just ABCpdf but also the printed will spit out an extra page. So I used the following code to eliminate the last page:
MyDoc.Delete(MyDoc.Page);
This however lead to a different kind of a problem. On development server, which has IE 8 I get an extra blank page and on production where I have IE6, I get no extra blank page. So I have emailed the support team at websupergoo to show me a way to look for a blank page. The idea is to iterate through a pdf and identify all blank pages and delete them using above logic.
And I second Jakkwylde's opinion. Websupergoo folks are extremely helpful and prompt in responding. I had another problem getting ABCpdf to work under 64 bit and had spent almost a day trying to figure it out. They provided me multiple scenarios which I could try out. Their support was right on the money and I got my app up and running in minutes.
protected void RemoveBlankPages(Doc pdf)
{
for (int i = pdf.PageCount; i > 0; i--)
{
pdf.PageNumber = i;
//get the pdf content
string textContent = pdf.GetText("Text");
//delete the page if it is blank
if (string.IsNullOrEmpty(textContent))
pdf.Delete(pdf.Page);
}
}
I've found abcPDF to be strange and unpredictable. That being said, what may be happening is that the combination of the page size and page-break-after may be the culprit. Reduce your page height and/or remove the page break.
One thing worth revisiting is the validity of your HTML markup if you are using the AddImageUrl method. Instances where the rendered PDF is not as expected can result from bad markup, busted tags, etc.
For what it's worth, WebSuperGoo has excellent support and respond great when you encounter anomalies. Often they can advise a work around or provide alternatives to your implementation if you send them your source code.
Kush is correct in that "I have experienced the same exact problem. the empty page is due to the page-break-after: always; in the CSS. Not just ABCpdf but also the printed will spit out an extra page."
If a div has "page-break-after:always" IE will literally always start a new page, and if nothing is added it will just print blank. Firefox does not.
abcpdf uses IE8s rendering engine, and as such makes a blank page. For purposes of the OP, just using an explicit height should solve the problem, and the engine will insert the page breaks for you.
I am trying to solve a similar issue, where I can't set the height explicitly because sometimes the content may take 2 pages. (Each page corresponds to a person, and each person should start on a new page when printed). I emailed abcpdf as well to see if they have a hack fix to detect the empty page, but was curious if anyone knows how to fix the underlying problem and css hack IE8 so as to make it not print the final page if empty. I'm guessing it's not possible, but wanted to make sure I'm not missing something obvious.
The AddImageURL() method of ABCPDF is loosely bind method which doesn't render html tightly within required area which causes new blank page.
try to use AddImageHTML() method to convert your desired HTML into PDF..
Doc theDoc = new Doc();
theDoc.Page = theDoc.AddPage();
int theID = 0;
theDoc.SetInfo(0, "CheckBgImages", "1");
theDoc.SetInfo(0, "RenderDelay", "5000");
theDoc.HtmlOptions.Engine = EngineType.MSHtml;
theID = theDoc.AddImageHtml(HTML);
while (true)
{
if (!theDoc.Chainable(theID))
break;
theDoc.Page = theDoc.AddPage();
theID = theDoc.AddImageToChain(theID);
}
for (int i = 0; i <= theDoc.PageCount; i++)
{
theDoc.PageNumber = i;
theDoc.Flatten();
}
theDoc.Save(HttpContext.Current.Server.MapPath(Path));
theDoc.Clear();
It will always give accurate results.
To avoid page breaking in the last page, I did something like this and it worked.
I made sure that the last page didn't have the page-break-after: always, this can be done with any templating or front-end framework like angularJS, but for this example I use blade templating (but any php will do...)
#if ($last_page)
<div class='footer last-page'>
#else
<div class='footer'>
and then I have this in my style sheet
.footer {
page-break-after:always;
}
.last-page {
page-break-after:avoid;
}
We had the same issue in production environment only but not in test environment. We only had page-brek-after used at multiple places in the html.
Fix for first issue: I spotted the issue by removing the page-brek-after attributes one by one and this finally gave me the DIV section where page break was causing by some of it's element.
I fixed the height of each elements inside the DIV and this finally fixed my issue without removing the page-break-after attribute.
Fix for similar issue: If you have a custom hard coded footer, make sure to check by increasing/decresing it's height and margine.
I had this same thing happen with html to pdf where abcpdf was adding a blank page with nothing but a footer on it before the rest of the content (as page 1). This would occur when my content included a table surrounded by a div where the div height was height:auto followed by a page-break-before: always. It only happened when the table data contained "", string.Empty, or a single line of text. If the table data contained 2 lines or more of text, the issue did not present.
I solved it by adding a min-hight: 1in style to the div that had height: auto.

Resources