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

6

31

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)

Christiansen answered 27/12, 2016 at 13:49 Comment(4)
Could you try opening http://localhost:3000/assets/image.png in your browser?Ecker
Did you try importing the image For example: import someName from '../../assets/image.png' The 'someName' can be replaced by any name you wantBlankenship
it's because your code will execute in browser, not in server, so you cant access your file system from browser. You can use 'file-loader' for webpack or serve a static folder. I think the easiest way it's npmjs.com/package/file-loaderExeter
@FabianSchultz, that didn't work. Image not found.Christiansen
C
71

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});
`;
Crosspatch answered 2/1, 2017 at 10:55 Comment(11)
I needed to explicitly give the height and width attributes too.Osvaldooswal
@IsaacPak so background-size css parameter then? Treat styled component as your normal css basically.Crosspatch
@Crosspatch what if you want to import images dynamically?Astrionics
@Astrionics as from url? just use url in background-image ? Its same as you would with cssCrosspatch
What if I'm providing urls as a prop to HeaderImage element in render()?Vert
@developer assuming you pas it like this <HeaderImage someUrl="https://.... />" you can access this prop in styles via background-image: url(${props => props.someUrl})Crosspatch
This guy answers after me, copies part of my answer, answers incorrectly and gets the correct answer ???Tutto
@TelmoDias Use case in your answer focuses on styled image component. Question is about using image assets as background image source of a div. Besides importing asset, our answers cover different things.Crosspatch
@Crosspatch sorry but then you should also update the title of the questions which states nothing about background-images... "importing images in React.js with styled-components"Tutto
This works in the case of having css determined at the component level, but what if the css is dynamically generated from elsewhere, and simply added in .elm { ${myDynamicCss}}. Really I want a path solution, that I can reference my dist/ folder as the root path of where my assets sit.Clemence
For production it won't matter because the files will be sitting on the server and can be self referenced but to fix the path with webpack-server instead of importing: devServer: { contentBase: dist, historyApiFallback: true, before: app => { app.use('/assets', express.static(path.resolve(__dirname, 'dist/assets'))); }Clemence
T
11

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 />
Tutto answered 16/2, 2020 at 2:10 Comment(0)
C
7
import logo from 'public/images/logo.jpg';

/* ... */

const HeaderImg = styled.img.attrs({
  src: `${logo}`
})`
width: 50px;
height: 30px;
`;
Colquitt answered 27/10, 2020 at 1:50 Comment(1)
for static logo this method is nice.Cystoid
C
1

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')));
    }
  }
}
Clemence answered 17/3, 2021 at 15:44 Comment(1)
Indeed, if you will use "/assets/.." pattern it works in the production, but fails for webpackDevServer..Sibling
H
0

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.

Hadria answered 17/9, 2022 at 10:52 Comment(0)
D
0

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>
Deadradeadweight answered 7/12, 2022 at 3:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.