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>
Related
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
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>
I have the below image HTML code, working great on responsive websites and loading images only when needed based on screen-size, saving the user bandwidth. I'm also already lazy-loading images based on whether they show in the browser viewport.
<picture>
<source media="(max-width: 300px)" srcset="/images/thumb.png ">
<source media="(max-width: 500px)" srcset="/images/largethumb.png ">
<img src="/images/original.png">
</picture>
However, I have many images on my page, so how can I reduce the HTML payload? I'm looking for something like this, but not sure if it's possible at all:
HTML
<picture>
<source srcset="/images/thumb.png ">
<source srcset="/images/largethumb.png ">
<img src="/images/original.png">
</picture>
PSEUDO CSS
picture source:nth-child(1){
media:(max-width: 300px);
}
picture source:nth-child(2){
media:(max-width: 500px);
}
But I can't find anything on Google.
I already checked:
https://alligator.io/html/picture-element/
https://bitsofco.de/the-srcset-and-sizes-attributes/
I'd suggest going with lazy loading.
It literally defers the loading of resources on the page as long as they are not needed. E.g using Intersection Observer API images will never be loaded if users never get to that point of the website. This means serious savings in bandwidth.
There are couple ways how to do this:
Native lazy loading
<img src="yourimage.jpg" loading="lazy" alt="..." />
More info here: https://web.dev/browser-level-image-lazy-loading/
Using the Intersection Observer API
All details here: https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API
Here is also great article how to match all technics perfectly with responsive images: https://css-tricks.com/tips-for-rolling-your-own-lazy-loading/
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).
I have a basic custom Pin it button. This picks up images inline to the page, but it's not picking up images using the HTML5 picture element with srcset.
<img src="//assets.pinterest.com/images/pidgets/pinit_fg_en_rect_red_28.png" />
Here's an example of the picture element in use, where the button is not working:
<picture>
<img srcset="https://s3-us-west-2.amazonaws.com/s.cdpn.io/652/coffee5.jpg">
</picture>
A very stripped down demo to play with that illustrates the problem: http://codepen.io/michaelpumo/pen/eZyddp
Any ideas?
Update: I might actually have to add that my usecase is a bit more complicated than this. The above is a simplified / stripped down version to illustrate the point. I'm lazy loading these too you see.
Please use the following. It works.
<picture>
<img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/652/coffee5.jpg" srcset="https://s3-us-west-2.amazonaws.com/s.cdpn.io/652/coffee5.jpg" data-pin-description="Hello World">
</picture>
I thought src and description should be there for Pinterest.