Responsive images in React Native Web? - react-native-web

I need to load a different image depending on screen size. On web you would use the picture element:
<picture>
<source srcset="big.jpg" media="(min-width: 800px)">
<img src="small" />
</picture>
Note that this is different to an image with srcset. With srcset the browser decides which image to load. I need to control this as it's an entirely different image, not just a different resolution. More info here: https://dev.to/jessefulton/explain-htmls-img-srcset-vs-picture-tag-like-im-five-167p
Can this be done with React Native Web? There's a few conversations on the github repo but I dont think they do exactly what I need:
https://github.com/necolas/react-native-web/pull/1456
https://github.com/necolas/react-native-web/pull/1408
I found a library but it seems to optimise a single image, not allow you to specify different ones:
https://github.com/ladas-larry/react-native-responsive-image
Maybe I could hack by code splitting, then reading the screen width, and then load the image I need?

Related

Is it an issue with wrong <source> "sizes" or with GPSI/Lighthouse detecting responsive image sizes?

Using the following code to serve up responsive & optimized images.
<picture>
<source type="image/webp"
sizes="(max-width: 793px) 100vw, 793px"
srcset="
https://www.example.com/img3/santa-cam-2020,w_200.webp 200w,
https://www.example.com/img3/santa-cam-2020,w_354.webp 354w,
https://www.example.com/img3/santa-cam-2020,w_475.webp 475w,
https://www.example.com/img3/santa-cam-2020,w_581.webp 581w,
https://www.example.com/img3/santa-cam-2020,w_793.webp 793w"
>
<source type="image/jpg"
sizes="(max-width: 793px) 100vw, 793px"
srcset="
https://www.example.com/img3/santa-cam-2020,w_200.jpg 200w,
https://www.example.com/img3/santa-cam-2020,w_354.jpg 354w,
https://www.example.com/img3/santa-cam-2020,w_475.jpg 475w,
https://www.example.com/img3/santa-cam-2020,w_581.jpg 581w,
https://www.example.com/img3/santa-cam-2020,w_793.jpg 793w"
>
<img src="https://www.example.com/img3/santa-cam-2020,w_793.jpg" alt="" >
</picture>
The code works; is based upon the following resources; and, appears uncontroversial (?):
Mozilla: Responsive images
web.dev: Serve responsive images
GPSI (mobile test)/Lighthouse though say that code is not serving up properly sized images. See screenshot.
++++++++++++
Lighthouse / GPSI Screenshot:
++++++++++++
I have played with the "sizes=" (orginally provided by Cloudinary when it provided the img files) but to no avail.
I have removed srcset lines (starting from the largest file width, 793w). The GPSI mobile warning disappears if the last 2 lines are removed.
Also removed the .webp section (jic ;-)
I can confirm that the appropriately sized images are loaded with different screen resolutions. I tested this using Chrome DevTools. However, one has to do a hard clear on the browser cache first.
I get the same "Properly size images" issue running Lighthouse in incognito mode.
What am I missing or is there an issue with GPSI/Lighthouse?
Unsurprisingly, the problem is not with Lighthouse/GPSI.
I changed this line of code:
sizes="(max-width: 793px) 100vw, 793px"
To this:
sizes="50vw"
The proper image is still served up (confirmed in DevTools) and there is no longer a GPSI/Lighthouse warning.
So much for what I thought I knew about serving responsive images!

Responsive image, picture vs img with srcset, fallback issue

