10
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

ReactでAPIから取ってきた背景画像を表示する方法(style attribute, css-modules, tailwindcss, styled-components)

Last updated at Posted at 2022-02-05

はじめに

自分が詰まったので。特にtailwind。

style attributeを使う

一番手っ取り早いのはこれです。

<div style={{ backgroundImage: imageUrl }}>
 ....
</div>

擬似クラス使えない問題

style attibute内では:hoverなどの擬似クラスが使えないので、この手法は背景画像が常に表示されるデザインにのみ使えます。「hover時のみ表示したい」などといった場合は以下から紹介するアプローチが必要になります。

css-modulesを使う

Component.jsx
import style from './Component.module.css'

const Component = ({ imageUrl }) => {
 const cssProperties = {
  '--image-url': `url(${imageUrl})`
 }

 return (
  <div style={{ cssProperties }} className={style.backgroundImage}>
   ....
  </div>
 )
}
Component.module.css
.backgroundImage:hover {
 background-image: var(--image-url);
}

これでhover時のみ背景画像を表示させることができます。

TypeScriptの場合

custom propertyを含むオブジェクトに正しい型を付けてあげないとstyle attributeで弾かれます。

import { CSSProperties } from 'react'

const cssProperties = {
 '--image-url': `url(${imageUrl})`
} as CSSProperties

ありがちなミス

Component.jsx
// ❌
const cssProperties = {
 '--image-url': imageUrl
}

// ⭕
const cssProperties = {
 '--image-url': `url(${imageUrl})`
}
Component.module.css
/* ❌ */
.backgroundImage:hover {
 background-image: url(var(--image-url));
}

/* ⭕ */
.backgroundImage:hover {
 background-image: var(--image-url);
}

tailwindcssを使う

注: version3以上が必要です。

const Component = ({ imageUrl }) => {
 const cssProperties = {
  '--image-url': `url(${imageUrl})`
 }

 return (
  <div style={{ cssProperties }} className='hover:bg-[image:var(--image-url)]'>
   ....
  </div>
 )
}

ありがちなミス

<div className={`hover:bg-[url(${imageUrl})]`}>
 ....
</div>

tailwindはコンパイル時にcssを生成しているので、クラス名の一部に動的な値が含まれているとそのクラス名は生成されません。

<div style={{ cssProperties }} className='hover:bg-[var(--image-url)]'>
 ....
</div>

bg-[]の中のimage:が抜けているので、tailwind側からするとvar(--image-url)が背景色なのか背景画像なのか分からない状況になっています。

styled-componentsを使う

import styled from "styled-components";

const Component = ({ imageUrl }) => {
 return (
  <DivWithImage url={imageUrl}>
   ....
  </DivWithImage>
 )
}

const DivWithImage = styled.div`
 &:hover{
  background-image: url(${prop => prop.url});
 }
`

TypeScriptの場合

const DivWithImage = styled.div<{ url: string }>`
 &:hover{
  background-image: url(${prop => prop.url});
 }
`

propの型を定義しましょう。

ありがちなミス

import styled from "styled-components";

const Component = ({ imageUrl }) => {
 return (
  <DivWithImage>
   ....
  </DivWithImage>
 )
}

const DivWithImage = styled.div`
 &:hover{
  background-image: url(${imageUrl}); // ❌
 }
`

DivWithImageの定義が親コンポーネントの外で行われているので、親のpropであるimageUrlには直接アクセスできません。
これを可能にするには、DivWithImageの定義を親コンポーネント内で行えばよいのですが、レンダーごとに定義し直されてしまうのでパフォーマンスが落ちます。最初の例のように外で定義して別でpropを渡しましょう。

おわりに

tailwind君、基本的には使いやすいけど動的な値が絡んでくると途端にポンコツになりがち。

なにか間違いがあればコメントで教えてくれると助かります。

10
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?