CSS3 replace image src with another attr - css

I have lazyload working on my site. But if someone wants to print the webpage then id like the images to print out as well and not the loading spinner.
Here is what my images look like
<img class="lazy" data-original="images/gd-0007.jpg" src="../../img/loadingplaceholder.gif">
so using the #media print { } Id like to make the src the same as the data-original.
Tried this but no luck. (did it in the stylesheet to see if it worked)
#media print {
.lazy {
src: attr(data-original);
}
}
Here is where i got the idea:
http://andydavies.me/blog/2012/08/13/what-if-we-could-use-css-to-manipulate-html-attributes/
Here is a jsfiddle if it helps:
http://jsfiddle.net/gXpzb/

The problem is, this is just an idea for something that the author thinks would be nice to have in CSS one day, currently this is not supported.
There is no src property to be set in CSS, but a content property, however it doesn't seem to accept an URL fetched using attr(), respectively it doesn't seem to be implemented by any browser yet. Judging from the specs, something like this could be possible in the future:
content: attr(data-original url);
See also: Css Content, Attr and Url in the same sentence
So, as far as I can tell you'll currently have to stick with explicitly defining the URLs in CSS, something like
<img class="lazy gd0006" src="http://beresponsive.net/tcex/img/loadingplaceholder.gif">
<img class="lazy gd0007" src="http://beresponsive.net/tcex/img/loadingplaceholder.gif">
<img class="lazy gd0008" src="http://beresponsive.net/tcex/img/loadingplaceholder.gif">
...
#media print {
.lazy.gd0006 {
content: url('/images/gd-0006.jpg');
}
.lazy.gd0007 {
content: url('/images/gd-0007.jpg');
}
.lazy.gd0008 {
content: url('/images/gd-0008.jpg');
}
...
}

Related

Angular: How to add global CSS (e.g. to the body), but only for one specific page?

How can I add separate CSS for one page in Angular?
This is the CSS I need, as per How to remove the URL from the printing page?:
#media print{
#page{
margin:0;
}
body{
margin:30px;
}
}
But putting CSS into the component with ::ng-deep or ViewEncapsulation.None won't help here, because when navigating away from a page, the CSS of the page isn't deleted.
I've added a Stackblitz, which explains the problem clearly.
I've come up with a potential solution, but it doesn't work:
encapsulation: ViewEncapsulation.None
...
constructor(private renderer: Renderer2) {
this.renderer.addClass(document.body, 'special-print');
}
ngOnDestroy() {
this.renderer.removeClass(document.body, 'special-print');
}
....
....
....
#media print{
#page{
margin:0;
}
body.special-print{
margin:30px;
}
}
Why it doesn't work:
While it would help with <body> CSS, it won't help with #page CSS. Perhaps the question would be better summarized as "How to add global CSS, but remove it when we leave the page?".
Solved!
We print the <style> block directly into the component's HTML, and therefore when the component gets removed, our <style> block gets removed too. (Normally this wouldn't work, but thanks to DomSanitizer.bypassSecurityTrustHtml, Angular won't break our code when running optimizations.)
Here's a StackBlitz.
First, create a new component to handle the work:
component.ts: (This is all we need. We don't need an HTML or style.css file.)
//Inside your local component, place this HTML
//<app-local-css [style]="'body{background:green !important;}'"></app-local-css>
// OR
//<app-local-css [scriptURL]="'/path/to/file.css'"></app-local-css>
#Component({
selector: "app-local-css",
template: '<span style="display:none" [innerHTML]="this.safeString"></span>'
})
export class LocalCSSComponent implements OnInit {
constructor(protected sanitizer: DomSanitizer) {}
#Input() scriptURL?: string;
#Input() style?: string;
safeString: SafeHtml;
ngOnInit() {
if (this.scriptURL) {
let string = '<link rel="stylesheet" type="text/css" href="' + this.scriptURL + '">';
this.safeString = this.sanitizer.bypassSecurityTrustHtml(string);
} else if (this.style) {
let string = '<style type="text/css">' + this.style + "</style>";
this.safeString = this.sanitizer.bypassSecurityTrustHtml(string);
}
}
}
And then use it like this:
mySample.component.html:
<app-local-css [style]="'body{background:green !important;}'"></app-local-css>
// OR
<app-local-css [scriptURL]="'/path/to/file.css'"></app-local-css>
Angular is doing client-side rendering, which is bad news, because you do not have separate pages. You have several possible solutions though:
1. Separate page
You can create another page with or without Angular, which includes the CSS you need and load that page. In the most simplistic approach to achieve this, the other page would have a different URL. If having a different URL is not to your liking, then you could hide your page's content and show the other page inside an iframe. It would admittedly be a hacky solution, but it is a solution.
2. Client-side CSS rendering
Instead of just loading the CSS, you could have a component which would control global CSS rules, matched by your view's name. You would have a template value rendered to a property, like:
#media print{
#page{
margin:0;
}
body{
margin:30px;
}
}
And when you visit the page where this needs to be activated, you would simply initialize a property with a style HTML element that was generated based on the template and added to head. Once you leave the given view, your component would detect that event and would remove() that element. If you choose this solution, then it would be wise to make sure that you are supporting this on more general terms, so that if some new views will have their custom global CSS, then they would be easy to integrate into your project in the future.
3. body classes
You could add/remove some custom-print or whatever class to/from body whenever the style is to be changed. This way you could add the CSS exactly once to your HTML and change the rules accordingly, like:
body.custom-print {
margin: 30px;
}
This would be a neat solution, but the problem in your case is that you have a #page rule as well and I'm not sure how you could make that dependant on body classes or some other HTML attributes. I would conduct quite a few experiments about this if I were you.
4. Iframe staging
You could avoid having that CSS in your main page, but would have a hidden iframe where you would have the CSS and would just copy the content into the CSS and once that's loaded, print that.
Don't change the whole body from apple. Instead, there are a few changes to make.
In the app component, hold a boolean for whether or not you are on apple, and use ngClass for class defined in scss.
Track which route you are on in appComponent, and set isApple accordingly
Add a div around all your html, for container to take full size
Add global html, body setting height to 100% so you see color everywhere
Remove body overriding in apple
so,
appComponent.ts:
isApple: Boolean;
constructor(router: Router) {
router.events.subscribe(v => {
if (v instanceof NavigationEnd) {
this.isApple = v.url === "/apple";
}
});
}
appComponent.html:
<div [ngClass]="{'red':isApple}" class="container">
<p>
There are two components: Apple and Banana. Switching between them will show
the problem.
</p>
<router-outlet></router-outlet>
</div>
appComponent.scss
.red {
background-color: red;
}
.container {
height: 100%;
}
apple.component.scss (remove body)
/*Sample "global" CSS, that affects something outside the current component.*/
::ng-deep {
#media print {
#page {
margin: 0;
}
}
}
styles.scss (global)
html, body {
height: 100%;
}
You can see this altogether at this Stackblitz link
You can add different css files in the component (for instance, app-task.component.ts):
#Component({
selector: 'app-task',
templateUrl: './app-task.component.html',
styleUrls: ['./app-task.component.scss', './styles2.scss', './styles3.scss']
})
In this example, the style files are in the same folder that the component, but this is not the best option: you have to put the files in assets, for example. Also, be careful with the thread of the styles, since the first one you put will be put before the second (obviously).

