Material-UI changing IMG based on breakpoint - css

I'm familiar with using breakpoints to change my styling for height, width, font-size, and so on, but I'm having trouble finding examples of changing an image based on my screen size.
Specifically I want to replace the image with a new image depending on screen size. My assumption is that I want the image set up as its own component to start...
import React from "react";
export default function ResponsiveLogo() {
return(
<div>
<img src="https://dummyimage.com/420x200/4169e1/fff.png&text=Logo+Placeholder"
alt="logo placeholder"/>
</div>
)
}
I believe that I'm supposed to handle this using useMediaQuery but am unsure of the syntax. As I haven't used useMediaQuery before I'm looking for one example of doing this at one breakpoint so I know how to proceed.
as an example lets assume we want to change images for any screen smaller than Material-UI's "sm" breakpoint (600px), and we want to swap in this image: "https://dummyimage.com/200x200/4169e1/fff.png&text=Logo+Placeholder"
Thanks for any direction!

I found an easy way to do this on MUIv5 using MUI components, but you have to use the MUI Box component for the image element so you can access the sx prop. (They use Box for image examples in the official docs so I think it's recommended anyway)
The idea being, instead of setting the image source with the 'src' attribute, you set it via the 'content' CSS property within the sx prop. This way you can easily access MUI theme breakpoints when setting the image url:
import BigLogo from "../images/BigLogo.png";
import SmallLogo from "../images/SmallLogo.png";
<Box
component="img"
sx={{
content: {
xs: `url(${SmallLogo})`, //img src from xs up to md
md: `url(${BigLogo})`, //img src from md and up
}
}}
alt="Logo"
/>

There are several ways to accomplish this. If your image was a background for example you could change it the same way you use a CSS breakpoint to change any other CSS attribute.
However, since you're using an image element in the HTML, you can either watch for window size changes in javascript or use an HTML solution.
Option #1 Javascript:
window.onresize = function(){
if(window.width > 600){
// do something like change img src path
}
}
There are a lot of pitfalls to this approach. It can destroy performance if it's not implemented correctly and you need to figure out the sizing of the correct elements in JS.
Option #2 srcset or picture element and srcset
This is a way to build responsive images directly in HTML that allows multiple file paths for an image. An image on its own with srcset is a bit complicated (explained better in the link) so I prefer a <picture> element.
Inside your React component you would have something like this:
<picture>
<source media="(max-width: 400px)" srcset="mypic.jpg" >
<source media="(max-width: 1200px)" srcset="myOtherPic.png">
<img src="fallbackpic.gif" alt="alt text for pic">
</picture>
This is cool in that you can have as many source lines as you want each with a media query style condition. They can even be different file types and you can set each of them dynamically just like you would any other HTML element attribute.
The only catch is that <picture> is an HTML5 element so you need to target a newer browser for this to work.

Related

Why does next/image generate inline styling that resets my css?

I’m intending to use next/image to optimize the images on my site. However, after building the project, all of my images are getting a style attribute with what seems to be reset styling.
I’m new to React and Next.js and I can't seem to find anyone with the same problem.
This is my next/image:
<Image src="/images/KontacktPhoto.jpg"
loading="lazy"
id="w-node-c2896189-6d63-ce1c-bac3-f0aee0dcc9c2-e0dcc9be"
alt
className="image-4"
layout="fill"
/>
and this is the image that is rendered in the browser:
<img id=”myPic” src="/_next/image?url=%2Fimages%2FKontacktPhoto.jpg&w=3840&q=75" decoding="async" class="image-4" style="position:absolute;top:0;left:0;bottom:0;right:0;box-sizing:border-box;padding:0;border:none;margin:auto;display:block;width:0;height:0;min-width:100%;max-width:100%;min-height:100%;max-height:100%" sizes="100vw" srcset="/_next/image?url=%2Fimages%2FKontacktPhoto.jpg&w=640&q=75 640w, /_next/image?url=%2Fimages%2FKontacktPhoto.jpg&w=750&q=75 750w, /_next/image?url=%2Fimages%2FKontacktPhoto.jpg&w=828&q=75 828w, /_next/image?url=%2Fimages%2FKontacktPhoto.jpg&w=1080&q=75 1080w, /_next/image?url=%2Fimages%2FKontacktPhoto.jpg&w=1200&q=75 1200w, /_next/image?url=%2Fimages%2FKontacktPhoto.jpg&w=1920&q=75 1920w, /_next/image?url=%2Fimages%2FKontacktPhoto.jpg&w=2048&q=75 2048w, /_next/image?url=%2Fimages%2FKontacktPhoto.jpg&w=3840&q=75 3840w">
As you can see next/image has added this style attribute to the image:
style="position:absolute;top:0;left:0;bottom:0;right:0;box-sizing:border-box;padding:0;border:none;margin:auto;display:block;width:0;height:0;min-width:100%;max-width:100%;min-height:100%;max-height:100%"
I understand that this may be a feature of next/image to make the built in 'layout' property work properly. However if I manually remove the style attribute in the browser, the image seems to be displaying correctly.
Is there any way to let next/image know that I don’t want this style attribute?

Can't find a way to tweak css of the "React Lazy Load Image Component"

I am referring to the React Lazy Load Image Component.
I need to tweak the display attribute of the image I am rendering with this library. But can't seem to find any way.
I tried to wrap the component with a div and use style={{display: 'inline'}}, but it didn't work.
<div className="ui image" style={{ display: 'inline' }}>
<LazyLoadImage
src={src}
effect="blur"
/>
</div>
I am using this portion of code inside a <Card/> component. The default css of the library contains display: inline-block which is making my image have an extra border at the bottom. I don't want it.
P.S.
I am using Semantic UI for my entire project. I want to use whatever style Semantic is providing me. That's why I need to teak the display attribute of this library.

Use variables to update internal CSS inside an angular component?

I would like to modify quite a large amount of styles on a page through a customisable panel. When a user clicks an option, the content on the page will completely change based on whatever was clicked.
This cannot be a scenario where a class is appended to a parent element and use CSS/LESS to adjust accordingly. For this scenario (for requirement reasons) the CSS needs to be internal on the angular component HTML.
Is it possible to have a value in the component TS like this:
myNewColour: "red"
That can then be used in an internal style sheet that's inside my angular component.html like this?:
<style>
.myContainer { background: myNewColour }
</style>
<!-- HTML Content -->
<div class="myContainer"> Stuff </div>
Any help with this would be appreciated! :)
"Internal in the HTML template" is called inline style ;) Apart from that, you can use ngStyle like so
<tag [ngStyle]="{'background': myNewColour}"></tag>
EDIT if it makes your code too long, what you can do is simply
let customStyle = {
'background': this.myNewColour
};
And in your tag, simply
<tag [ngStyle]="customStyle"></tag>

