What is the purpose of data URIs? - html

Why are resources sometimes embedded in data URIs, rather than using a regular URI that links to a resource stored as a file on a server?

1. Reducing server requests
Data URIs can be used to decrease server load and improve client performance, by reducing the number of HTTP requests required to acquire resources. For example, this HTML:
<img src="assets/bullet.png">
... can be replaced with this:
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAALCAYAAACprHcmAA
ABFklEQVQY022RoW4CURBFD2ETymYFigRDEEgcFoNBIcAj0AQLH0AVfAEOQ0IgCP6C7L5ZWlpBG5
o2paJJ01JR/6aCbrI03GTcmZk7c+GfAkj54PqQDsDhkgSuDNQ3njff5vO7bS4XCgx9KJ2B5gReG9
D30UiPy6UeFwt96/X0Nps9+FCNw3UDakCfWy37WKvpU7Npv1cr+zEe600msw/AQyAlMJcTbKMmA3
pfLOrPeq0PlYoaaGDAFdgJaLwMaAD6OZnoodvV0HEGCKQFwj/IxmED+jWb2Zd2WyWZ7CPgGBhegj
eua187Hb0rFNRAOTqwJHAw51ZsZMXAVBIJJ/7nqsA+mhrbMBXIXQrGE2gYGAj0BcoSS/EXVfKm38
k6jyMAAAAASUVORK5CYII="
>
... to produce an image like this: with one fewer HTTP request.
Note: it appears to be impossible to embed data URI images in a Stack Overflow post; however, the image above was uploaded to an image hosting service using the data URI shown.
If, for example, your site uses many small icons, specifying them all as data URIs in a stylesheet:
.icon-bullet-red { background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAALCAYAAACprHcmAAABFklEQVQY022RoW4CURBFD2ETymYFigRDEEgcFoNBIcAj0AQLH0AVfAEOQ0IgCP6C7L5ZWlpBG5o2paJJ01JR/6aCbrI03GTcmZk7c+GfAkj54PqQDsDhkgSuDNQ3njff5vO7bS4XCgx9KJ2B5gReG9D30UiPy6UeFwt96/X0Nps9+FCNw3UDakCfWy37WKvpU7Npv1cr+zEe600msw/AQyAlMJcTbKMmA3pfLOrPeq0PlYoaaGDAFdgJaLwMaAD6OZnoodvV0HEGCKQFwj/IxmED+jWb2Zd2WyWZ7CPgGBhegjeua187Hb0rFNRAOTqwJHAw51ZsZMXAVBIJJ/7nqsA+mhrbMBXIXQrGE2gYGAj0BcoSS/EXVfKm38k6jyMAAAAASUVORK5CYII=) }
.icon-bullet-green { background-image: /* ... */ }
.icon-save { background-image: /* ... */ }
.icon-load { background-image: /* ... */ }
.icon-delete { background-image: /* ... */ }
/* ... etc. */
... can eliminate a large number of HTTP requests, at the cost of overall download size, legibility, and an increased likelihood that a bad edit might render the URI nonsensical (and difficult to fix).
An alternative method to achieve the same result for images is the use of CSS sprites.
2. Embedding content in a single file
A data URI can be used to contain all of the resources required to correctly display a page in a single document. This may be useful in e.g. a README file distributed alongside a piece of software. In theory, data URIs could also be used as an alternative to the use of attachments to embed resources in HTML email, but in practice client support for data URIs is too unreliable for this to be a useful technique.
3. Avoiding browser warnings
Some browsers display a warning if a page contains content served over a mixture of HTTP and HTTPS. If your server is set up so that static content like images is typically served over HTTP, but dynamic content is served over HTTPS, embedding that static content with a data URI is a possible workaround.