Exclude CSS class from inheriting

I have tried to search but am not sure if I am posing the question right.
I applied the following css to my site:
a[target='_blank']::after {
content: '\29C9';
}
This means that all external links will get the icon attached to it. So far, so good, it works as expected.
There are some situations though where I do not want this to happen, like in social share buttons. How can I exclude some classes?
Like when the link appears in a div with class 'socialbutton'?
PS I cannot add other style to these buttons (WordPress website and generated code)
You can overwrite this css code by adding new css to the class.
Example you can overcome this:
a[target='_blank']::after {
content: '\29C9';
}
By doing this:
.socialbutton::after {
content: '\fff' !important;
}
You can use the :not() selector:
a[target='_blank']:not(.social)::after {
content: '\29C9';
}

CSS paged media :last page selector

I need to know if I can modify content on the last page with the :last selector.
I'm not sure if it exists, I see it being used in other stackoverflow answers like this: Footer on last printed page.
But I can't find it in the documentation and it does not work when I try to use it.
I'm trying to clear the content on the footer of my last page like this:
#page {
#bottom-right {
content: "Please turn over";
}
}
#page :last {
#bottom-right {
content: none;
}
}
It works when I use it with the :firstselector. How can I get the effect for the last page?
I'm using Weasyprint to print PDF files.
This can be achieved using named pages.
Create an element on the last page (or use an existing one that will appear on the last page) and assign it a last-page class.
Example below:
HTML
<div class="last-page"></div> <!-- Or add this class to an existing element that appears on the last page -->
CSS
.last-page {
page: last_page;
page-break-before: always; /* Use if your last page is blank, else omit. */
}
#page {
#bottom-right {
content: "Please turn over";
}
}
#page last_page {
#bottom-right {
content: none;
}
}
Tested with Weasyprint - worked a charm.
Based on the CSS3 Page docs it appears the :last pseudo-class was removed (or never included).
It might be possible to target the last page using the :blank pseudo-class if you can force a page break at the end of your document. This might have unwanted effects on other blank pages though.

I want to use non-printing buttons at specific locations on an html document

I have a "print this page" button that works fine:
<a style="top:-40;left: 375;position:absolute;z-index:5000;">
<script>
document.write("<input type='button' " +
"onClick='window.print()' " +
"class='printbutton' " +
"value='Print This Page'/>");
</script>
</a>
It is exactly where I want it and it doesn't show on the print.
I have several navigation buttons that jump to other pages:
<button style="position:absolute;top:1050px;left:-105px;z-index:5000;">
Home</button>
These work fine, but they do print.
How can i make them not-print like the print button? I have tried several variations on modifying the print button script, but have not found the right combination yet.
Suggestions certainly appreciated. Please be very specific because I am very early into this.
You could do like suggested here.
Put this in your CSS file or add it to your style headers like you did with the "a" elements.
inside of a CSS document would look like this:
#media print
{
.no-print, .no-print *
{
display: none !important;
}
}
Using inline-styles within your current document would look like this:
<style>
#media print
{
.no-print, .no-print *
{
display: none !important;
}
}
</style>
then wrap your buttons in the no-print class.
<div-class="no-print">
<button style="position:absolute;top:1050px;left:-105px;z-index:5000;">
Home</button>
</div>

Image not scaling correctly in Firefox

I have a 2550px x 3300px image of a document. I scale it to 901px to 1166px using css. Also used image width/height attributes without css. It looks great in chrome and IE but the image contents look jagged in FF (3.6). Resizing the image itself is not an option (for good quality printing).
Any suggestions?
You could try adding the CSS tag image-rendering: optimizeQuality; although this should be the default. Perhaps you have another tag somewhere which is overriding the default?
From http://articles.tutorboy.com/css/resize-images-in-same-quality.html
If the intention is to get a better quality when the user prints the page you could use separate style sheets for print and screen.
<style>
#media screen
{
#origImage { display:none; }
}
#media print
{
#screenImage { display:none; }
}
</style>
...
<img id="origImage" src="original.jpg" />
<img id="screenImage" src="resized.jpg" />

Resources