Lower quality images in Next.js "Image" vs. normal "img" tag - html

I'm working with Next.js, and for some reason my images are looking somewhat blurry when I use Next/Image.
Here's what my code looks like:
<img src={url} width={articleWidth} />
<Image
className="text-center"
src={url}
alt={alt}
width={width}
height={height}
/>
Here's what the images look like (it might be a bit difficult to tell but the Next/Image version is clearly blurrier on my monitor).
A few other pieces of info I noticed
The version using the img tag had an intrinsic size of 2016 x 1663 and the version using Next/Image had an intrinsic size of 750x615
How do I make Next/Image images look just as clear as my regular img component

Next.js creates versions of your image on run time and serves the apt sized image to render.
If you want to opt out of it:
You can selectively use the unoptimized prop:
<Image
className="text-center"
src={url}
alt={alt}
width={width}
height={height}
unoptimized
/>
or,
Using the unoptimized option in next.config.js:
module.exports = {
images: {
unoptimized: true,
},
}
When above is set true images will be served as is, without any size change.

Related

setting alternative img source

i have a web app written in aspx.
I have a img control.
If a required image is not available then the alt text message displays.
Is there a way to set an 'alt image' instead? This img control relies on updates so after a default period of 10 seconds if no image is acquired then I would like to set a default image instead. It would be handy if there was a property like 'alt image'.
I guess I could use a timer to check but would be interested in other approaches.
Thanks
The onerror attribute can execute js and set a new image like shown below
<img src="/images/200.png" onerror="this.src='/images/404.png'" >

Metaio SDK (AREL) - how to show image content without tracking?

I have just simple rectangle button realized as image content and i wanna to show it on screen without any tracking and without using screen anchors.
You can see i have no translation and rotation, but screen is still empty.
<object id="button1">
<title><![CDATA[Button 'images']]></title>
<assets3d>
<model><![CDATA[html/resources/0cde94934f9b4dab0998a3d73b2865ba/0cde94934f9b4dab0998a3d73b2865ba.zip]]></model>
<transform>
<translation>
<x>0.0</x>
<y>0.0</y>
<z>0.0000000000</z>
</translation>
<rotation type="eulerdeg">
<x>0.0000000000</x>
<y>0.0000000000</y>
<z>0.0000000000</z>
</rotation>
<scale>
<x>0.0</x>
<y>0.0</y>
<z>0.0</z>
</scale>
</transform>
<properties>
<coordinatesystemid>0</coordinatesystemid>
<screenanchor flags="4">0</screenanchor>
</properties>
</assets3d>
<viewparameters/>
</object>
You can use Dummy-Tracking: http://helpdesk.metaio.com/questions/7548/explanation-on-dummy-tracking
In general the best place to ask questions about AREL or the metaio SDK is http://helpdesk.metaio.com
There you should get an answer quickly.
I think that the problem is here:
<scale>
<x>0.0</x>
<y>0.0</y>
<z>0.0</z>
</scale>
The 0.0 is not a neutral scaling value.Your scaling transformation results in an object with no dimension. As it is shown on http://www.advancedmetaio.com/explaining-the-arel-xml-structure-part-2-transformations/, if you don't want to apply any scaling transformation your scaling values should be (1, 1, 1) :
<scale>
<x>1.0</x>
<y>1.0</y>
<z>1.0</z>
</scale>

Setting an image src to empty