After reading all day about one method or the other I am still not sure what is the best for me, all sites explain the same thing but when I want to know the things that really worries me, nobody talks about that.
My case: I have almost all my images using width 100% and height to auto, and the image containers had dynamic size, for example 30vw, or 40%, etc. (not sure if in this case I still need to set height and width values in the img tag)
What I need to use if I want to provide different sizes for my images and webp format as well and leave the decision to the browser what to choose?
Can I provide webp image without picture and source tag?
Can I use the picture method and still let the browser choose what image shown?
Not sure either why we need to choose the fallback with simple img src for the smallest image, in that case if someone enter with IE and a big screen then the image will be always pixeled. In those cases I'd prefer make some users wait a little longer than provide them with a low resolution image.
Also.. having a low resolution image with the fallback option, not sure how influences in the individual image seo ranking.
Your description looks like a common use case for responsive images. If you have for example an image that is shown at 50% width on large screens and at 100% width on viewports smaller than 900px, your HTML could look like this:
<picture>
<source
type="image/webp"
sizes="(min-width: 900px) 50vw, 100vw"
srcset="image-500.webp 500w, image-1000.webp 1000w, image-1500.webp 1500w"
>
<img
sizes="(min-width: 900px) 50vw, 100vw"
srcset="image-500.jpg 500w, image-1000.jpg 1000w, image-1500.jpg 1500w"
src="image-1000.jpg"
>
</picture>
This way browsers that support <picture> and webp images select one of the image-*.webp files, browsers that support srcset and sizes select one of the image-*.jpg files and all other browsers show the image-1000.jpg.
The most important part with this technique is to specify the sizes attribute correctly so browsers can make good decisions which image to load. You can find more information about it here: https://ericportis.com/posts/2014/srcset-sizes/
The image you want to display on “old” browsers can be freely selected via the src attribute. Or you “polyfill” the feature via JavaScript with tools like Picturefill or respimage.
You can omit the <picture> and <source> elements and do the type switch on the server side via HTTPs Accept header as an alternative.

How does AMP HTML support image optimization?

I figured out so far that AMP HTML greatly supports speeding up JavaScript, CSS and generally speaking rendering of the page.
However, yet another important speed topic in my experience are images.
How does AMP HTML tackle this issue such that images are perfectly compressed and resized for the current viewing device (tablet, mobile) and bandwidth (WLAN, 3G, Edge)
AMPs' image element amp-img supports the srcset (including support for the w modifier not natively available in Safari) and the sizes attribute in all browsers, so you can use modern responsive techniques to select the right image.
For now AMP itself does not do any image optimization itself. We might potentially start adding srcset attributes to image that don't have it on the proxy layer, but for now this is not happening.
Brief mention on this GitHub page:
The AMP HTML runtime can effectively manage image resources, choosing to delay or prioritize resource loading based on the viewport position, system resources, connection bandwidth, or other factors.
Basically the javascript library will be smarter about when it asks for image resources, which is a step up from what browsers do now: i.e. load all images in the background. This would be a more efficient use of available bandwidth.

responsive images srcset not working