In addition to the previous answer (which is a very good summary), one thing I've been using this for lately is fonts. If I need to use just a small subset of characters from a font (say, a design-y font for a logo, or a special dingbat bullet icon), I can encode just the characters I need into a CSS #font-face declaration and not make the user download the entire font file.
For example, if I only want the devil (d) and angel (e) faces from Eggfaces ( http://www.dingbatdepot.com/details/EggfacesTFB ) , then I can use FontSquirrel's webfont generator tool ( http://www.fontsquirrel.com/tools/webfont-generator ) to create something like this:
#font-face {
font-family: 'eggfaces';
src: url(data:application/x-font-woff;charset=utf-8;base64,ENCODED_FONT_HERE) format('woff');
font-weight: normal;
font-style: normal;
}
See this fiddle for an example: http://jsfiddle.net/vuuVh/

Related

HTML e-mail generated by React breaks in GMail web client

I needed to generate a newsletter e-mail server-side. I researched various options, but I picked React (server-side rendering) because of good TypeScript support and my familiarity with that technology.
Generating an e-mail that displays correctly in GMail (or any other popular client) is a very tricky subject, as one needs to use small (and legacy) HTML subset. But that's a separate issue.
So I've crafted a test e-mail with React SSR, using the subset of HTML supported by GMail. To be sure, I've validated it with W3 Validator and it was successfully checked.
But when I sent the generated HTML output to a GMail address and displayed it in the GMail desktop web application, the output was a mess. In the mail HTML presented in the browser, some elements had missing inline CSS properties, while other were outside of their original parents.
How can I generate an e-mail using React that doesn't break in the GMail web application?
React renderToString function (and the similar ones, too, probably) emits a single-line minified HTML output without any line length limit.
For reasons beyond my reasoning, such single-line HTML documents can "break" GMail HTML parser and cause glitchy output.
But, on the other hands, resources online actually recommend e-mail HTML minification, as whitespace can (reportedly) be interpreted inconsistently across e-mail clients. So pretty-printing HTML output doesn't sound like a good idea.
A solution is to re-minify the HTML document, but with a line length limit. To be safe, I've put the limit quite low. I've used a popular html-minifier package.
import * as React from "react";
import { minify } from "html-minifier";
import { renderToString } from "react-dom/server";
export const renderMyMail = (params: MyMailParams): string => {
const reactHtmlString = renderToString(MyMail({ params }));
const reminifiedHtmlString = minify(reactHtmlString, { maxLineLength: 255, keepClosingSlash: true });
return reminifiedHtmlString;
};
Now, the e-mail displays correctly in GMail web application.

Using Imported Fonts in a Google App

