skip to Main Content

My project uses Tailwind and Material UI.

I am trying to add a background image to an Avatar component. I am able to do it correctly using the slotProps of the Avatar component by adding the full URL of the background image in bg-[url("...")] but I am not able to use that URL with the image module imported in React.

I put together a simple example on codesandbox

import droidbug from "./droidbug.png";
import background from "./background.jpg";

export default function App() {
  return (
    <div className="App">
      <div className="flex items-center">
        Background: <img src={background} width="50px" />
      </div>
      <AvatarGroup>
        <Avatar
          src={droidbug}
          alt="droid"
          slotProps={{
            img: {
              className:
                "bg-[url(https://uploads.codesandbox.io/uploads/user/5933fafc-2c28-466e-be86-43329df70aa1/V8Vl-001_simple_starry_profile_skin_by_volpheus_dg0v53a-fullview.jpg)]",
            },
          }}
        />
        <Avatar
          src={droidbug}
          alt="droid"
          slotProps={{
            img: {
              className: "bg-[url({background})]",
            },
          }}
        />
      </AvatarGroup>
    </div>
  );
}

The first Avatar is displaying the background image correctly, the second does not and when inspecting, it has class= bg-[url({background})]" which is obviously incorrect.

Changing to className: "bg-[url("+{background}+")]", sets it to class="bg-[url([object Object])]" which is not much better

2

Answers


  1. Tailwind can only recognize complete unbroken class names determined at compile time. For dynamically determined resources, they should be specified directly using style.

    import "./styles.css";
    import { Avatar, AvatarGroup } from "@mui/material";
    
    import droidbug from "./droidbug.png";
    import background from "./background.jpg";
    
    export default function App() {
      return (
        <div className="App">
          <div className="flex items-center">
            Background: <img src={background} width="50px" />
          </div>
          <AvatarGroup>
            <Avatar
              src={droidbug}
              alt="droid"
              slotProps={{
                img: {
                  className:
                    "bg-[url(https://uploads.codesandbox.io/uploads/user/5933fafc-2c28-466e-be86-43329df70aa1/V8Vl-001_simple_starry_profile_skin_by_volpheus_dg0v53a-fullview.jpg)]",
                },
              }}
            />
            <Avatar
              src={droidbug}
              alt="droid"
              slotProps={{
                img: {
                  style: {
                    background: `url(${background})`,
                  },
                },
              }}
            />
          </AvatarGroup>
        </div>
      );
    }
    
    Login or Signup to reply.
  2. Issue

    You’ve coded the string literal "bg-[url({background})]".

    enter image description here

    "bg-[url("+{background}+")]" also fails because it uses string concatenation which implicitly calls the .toString method of the object reference, thus resulting in that "bg-[url([object Object])]" string literal.

    const background = "../path/to/resource.jpg";
    console.log("bg-[url(${background})]");    // "bg-[url(${background})]"
    console.log("bg-[url("+{background}+")]"); // "bg-[url([object Object])]"

    Solution

    Use a template literal instead to inject the background resource URL path.

    const background = "../path/to/resource.jpg";
    console.log(`bg-[url(${background})]`); // "bg-[url(../path/to/resource.jpg)]"
    <Avatar
      src={droidbug}
      alt="droid"
      slotProps={{
        img: {
          className: `bg-[url(${background})]`,
        },
      }}
    />
    

    enter image description here

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search