I would like to set an image as nothing. By doing src="" many people say it can cause problems to browsers:
http://www.nczonline.net/blog/2009/11/30/empty-image-src-can-destroy-your-site/
so I am not sure if below can face to the same problem as setting src to empty:
<img id="myImage">
since there's no src attribute on this case.
So If I want to initially set an image to nothing, what's the best I can do?
Best solution
Initialise the image as follows: src="//:0" like here: <img id="myImage" src="//:0">
Edit: as per the comment of Alex below, using //:0 apparently can trigger the onError event of the img. So beware of this.
Edit 2: From comment by Drkawashima: As of Chrome 61 src="//:0" no longer seems to trigger the onError event.
Other solution
Alternatively, you can use a very small image until you actually fill the src tag: like this image. With this 'very small image', you would then initialise the tag like so:
<img src="data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs%3D" width="0" height="0" alt="" />
source
Remove element from DOM
Alternatively, if you simply don't want the element to appear in the DOM, just use some JavaScript:
var myObject = document.getElementById('myObject');
myObject.parentNode.removeChild(myObject);
(as per this answer, using JavaScript's .remove() function is not recommended, due to poor browser support in DOM 4)
Or just use some jQuery:
$("#myObject").remove();
Using a 1px transparent encoded image is an accepted solution (recommended by CSSTricks)
<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" alt="">
PS: Don't be confused later when DevTools shows these as network requests of zero bytes, that's just how DevTools works, all imgs are listed as network requests.
DS: alt="" is included because otherwise, screenreaders will read the src out loud
Just use a hash symbol #. It's valid value for src attribute. :)
https://stackoverflow.com/a/28077004/3841049
Use this script to set a default image if src is empty or blank
$(document).ready(function () {
$('img').each(function () {
if($(this).attr('src')=="") {
$(this).attr('src', 'Images/download.jpg');
}
});
});

Using base tag on a page that contains SVG marker elements fails to render marker

I've run into a problem while attempting to use SVG marker elements in an SVG based visualization. I'm adding my changes to a web application which happens to include a base tag on every page, so that any references to CSS files, javascript files, etc can be relative.
I have some example code below which reproduces the issue. There is a line element, and a marker element defined. The marker element is referenced by the line in its 'marker-end' attribute, via uri and id of marker. Without the base tag, the arrow displays fine. With the base tag, it is not shown. The reason is because the base tag changes the way the browser resolves urls.. even for the simple id based url specified in the marker-end attribute of the line.
Is there any way I can get around this problem without having to remove the base tag?
I can't really remove it because the use of it is fairly ingrained in the product I'm working on. I need to support Firefox, Chrome and IE9+ for my webapp. Firefox and chrome both produce this problem. IE works fine (ie. arrow marker displays).
<html>
<head>
<base href=".">
<style>
.link { stroke: #999; stroke-opacity: .6; }
marker#arrow { fill: black; }
</style>
</head>
<body>
<svg width="100%" height="100%">
<defs>
<marker id="arrow" viewBox="0 -5 10 10" refX="0" refY="0" markerWidth="20" markerHeight="20" orient="auto">
<path d="M0,-5L10,0L0,5"></path>
</marker>
</defs>
<line x1="100" y1="100" x2="333" y2="333" marker-start="url(#arrow)" class="link"></line>
</svg>
</body>
</html>
The HTML <base> element is used to say "resolve all relative URLs relative not to this page, but to a new location". In your case, you've told it to resolve relative to the directory with the HTML page.
The SVG marker-mid="url(…)" attribute is a FuncIRI Reference. When you use a value like url(#foo) that relative IRI is normally resolved relative to the current page, finding the element with the foo id. But, when you use <base>, you change where it looks.
To solve this problem, use a better value. Since your base reference is the current directory, you can simply use the name of the current file:
<line … marker-mid="url(this_page_name.html#arrow)" />
If you have a different <base> href, than what you've shown, like:
<base href="http://other.site.com/whee/" />
then you will need to use an absolute href, e.g.
<line … marker-mid="url(http://my.site.com/this_page_name.html#arrow)" />
Try with javascript:
<line id="something" />
With native:
document.getElementById('something').setAttribute('marker-mid', 'url(' + location.href + '#arrow)');
With jQuery:
$('#something').attr('marker-mid', 'url(' + location.href + '#arrow)');
It just works.
In the context of a rich web app like one built on Angular, where you need to set the <base> tag to make HTML5-style navigation work, it can get messy to try to fix that in a permanent way.
In my case, the app I was working on was showing a SVG-based interactive diagram builder that would change the app url as I selected elements therein.
What I did was to add a global event handler that would fix all url(#...) inline styles in any <path> element found in the page:
$rootScope.$on 'fixSVGReference', ->
$('path').each ->
$path = $ this
if (style = $path.attr 'style')?
$path.attr 'style', style.replace /url\([^)#]*#/g, "url(#{location.href}\#"
Then trigger this handler in key places, like when the app state changes (I'm using ui-router)
$rootScope.$on '$stateChangeSuccess', ->
$timeout (-> $rootScope.$emit 'fixSVGReference'), 5
As well as anywhere where I know there'd be new/updated paths like these. Here, the $timeout thing is to account for the fact that the DOM nodes really are changed asynchronously sometime after the $stateChangeSuccess event is triggered.
In Angular 2+, you can inject the base path in your app module instead of using the <base> tag. This resolved the issue in Edge and Firefox for me.
import { APP_BASE_HREF } from '#angular/common';
#NgModule({
providers: [{
provide: APP_BASE_HREF,
useValue: '/'
}]
})
export class AppModule { }
https://angular.io/docs/ts/latest/api/common/index/APP_BASE_HREF-let.html
Ember 2.7 will replace the <base> tag with rootURL which should fix this issue.
In the meantime in my d3 for gradients I'm using the following:
.attr('fill', `url(${Ember.$(location).attr('href')}#my-gradient)`);
If you don't do this, the item you are targeting will seem to be transparent.
On Windows currently (04-2017) all Browsers behave as expected ( mask=url("#svgmask") ). Chrome, Firefox, even IE 11!! - but Edge comes up with an error.
So for Microsoft Edge you still need to give the absolute path ( mask="url(path/to/this-document.htm#svgmask)" ) for your mask ID´s when you are using a base tag in your document:
<svg viewBox="0 0 600 600" >
<defs>
<mask id="svgmask">
<image width="100%" height="100%" xlink:href="path/to/mask.svg" ></image>
</mask>
</defs>
<image mask="url(path/to/this-document.htm#svgmask)" width="600" height="600" xlink:href="path/to/image.jpg"></image>
</svg>
If you do not want want to modify / animate the svg there is a simpler solution than changing the url() parameter.
Include the svg as image:
<img src="yourpath/image.svg">
You can archive it with:
$("[marker-mid]").attr("marker-mid", function () {
return $(this).attr("marker-mid").replace("url(", "url(" + location.href);
});

Controlling image load order in HTML

Is there a way to control the load order of images on a web page? I was thinking of trying to simulate a preloader by first loading a light-weight 'LOADING' graphic. Any ideas?
Thanks
Use Javascript, and populate the image src properties later. The # tells the browser to link to a URL on the page, so no request will be sent to the server. (If the src property was empty, a request is still made to the server - not great.)
Assemble an array of image addresses, and recurse through it, loading your images and calling a recursive function when the onload or onerror method for each image returns a value.
HTML:
<img src='#' id='img0' alt='[]' />
<img src='#' id='img1' alt='[]' />
<img src='#' id='img2' alt='[]' />
JS:
var imgAddresses = ['img1.png','img2.jpg','img3.gif'];
function loadImage(counter) {
// Break out if no more images
if (counter==imgAddresses.length) { return; }
// Grab an image obj
var I = document.getElementById("img"+counter);
// Monitor load or error events, moving on to next image in either case
I.onload = I.onerror = function() { loadImage(counter+1); }
//Change source (then wait for event)
I.src = imgAddresses[counter];
}
loadImage(0);
You could even play around with a document.getElementsByTagName("IMG").
By the way, if you need a loading image, this is a good place to start.
EDIT
To avoid multiple requests to the server, you could use almost the same method, only don't insert image elements until you're ready to load them. Have a <span> container waiting for each image. Then, loop through, get the span object, and dynamically insert the image tag:
var img = document.createElement("IMG");
document.getElementById('mySpan').appendChild(img);
img.src = ...
Then the image request is made only once, when the element is created.
I think this article https://varvy.com/pagespeed/defer-images.html gives a very good and simple solution. Notice the part which explains how to create "empty" <img> tags with:
<img src="data:image/png;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=" data-src="your-image-here">
to avoid <img src="">
To display a loading image, just put it in the HTML and change it later at the appropriate moment/event.
Just include the 'loading' image before any other images. usually they are included at the very top of the page and then when the page loading completes, they are hidden by a JS.
Here's a small jQuery plugin that does this for you: https://github.com/AlexandreKilian/imageorder