I am creating a web app using Google Apps Script. When I wanted to import a photo from Google Docs, I followed the advice from this question and it worked perfectly. I thought a similar process would work for using a custom font hosted on Docs, but it throws a CORS exception.
The relevant code:
#font-face {
font-family: MyCustomFont;
src: url("https://drive.google.com/uc?export=download&id=1r2a5nd6om75url39428dfju4");
}
#headBanner {
font-family: MyCustomFont;
}
<div id="headBanner">
<p>This text should be in MyCustomFont</p>
</div>
The error it throws is: "Access to Font at '[URL in font]' from origin '[Google Script page I'm using]' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin '[Google Script page I'm using]' is therefore not allowed access."
How could I fix this? I just find it perplexing that it would throw a CORS exception for the font file but not for the picture.
Font files, along with AJAX requests using fetch are the only things that use CORS. Image requests and static inline requests for JavaScript (via tags) and CSS do not invoke CORS.
In this case, there is nothing you can do, short of (as #andrei-gheorghiu suggests) downloading the font file manually, saving it to your server and then accessing it from there. Whilst you can do that technically, it would technically be stealing. Hence his use of "Can, not may"...
Fun fact - CORS was basically invented for the specific use-case you've come across - so that 'font factories' could design fonts (which cost them money, obviously) and then be able to allow/deny access to those font files, depending on whether you have paid a license fee.
No doubt not the answer you wanted, but the answer nevertheless.

Why is photo not displayed using <img>?

I am creating a div of text and image so they are side by side. When I use the tag the photo will not display. This is a photo I took with my camera. It is high resolution; still, that shouldn't matter. When I try other photo files in its place, they work fine. Another strange thing is that other photos from that same group do not work (ex. me1.jpg, me2.jpg). I have tried "../images/People/me4.jpg" and "/images/People/me4.jpg" to no avail. Thx for help.
<article>
<section>
<img src="images/People/me4.jpg" />
<p> this is some sampel text about peole
and blah the ateh te as;ldk aldjfs al;sdk
a;slkd asd;ljfa;lsjd a;dljfa dkfei teh ie
</p>
</section>
</article>
article {
width: 440px;
padding-left: 20px;
}
section {
width: 430px;
background: white;
}
section > img {
float: left;
width: 170px;
height: 200px;
}
Your problem may be either in the "CSS" (for you have only posted a part of CSS is not possible to detect), as the "path" of the file (which is more likely), I recommend:
Differences between HTTP and FILE
First you must learn the differences between "http protocol" and "file protocol".
HTTP protocol:
HTTP functions as a request-response protocol in the client-server computing model. A web browser, for example, may be the client and an application running on a computer hosting a web site may be the server. The client submits an HTTP request message to the server. The server, which provides resources such as HTML files and other content, or performs other functions on behalf of the client, returns a response message to the client. The response contains completion status information about the request and may also contain requested content in its message body.
File protocol:
The file URI scheme is a URI scheme specified in RFC 1630 and RFC 1738, typically used to retrieve files from within one's own computer.
Developer tools
Second, your need learn about "Developer tools" (network tab), with developer tools you can detect "path" from your image and problems in "CSS" (if is your problem).
Using developer tools from Chrome (like Webkit):
https://developer.chrome.com/devtools#improving-network-performance
example:
Using from Firefox:
https://developer.mozilla.org/en-US/docs/Tools/Network_Monitor
Example:
I recommend that if you are developing your "html" for future use in a website/homepage, always use "http", good examples of "http" to use on your machine:
http://www.wampserver.com/en/ (windows, apache, php, mysql)
https://www.apachefriends.org/ (cross-platform, apache, php, mysql, pearl)
http://nodejs.org/ (javascript for network, async server :) )
http://fatfreeframework.com/home (framework php, no need apache in "developer")
https://www.djangoproject.com/ (python + web framework)
First try placing the image in the same folder where the HTML is . and just use
<img src="me4.jpg" />
if you see the image on the HTML page then paste the image file to its original folder back and then right lick on the image to copy the exact location of the image file and paste it in the src of the image in img tag
as
<img src="d:/folder/new/me4.jpg" />
there might be a problem with the source location of the image

#font-face custom font not rendering properly with xhtml2pdf for django

I'm trying to use a custom font in my attempts to render a pdf from HTML.
I've tried it out in HTML, the font shows up, so the path to the font must be correct, and it's probably being used correctly. The font is of type .ttf, and according to the docs on http://xhtml2pdf-base.googlecode.com/hg/doc/xhtml2pdf-en.html, it should render, but it doesn't.
Here's what I have in my style tags:
#font-face {
font-family: "Swiss";
src: url("/static/font/swiss.ttf");
}
body {
font-family: "Swiss";
font-size: 12px;
}
And the html:
<body>
asdf
</body>
I've tried many things, stripping the quotes off the font url and font family, my body is wrapped inside HTML tags so the html is properly formatted. Everything renders fine when rendering in a web page, but it's not being rendered properly when converting to PDF. Can anyone help me spot the error?
Best way is to use a callback to fetch fonts using filesystem path. Is more accurate and also you wan't be hitting webserver for each resource (resource meaning, fonts, images, etc)
pisa.CreatePDF(html.encode("UTF-8"), file_object , encoding='UTF-8',
link_callback=fetch_resources)
def fetch_resources(uri, rel):
find_file_in_path_using_uri
return path
By the way, I think your problem is you haven't done collect static so fonts are not really at /static/font/swiss.ttf. I mean they are not there outside django, and xhtml2pdf it's outside django. I'm not 100% sure.
I have had the same problem. gdrimes was right. After changing the url from relative:
#font-face {
font-family: FreeSans;
src: url("./FreeSans.ttf");
}
to absolute
#font-face {
font-family: FreeSans;
src: url("/home/rok/Documents/Muzey/muzey/website/templates/pdf/FreeSans.ttf");
}
the font in my PDF document was updated.
I am late to this thread but I recently had the same problem. The suggestion to use a callback to provide the font definition does work (but in my case case had some limitations because I needed some logic to use different fonts depending on external conditions). However, I found that the problem was that the url("/static/font/swiss.ttf") needs to be an absolute file location, not relative to your application location, as is shown. For example, in my case, my application location was '/home/user/app' the url needs to be:
url("/home/user/app/static/font/swiss.ttf").