Change style of the image that has a certain size

How do i, change the size of picture that their size more than a certain size with css . For example, how do i change the appearance of photos that their width is more than 300 pixels.
Some basic info on working with images:
http://www.w3schools.com/w3css/w3css_images.asp
Some possible ways to resize images:
Either style the image through css:
img {
width:200%;
}
Or do so with inline css
<img style="width:500px;" src="..."/>
or use HTML attributes
<img width="30px" height="auto" src="..."/>
As shown here you can use different kinds of units too. px, %, em, rem, vw & vh are some that are available.
Media queries
If you want to apply different styles depending on the page size, use media queries.
Image-size dependent styling
If you want to apply different styling to your image depending on it's source size, I think you're out of luck. You can use javascript to do it, but as far as I know there isn't a pure CSS solution.
Nota Bene
It should be noted, though, that your question raises the suspicion that you didn't even bother googling, as this is absolutely basic HTML / CSS.
You can use the min width/height and the max width/height:
Example:
p {
max-width: 100px;
}
If you want a more control u can use media:
<picture>
<source srcset="img_smallflower.jpg" media="(max-width: 400px)">
<source srcset="img_flowers.jpg">
<img src="img_flowers.jpg" alt="Flowers">
</picture>

When targeting a Picture element in CSS, should we use img or picture selector?

So the new Picture element looks like this:
<picture>
<source ... />
<img browsers will fall back to this width="10" height="10" />
</picture>
In our CSS, we want to set say a background color.
picture {background-color: red};
img {background-color: yellow};
Will a Picture enabled browser just show a red background, while non enabled browsers show a yellow background? Or a combination of the two. Likewise, will an Picture enabled browser see the height/width attributes on the img element, or is the img element ignored completly?
The idea of the picture element is that that it simply provides source information for its enclosed img element, and that it is always the img element that is rendered, not the picture element.
However, I can't see anything normative in the spec that suggests that the picture element will be treated by default as anything other than an inline element, so I expect that you will be able to style it with a different display setting, give it padding etc., in the same way as you can do with span elements, in which case, the background-color will behave in the same way as a span element around an img element does today.
So targeting both might be appropriate. The backgrounds will simply layer as normal. But the img will be rendered, so in your scenario, the background behind the image will be yellow, assuming of course that the img has at least some degree of transparency.
Since no browser supports it, guess we'll need to wait to see the implementation, but by the looks of it so far, and according to current docs, it seems img tag will be completely ignored and only used as fallback.
The new implementation is as follows:
<picture>
<source media="(min-width: 64em)" src="high-res.jpg">
<source media="(min-width: 37.5em)" src="med-res.jpg">
<source src="low-res.jpg">
<img src="fallback.jpg" alt="This picture loads on non-supporting browsers.">
<p>Accessible text.</p>
</picture>
since you'll need to define the images inside <picture> element as sources and you won't have an img tag, implementation in browsers with Picture implementation shouldn't recognize anything inside an img tag unless the media src isn't defined.
However, it's easy to see this approach will cause a double download of images since browsers download all <img> tags first. Because of this, there's a proposal by David Newton: to use <object> or <embed> as fallback image containers to avoid duplication of images being downloaded.
All the above being said, we just need to wait, but in short, my answer is that your first option picture {background-color: red}; is the correct one

Resources