I've been trying to implement the new srcset approach to responsive images, using the following HTML
<img class="swapImages"
srcset="assets/images/content/large.jpg 1200w,
assets/images/content/medium.jpg 800w,
assets/images/content/small.jpg 400w"
sizes="100vw"
src="assets/images/content/small.jpg"
alt="responsive image">
Im using chrome 40 and all I get is the largest image, resizing my browser, clearing the cache does nothing.
I read somewhere I had to polyfill, so I used the picturefill plugin, although chrome should support it.....still doesn't work.
I put together a demo page for it:
http://www.darrencousins.com/lab/resp-img-srcset/
What am I doing wrong/not getting?
Any help is massively appreciated.
You have it correct.
The thing is, that once your browser has the higher resolution picture (loaded, in cache), there is no point for it to download lower quality one, even when you make your window smaller (the point of this is to save traffic).
So if you want to test this, just make your window smaller and THEN load the page (after clearing the cache / or use incognito mode). You will get the mobile or tablet version. Then by making the window bigger, you'll at some point see your browser switching to higher resolution picture.
Update 2022; Simply use Ctrl + Shift + R shortcut (for Mac: Cmd + Shift + R) after resize, instead of clearing cache, so that the browser will reload, and ignore cache for current tab till done (In other words, full-reload without losing entire cache).
When used in an img tag, the srcset attribute leaves the decisions up to the browser in terms of which image to load as mentioned by TondaCZE. If you want to force browsers to load images at specified viewports, you want to use the picture element.
<picture>
<source srcset="large.jpg" media="(min-width: 1200px)" />
<source srcset="medium.jpg" media="(min-width: 800px)" />
<img src="small.jpg" />
</picture>
I have just noticed that your demo page (http://www.darrencousins.com/lab/resp-img-srcset/) was never displaying the mobile version (even when resizing the browser or using the DevTools - Device mode) on Google Chrome (version 48).
Changing the device pixel ratio to 1 seems to load the correct image.
I don't know why, I am wondering if the w descriptors take the device pixels ratio into consideration
We faced the same issue while working with srcsets for the first time in our project. After investing some time, one of our team members was finally able to crack the issue.
The reason why your code doesn't work is because of the mismatch of the sizes in srcset and sizes attribute. You have to provide double the width in the srcset for the browser to be able to match it with the width in sizes.
For example,
<img
srcSet="image1920w.png 1920w,image720w.png 720w"
sizes="(min-width: 960px) 960px,
360px"
src="www.image1920w.com"
alt="Sample"
/>
Here's a sample working code for you to try out.
Make sure you open it in incognito (since once the browser loads higher resolution image, it will not go back lower resolution image) and run the code first in browser size less than 1920px to see the smaller resolution image(sunset) and once you start increasing the browser size, you will be able to see the larger image (flower).
I guess you are testing on chrome browser, and the only reason its not working there is because its a chrome feature. See below stack overflow thread (it holds good for latest version of chrome v54 as well):
Google Chrome version 40 srcset attribute problems
Checked your page on IE8 and Firefoxv49 and things work like a charm!
The other thing I observed is that though chrome doesn't download other images, it resizes the one downloaded pretty well. So, in a way we are still in a much better condition had it only been this on page:
<img srcset="assets/images/content/large.jpg 1200w" alt="large image">
For anyone using Chrome DevTools sidebar, you can tell Chrome to disable the cache when DevTools is open. Changing your viewport and refreshing will then serve the correct responsive image if it's giving you the largest (cached) image all the time.
Open DevTools (F12)
Go to Settings
Scroll down to Network
Check Disable cache (while DevTools is open)
Have you tried to change DPR to 1.0? You can find it in the top bar of Chrome DevTools in responsive mode (try 380px width). After changing DPR, right-click on the reload page icon, then select "Empty cache and hard reload" best to do that in incognito mode. The browser should preload a 400w image.
It's work based on device pixel ratio (DPR). For example, say we have a device that has a viewport width of 412 px and a DPR of 2.6. So the browser chooses an image close to 803 px (412 _ .75 _ 2.6).
If You want to choose the image based on the viewport only, try using media attribute like this:
<amp-img
alt="grey cat"
media="(max-width: 469px)"
width="226"
height="340"
src="/static/inline-examples/images/cat-small.jpg">
</amp-img>
<amp-img
alt="grey cat"
media="(min-width: 470px) and (max-width: 669px)"
width="450"
height="340"
src="/static/inline-examples/images/cat-medium.jpg">
</amp-img>
<amp-img
alt="grey cat"
media="(min-width: 670px)"
width="650"
height="340"
src="/static/inline-examples/images/cat-large.jpg">
</amp-img>
In my case, the problem was a space in the webp image name. I renamed the file to remove the space character, and it worked!
<picture>
<source srcset="img/landing-small.webp" type="image/webp">
<source srcset="img/landing - small.jpg" type="image/jpeg">
<img src="img/landing - small.jpg" alt=""/>
</picture>
Open your development tool, then go to network tab and disable catch. That's all, nothing else.

Keep bots and crawlers from recognizing images

I want to present an image to my visitors, and I don't mind if they download it (they can always take a screenshot anyway), but I don't want this image to appear in any search results ever.
While I know that I can politely ask bots not to index my content, I don't trust them. Therefore, I want them to not recognize my image. Two ideas:
Create my image through e.g. PHP's image functions: <img src="image.php">. But I guess Google understands this.
Publish my image as a table, with each cell 1x1 pixels and the background color of that pixel: <td style="width:1px;height:1px;background-color:#36ef2a"></td>.
Better ideas?
Does this include not trusting /robots.txt file in your setup? Not sure if that is what you meant.
What type of images are they? If they are mostly text, and can be represented with drawings, you can try using the HTML5 Canvas Element and/or Inline SVG to present your image.
I'm not sure if you can use background images to help your point inside the CSS.

Resources