Alternative to iFrames with HTML5

I would like to know if there is an alternative to iFrames with HTML5.
I mean by that, be able to inject cross-domains HTML inside of a webpage without using an iFrame.
Basically there are 4 ways to embed HTML into a web page:
<iframe> An iframe's content lives entirely in a separate context than your page. While that's mostly a great feature and it's the most compatible among browser versions, it creates additional challenges (shrink wrapping the size of the frame to its content is tough, insanely frustrating to script into/out of, nearly impossible to style).
AJAX. As the solutions shown here prove, you can use the XMLHttpRequest object to retrieve data and inject it to your page. It is not ideal because it depends on scripting techniques, thus making the execution slower and more complex, among other drawbacks.
Hacks. Few mentioned in this question and not very reliable.
HTML5 Web Components. HTML Imports, part of the Web Components, allows to bundle HTML documents in other HTML documents. That includes HTML, CSS, JavaScript or anything else an .html file can contain. This makes it a great solution with many interesting use cases: split an app into bundled components that you can distribute as building blocks, better manage dependencies to avoid redundancy, code organization, etc. Here is a trivial example:
<!-- Resources on other origins must be CORS-enabled. -->
<link rel="import" href="http://example.com/elements.html">
Native compatibility is still an issue, but you can use a polyfill to make it work in evergreen browsers Today.
You can learn more here and here.
You can use object and embed, like so:
<object data="http://www.web-source.net" width="600" height="400">
<embed src="http://www.web-source.net" width="600" height="400"> </embed>
Error: Embedded data could not be displayed.
</object>
Which isn't new, but still works. I'm not sure if it has the same functionality though.
object is an easy alternative in HTML5:
<object data="https://github.com/AbrarJahin/Asp.NetCore_3.1-PostGRE_Role-Claim_Management/"
width="400"
height="300"
type="text/html">
Alternative Content
</object>
You can also try embed:
<embed src="https://github.com/AbrarJahin/Asp.NetCore_3.1-PostGRE_Role-Claim_Management/"
width=200
height=200
onerror="alert('URL invalid !!');" />
Re-
As currently, StackOverflow has turned off support for showing external URL contents, run code snippet is not showing anything. But for your site, it will work perfectly.
No, there isn't an equivalent. The <iframe> element is still valid in HTML5. Depending on what exact interaction you need there might be different APIs. For example there's the postMessage method which allows you to achieve cross domain javascript interaction. But if you want to display cross domain HTML contents (styled with CSS and made interactive with javascript) iframe stays as a good way to do.
If you want to do this and control the server from which the base page or content is being served, you can use Cross Origin Resource Sharing (http://www.w3.org/TR/access-control/) to allow client-side JavaScript to load data into a <div> via XMLHttpRequest():
// I safely ignore IE 6 and 5 (!) users
// because I do not wish to proliferate
// broken software that will hurt other
// users of the internet, which is what
// you're doing when you write anything
// for old version of IE (5/6)
xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if(xhr.readyState == 4 && xhr.status == 200) {
document.getElementById('displayDiv').innerHTML = xhr.responseText;
}
};
xhr.open('GET', 'http://api.google.com/thing?request=data', true);
xhr.send();
Now for the lynchpin of this whole operation, you need to write code for your server that will give clients the Access-Control-Allow-Origin header, specifying which domains you want the client-side code to be able to access via XMLHttpRequest(). The following is an example of PHP code you can include at the top of your page in order to send these headers to clients:
<?php
header('Access-Control-Allow-Origin: http://api.google.com');
header('Access-Control-Allow-Origin: http://some.example.com');
?>
This also does seem to work, although W3C specifies it is not intended "for an external (typically non-HTML) application or interactive content"
<embed src="http://www.somesite.com" width=200 height=200 />
More info:
http://www.w3.org/wiki/HTML/Elements/embed
http://www.w3schools.com/tags/tag_embed.asp
An iframe is still the best way to download cross-domain visual content. With AJAX you can certainly download the HTML from a web page and stick it in a div (as others have mentioned) however the bigger problem is security. With iframes you'll be able to load the cross domain content but won't be able to manipulate it since the content doesn't actually belong to you. On the other hand with AJAX you can certainly manipulate any content you are able to download but the other domain's server needs to be setup in such a way that will allow you to download it to begin with. A lot of times you won't have access to the other domain's configuration and even if you do, unless you do that kind of configuration all the time, it can be a headache. In which case the iframe can be the MUCH easier alternative.
As others have mentioned you can also use the embed tag and the object tag but that's not necessarily more advanced or newer than the iframe.
HTML5 has gone more in the direction of adopting web APIs to get information from cross domains. Usually web APIs just return data though and not HTML.
I created a node module to solve this problem node-iframe-replacement. You provide the source URL of the parent site and CSS selector to inject your content into and it merges the two together.
Changes to the parent site are picked up every 5 minutes.
var iframeReplacement = require('node-iframe-replacement');
// add iframe replacement to express as middleware (adds res.merge method)
app.use(iframeReplacement);
// create a regular express route
app.get('/', function(req, res){
// respond to this request with our fake-news content embedded within the BBC News home page
res.merge('fake-news', {
// external url to fetch
sourceUrl: 'http://www.bbc.co.uk/news',
// css selector to inject our content into
sourcePlaceholder: 'div[data-entityid="container-top-stories#1"]',
// pass a function here to intercept the source html prior to merging
transform: null
});
});
The source contains a working example of injecting content into the BBC News home page.
You can use an XMLHttpRequest to load a page into a div (or any other element of your page really). An exemple function would be:
function loadPage(){
if (window.XMLHttpRequest){
// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
}else{
// code for IE6, IE5
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange=function(){
if (xmlhttp.readyState==4 && xmlhttp.status==200){
document.getElementById("ID OF ELEMENT YOU WANT TO LOAD PAGE IN").innerHTML=xmlhttp.responseText;
}
}
xmlhttp.open("POST","WEBPAGE YOU WANT TO LOAD",true);
xmlhttp.send();
}
If your sever is capable, you could also use PHP to do this, but since you're asking for an HTML5 method, this should be all you need.
The key issue to load another site's page in your own site's page is security. There is cross-site security policy defined, you would have no chance to load it directly in your iframe if another site has it set to strict same origin policy. Hence to find an alternative to iframe, they must be able to bypass this security policy restriction, even in the future, if any new component is introduced by WSC, it would have similar security restrictions.
For now, the best way to bypass this is to simulate a normal page access in your logic, this means AJAX + server side access maybe a good option. You can set up some proxy at your server side and fetch the page content and load it into the iframe. This works but not perfect as if there is any link or image in the content and they may not be accessible.
Normally if you try to load a page in your own iframe, you would need to check whether the page can be loaded in iframe or not. This post gives some guidelines on how to do the check.
You should have a look into JSON-P - that was a perfect solution for me when I had that problem:
https://en.wikipedia.org/wiki/JSONP
You basically define a javascript file that loads all your data and another javascript file that processes and displays it. That gets rid of the ugly scrollbar of iframes.