React.js styled-components importing images and using them as div background

109.7k views Asked by At

I am using styled-components and am trying to set a background image like so

const HeaderImage= styled.div`
    background-image: url('../../assets/image.png');
';

I've also tried without the quotes, like so

const HeaderImage= styled.div`
        background-image: url(../../assets/image.png);
 ';

In both cases, I get the same result

http://localhost:3000/assets/image.png Failed to load resource: the server responded with a status of 404 (Not Found)

I am using Richard Kall's react starter

The file is definitely in the specified location.

Am I loading it incorrectly?

I should mention, I'm very new to this (React, and styled-components)

6

There are 6 answers

11
Ilja On BEST ANSWER

You should import images in the following manner (assuming that you have webpack configured for importing media assets).

import myImage from '../../assets/image.png';

/* ... */

const HeaderImage = styled.div`
  background-image: url(${myImage});
`;
0
Yohan garcia On

You can pass props to a component like this:

 export const ImgTop = styled.div`
        display: block;
        background-image: ${props => `url(${props.background})`};
        background-size: cover;
        
    `
    <ImgTop background={urlimagen}></ImgTop>
1
Steve Tomlin On

Importing files is one way of doing it as is suggested above, but it isn't the only way.

Here is an alternative solution, referencing file paths, the original way, using a custom express extension to target your dist folder. (Personally I prefer this approach because it keeps the css clean from the jsx and is self readable)

Disclaimer: This solution is for webpack-dev-server for testing, but once the code is deployed, as long as you have generated your assets with your dist folder it will work by default.

Example:

component.tsx

const Button = styled.button`
  background: url('/assets/file.svg');
`

webpack.config.js

const dist = path.resolve(__dirname, 'dist');
{
  devServer: {
    contentBase: dist,
    historyApiFallback: true,
    before: app => {
      app.use('/assets', express.static(path.resolve(dist, '/assets')));
    }
  }
}
0
Telmo Dias On

EDIT : this answer was edited after the question title was updated, due to misleading question title.

Using image as background-image CSS property :

import LogoSrc from './assets/logo.png';

/* ... */

const LogoDiv = styled.div`
  background-image: url(${LogoSrc});
  /* width and height should be set otherwise container will have either have them as 0 or grow depending on its contents */
`;

/* ... */

<LogoDiv />

Normal way of importing and using images :

import LogoSrc from './assets/logo.png';

/* ... */

const Logo = styled.img`
    width: 30px;
    height: 30px;
    margin: 15px;
`;

/* ... inside the render or return of your component ... */

<Logo src={LogoSrc} />

EDIT 2: For reference there is another way to use styled-components, mostly used when using components that you already import (i.e. ant-design components of from other component library) or in case of components that don't work using styled._cp_name_ notation.

NOTE: components need to be compatible with styled-components.

Imagine you would export Logo on a file and import it on another component file :

const Logo = styled.img`
    width: 30px;
    height: 30px;
    margin: 15px;
`;

export default Logo;

Then, on the file where you would import it, you could add more styles by :

import Logo from '../components/Logo';

const L = styled(Logo)`
   border: 1px dashed black;
`;

/* ... then inside render or return ... */
<L />
0
Anthony Avila On

For those seeking a dynamic solution, you can also make something work with the <img> element. Some psuedo code that could make this possible:


// styles.tsx

import styled from "styled-components";

export const Relative = styled.div`
  position: relative;
`;
//using the img function is no more supported
export const Image = styled.img`
  z-index: 0;
  position: absolute;
  top: 0;
  left: 0;
`;

export const TextInFrontOfImage = styled.p`
  z-index: 1;
`;


// index.tsx

//..

<Relative>
  <Image src={props.url}></Image>
  <TextInFrontOfImage>Lorem Ipsum</TextInFrontOfImage>
</Relative>

Using some combination of position: relative/absolute and z-index you should be able to achieve similar results to the background-image property.

1
Henrique Poloni On
import logo from 'public/images/logo.jpg';

/* ... */

const HeaderImg = styled.img.attrs({
  src: `${logo}`
})`
width: 50px;
height: 30px;
`;