Correct way to display an img fallback - html

Premise: I have done a lot of research on how img and source tags work, but every single article only superficially deals with the attributes of these tags.
I need to make sure that if the browser does not support the image format (eg .wepb, but it can be .raw or .nef), or the path/url is wrong, there is a correct fallback to a .jpg, then to the alt. I thought of these two solutions:
<!-- First solution -->
<img src="foo.jpg" alt="foo"
srcset="foo.webp 1x">
<!-- Second solution -->
<picture>
<source srcset="bar.webp">
<img src="bar.jpg" alt="bar">
</picture>
Neither of them works, in fact if the file is not found, or if I try with unsupported extensions, there is no fallback on src, but the alt is triggered instead.

Every single article only superficially deals with the attributes of img and source.
For image filetype fallbacks try the type attribute on your <source> elements:
<picture>
<source srcset="bar.webp" type="image/webp">
<img src="bar.jpg" alt="bar">
</picture>
In this example, the user agent will choose the first source that has a type attribute with a supported MIME type. If the user agent supports WebP images, the first source element will be chosen. If not, the img element will be chosen.
Read more in the HTML Specification

Related

How to use next.js Image component with HTML <picture> element?

Next.js has an Image component that lazy loads images and also provides a srcset for a given image.
However, sometimes we want to deliver different images for different devices (art redirection).
Mozilla says we should use <picture> element for this purpose, providing different images for different media queries.
I can't find an article (even in next.js official docs) to tell us how can we do that using <Image> component.
Is it possible? How can I use next.js <Image> component and HTML <picture> element together?
I have searched for hundreds of websites, this is the only solution I found which workable on Next.js ( with tailwindcss ).
import Image from 'next/image'
<div>
<div className="md:hidden">
<Image src="Banner-767x500.webp" height={500} width={767} />
</div>
<div className="hidden md:inline-flex lg:hidden">
<Image src="Banner-1023x500.webp" height={500} width={1023} />
</div>
<div className="hidden lg:inline-flex xl:hidden">
<Image src="Banner-1400x500.webp" height={500} width={1400} />
</div>
<div className="hidden xl:inline-flex">
<Image height={500} width={2000} src="Banner-2000x500.webp" />
</div>
</div>
The new version of Next Image component removes a lot of the extraneous HTML and styles and allows full flexibility of the img tag. With that new improvement in the component we can use the picture tag and the image component as normal.
Plus, Web.dev explains the way the picture element works really well: https://web.dev/learn/design/picture-element/
In the same way that srcset builds upon the src attribute, the picture element builds upon the img element. The picture element wraps around an img element.
If there is no img element nested inside the picture element, the picture element won't work.
Like the srcset attribute, the picture element will update the value of the src attribute in that img element. The difference is that where the srcset attribute gives suggestions to the browser, the picture element gives commands. This gives you control.
So, understanding that the picture element is just a wrapper of the img element which the browser still requires, and using the new version of next/image (Nextjs v. 13), you can write it as:
import Image from "next/image";
<picture>
<source srcset=".." media="..."/>
<Image src="..." height="..." width="..." alt="..." />
</picture>
A better approach is to use vanilla HTML as the following example, tested in Next.js 13.
Pros:
Full control of what you're showing and when.
Cons:
Manual optimization of assets.
<picture>
<source srcSet="/portrait/my-dog.webp" media="(orientation: portrait)" />
<img src="/my-dog.webp" alt="A beautiful labrador" loading="lazy" />
</picture>

Why does HTML tags look so different for audio, video, and img elements?

