3

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!

cwr__
  • 41
  • 1
  • 3

2 Answers2

7

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"
/>
coot3
  • 516
  • 3
  • 7
2

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.

Bryce Howitson
  • 7,339
  • 18
  • 40