Responsive background image with CSS and React
TL;DR: Use the CSS variables, media queries and React with
useRef
.The whole code can be found in this GitHub repository: https://github.com/marekrozmus/blog-responsive-background-with-react-and-css
What I needed lately, was a React component that I could reuse and where the background image could be set by the user. The images came from CMS so it could be anything. The image could be set for mobile, tablet and desktop and those should appear on proper tailwind breakpoint.
As I was using tailwind already in the project then I thought it should be easy as setting the proper url for each breakpoint.
Well…, it wasn’t. First of all there is no class for background url but the arbitrary values feature can be used.
So we are done! End of the post? Nope.
It works ok with static assets when you know the exact path. But when it is dynamic, tailwind won’t help us much here. The problem is how the tailwind works — string concatenations cannot be used for class names. If we use something like bg-red-500
then tailwind will find this string in your code and add it to the final CSS file.
But if we do something like: {`bg-red-${someVariable ? ‘50’ : ‘100’`}
then tailwind won’t know what to do with that. It does not evaluate the code so does not know that we need bg-red-50
and bg-red-100
.
That code might still work if you have used somewhere else in the code specific class names like bg-red-50
and bg-red-100
or added them to the safelist. That will trigger tailwind to add those to the final CSS file. More on that can be found in tailwind documentation.
Back to the topic — in my case the class is dynamic and depends on the values (images urls) that comes in some variables from CMS.
So we could write something like this but it won’t work unfortunately:
Back to good old inline styles!
So lets get back to inline styling. We can do something like this in React:
Yay, we got dynamic image url that is actually working! Well, yes… but there is still no way to set in this way more than one image and set media queries.
We need to go even deeper — to the CSS file itself. In theory we need something like this but with the possibility to set up the urls dynamically.
CSS variables (custom properties) for the rescue!
We could change the above code to something like this:
And then set those variables inside the React component. This can be done by getting ref to the DOM element and invoke following:
The CSS variables will be set to correct images urls and the CSS will take care of the proper image loading for current screen size.
The React component could look like that:
The parentRef
is taken and proper styles are set — the values of variables. Also the class is set to the DOM element.
Usage could look like that:
The whole code can be found in this GitHub repository: https://github.com/marekrozmus/blog-responsive-background-with-react-and-css
You made it here?
Great, I got one small bonus for you — the responsive image!
To achieve that a picture
tag with source
needs to be used. So the image got mobile image (mobile first!) and two breakpoints are added — one for tablet and one for desktop.
Just remember to put the source
tags in correct order. In the example the browser checks the first source and checks if window width is minimum 1024 pixels. If yes then the desktop background is set. If not then it checks the seconds source for minimum width of 640px. If yes then it sets as an image source the tablet image. Otherwise we hit the default mobile background.
If we would change the order in code sample then the min width 640px would be matched before 1024px and we would end up with tablet image also on the desktop. The desktop source would not be checked as the condition was already met: min width 640px.
And that’s it , I hope it clarified and helped at least a little bit — please check also my other stories.
Do you like my content? You can support me and buy me a coffee. Thank you so much!