I'm new to HTML so apologies if this is a dumb question.
In HTML, a video element looks like this:
<video src="https://example.com" controls>Label or text to display</video>
An audio element looks like this:
<audio>
<source src="iAmAnAudioFile.mp3" type="audio/mp3">
</audio>
And an image element looks like:
<img src="image.png">
Is there a rationale for all these to use such a different syntax from each other? Why don't they just all look the same, like:
<img src="https://example.com" attribute1 attribute 2>This could be alt text or be empty</img>
<audio src="https://example.com" attribute1 attribute2>This could be alt text or be empty</audio>
<video src="https://example.com" attribute1 attribute2>Label or text to display</video>
I understand that each element has different needs (like video needs to display text if the browser can't display the video), but it seems like those could be accommodated in a unified syntax.
<video> and <audio> are actually unified.
You can very well have
<video>
<source src="thesource.mp4">
</video>
as well as
<audio src="thesource.mp3" controls>Some fallback text</audio>
They both have a few attributes that will differ, but most are shared.
For still images, the equivalent element would be <picture> and not <img>, though it can't have its own src.
<img> is a very old element, from an other era, which explains why it's not designed the same way.
There's a good reason. You can have multiple <source> elements inside an <audio>, or indeed a <video> element, so the syntax is in fact consistent (<img> only allows one source however, so only src is supported). And if there is only one source, you can indeed use the src attribute for <audio> as well.
From https://developer.mozilla.org/en-US/docs/Web/HTML/Element/source
It is commonly used to offer the same media content in multiple file formats in order to provide compatibility with a broad range of browsers given their differing support for image file formats and media file formats.
I assume you're talking about how the img tag doesn't have a closing tag?
Since the element cannot have any child nodes, it is defined as EMPTY and the end tag is forbidden (as it would serve no purpose).
The audio opening tag and end tag is on a new line I see in your example, but that doesn't matter, as long as it is closed. New line or on the same, it's the same.

Simple rollover effect using picture source srcset with next-gen images like .webp

Updating code and optimizing site speed so trying to change this simple html rollover effect:
<img src="img1.jpg" onmouseover="this.src='img2.jpg'" onmouseout="this.src='img1.jpg'">
To something along the lines of this:
<picture>
<source srcset="img1.webp" type="image/webp" onmouseover="this.src='img2.webp'" onmouseout="this.src='img1.webp'">
<source srcset="img1.jpg" type="image/jpeg" onmouseover="this.src='img2.jpg'" onmouseout="this.src='img1.jpg'">
<img src="img1.jpg" onmouseover="this.src='img2.jpg'" onmouseout="this.src='img1.jpg'">
</picture>
I didn't really expect the latter to work, but am mentally blocked as to the correct approach for this basic effect so the browser will access the appropriate image format.
Assuming one is already using Modernizr js, here is one possible solution using CSS & HTML:
.webp .rollover{
background:url("/img3/img1.webp")
}
.webp .rollover:hover{
background:url("/img3/img2.webp")
}
.no-webp .rollover{
background:url("/img3/img1.jpg")
}
.no-webp .rollover:hover{
background:url("/img3/img2.jpg")
}
<div class="rollover"></div>
I know there are other solutions as well, but this one worked for me.
One downside of this approach is there is a lag while img2.xxx is loaded 'onHover'. However, this also means img2 is not explicitly 'preloaded', hence speeding up overall page download time. (One could finesse this too).

Does the picture tag dislike React?

This question has been asked before but there was no given solution. At least nothing that worked for my problem.
In React, the picture tag does not work. It is written in plain html in JSX. No functions, no variables, etc. Just plain hard coded tags.
It had failed to load local images as well as online images.
I had copied the very same html in the JSX file and pasted into an html file. The html file rendered without fail.
This is the code snippet below was the that could render in a html file but not a jsx file through React.
<picture className="dice">
<source id="img512" className="img512" media="" srcSet="./512x512.png" />
<source id="img256" className="img256" media="" srcSet="./256x256.png" />
<source id="img144" className="img144" media="" srcSet="./144x144.png" />
<source id="img96" className="img96" media="" srcSet="./96x96.png" />
<img src="./512x512.png" alt="Icon" />
</picture>
I have tried a single source tag. I have tried removing every attribute exluding srcSet. I have tried using src instead of srcSet and also tried srcset. All have failed rendering an image. The only thing that rendered was the alt text.
Am I missing something here? Is there something that React doesn't like what I have done here?
Here is a link of the post I initially had read before posting:
picture tag in React
Update:
So as "Jesper We" mentioned I be using className instead of class. I personally already knew that this was a common mistake and would have caught this mistake. Since I posted the wrong code early I had ran the code again for the sake of confirmation. Still a no pictures unfortunately
I worked towards "Robin's" comment and check out his suggestion. I copied the code he provided in the link and pasted it into my code. Everything was working. Then I filled in the media queries of my original code. Oddly enough it did not work. Then I used other online images then those images worked. I had tried both png and jpg images and the both worked. Then I used my own images again that were png images and none of them worked.
Now it looks like there something wrong with the images I have but I think problem now no longer revolves around the code. I hope...
You need to modify your code, then it will work perfectly, see this code
https://stackblitz.com/edit/react-jessyq
Resize the output window, you will see the different images for different sizes. Hope your problem will be solved. HAPPY CODING :)
picture tag is used for responsive image, As far i know image will be change according to device width. For this purpose you should use picture tag with media query like this
<picture>
<source media="(min-width: 650px)" srcset="img_pink_flowers.jpg">
<source media="(min-width: 465px)" srcset="img_white_flower.jpg">
<img src="img_orange_flowers.jpg" alt="Flowers" style="width:auto;">
</picture>
For Details: https://www.w3schools.com/tags/tag_picture.asp
And you can't use class in react, use className instead of class.
<picture>
<source media="(min-width: 650px)" srcset="logo.png" width="170" height="100"/>
<img src="smallLogo.png" alt="smallLogo" width="50" height="50" />
</picture>

Display alternate image

Is it possible to show an alternate image if the original source file is not found?
I would like to achieve this only with css and html, no javascript (or jQuery and alike).
The idea is to still show an image instead of the "alt" test or default (ugly) cross of IE.
If not possible without javascript I will then rather check the img src with php with a basic if-then-else.
Very simple and best way to achieve this with little code
<img class="avatar" src="img/one.jpg" alt="Not Found" onerror="this.src='img/undefined.jpg';">
To me the above works perfect!
You can do this using the CSS background-image property of the img element, i.e.
img
{
background-image:url('default.png');
}
However, you have to give a width or height for this to work (when the img-src is not found):
img
{
background-image:url('default.png');
width:400px;
}
<object data="foobar.png" width=200 height=200>
<img src="test.png" alt="Just testing.">
</object>
Here foobar.png is the primary image, test.png is the fallback image. By the semantics of the object element, the content of the element (here the img element) should be rendered if and only if the primary data (specified by the data attribute) cannot be used.
Though browsers have had awful bugs in implementations of object in the past year, this simple technique seems to work on modern versions of IE, Firefox, Chrome.
yes, you can do it by using only html, when img src not found then it will throw error so here we can handle it. One more point is set this.onerror = null for recursive calling (default image not found)
<img alt="User Image" class="user-image" src="/Resources/images/user-icon.png" onerror="this.onerror=null; this.src='/Resources/images/default_img.png'">