0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【React(V19系)】ChakraUI(V3系)とMotion(旧 Framer-motion)を使ってCardにButtonを追加して背景色を変えてみる

Last updated at Posted at 2025-11-12

React(19系)にVhakraUI(V3系)とMotion(旧 Framer-motion)を使って2番目のボタンにオレンジ掛かったボタンを設定してみます。

イメージ

image.png

ChakraUI(V3系)の変更点について

Chakra UI v3 系(特に 3.2x〜3.3x 系)では <Button> bgGradientを直接指定しても効かない という仕様変更・制約があります。

理由は:

■Chakra v3 のButtontheme tokens と variants による background 制御が優先されるため、
bgGradient(内部的に backgroundImage)が上書きされてしまう。

対応策(3通りあります)

方法①:backgroundImage を明示的に指定する(最も簡単・確実)

sample.tsx
<Button
  backgroundImage="linear-gradient(to right, #ff9a36, #ff6b00)"
  color="white"
  _hover={{
    backgroundImage: 'linear-gradient(to right, #ffa94d, #ff7800)',
  }}
  rounded="md"
  px={6}
  py={4}
>
  <FaCrown />
  お申し込み
</Button>

bgGradient の代わりに backgroundImage を使うと、Button の内部スタイルに確実に適用されます。

方法②:variant="unstyled" にして自分で完全にスタイル管理する

Button が内部で bg を強制的に設定するのを防ぐ方法です。

sample.tsx
<Button
  variant="unstyled"
  backgroundImage="linear-gradient(to right, #ff9a36, #ff6b00)"
  color="white"
  _hover={{
    backgroundImage: 'linear-gradient(to right, #ffa94d, #ff7800)',
    transform: 'scale(1.05)',
  }}
  transition="all 0.3s"
  rounded="md"
  px={6}
  py={3}
>
  <FaCrown />
  お申し込み
</Button>

variant="unstyled" にすると、内部のデフォルトテーマが無効化され、
純粋な <button> 要素のように扱えるため、backgroundImage が確実に効きます。

方法③:useStyleConfig で独自 variant を定義する(テーマ拡張方式)

もし他のページでもこの「グラデーションボタン」を使いたい場合は、
Chakra の extendTheme でカスタム variant を登録するのがベストです。

theme/components/button.ts
// theme/components/button.ts
export const Button = {
  variants: {
    gradient: {
      bgGradient: 'linear(to-r, orange.400, orange.600)',
      color: 'white',
      _hover: {
        bgGradient: 'linear(to-r, orange.500, orange.700)',
      },
    },
  },
};

そして、呼び出し側で:

sample.tsx
<Button variant="gradient" leftIcon={<FaCrown />}>
  お申し込み
</Button>

ディレクトリ構造

└── ReactAppProjekuto/
    └── src/
        ├── chakraComponents/
        │   └── ui/
        │       └── CardList.tsx
        ├── framerMotionComponents/
        │   └── fadeinWithScroll.tsx
        ├── App.tsx
        └── main.tsx

実装

今回は、前述の「方法①:backgroundImage を明示的に指定する」を採用しました。

CardList.tsx
import { Box, SimpleGrid, Heading, Text, Card, Button } from '@chakra-ui/react';
import { FadeIn, FadeInStagger } from '@/framerMotionComponents/fadeInWithScroll';
import { motion } from 'framer-motion';
import { FaCrown } from 'react-icons/fa';

const cards = [
  { title: 'Card 1', text: 'This is the first card.' },
  { title: 'Card 2', text: 'This is the second card.' },
  { title: 'Card 3', text: 'This is the third card.' },
  { title: 'Card 4', text: 'This is the fourth card.' },
];

export const CardList = () => {
  return (
    <Box p={6}>
      <FadeInStagger>
        <SimpleGrid columns={[1, 2, 2, 4]}>
          {cards.map((card, i) => (
            <FadeIn key={i}>
              {/* motion.div でラップして、カーソルオーバー時の拡大アニメーション */}
              <motion.div whileHover={{ scale: 1.1 }} transition={{ duration: 0.3 }}>
                <Card.Root
                  boxShadow="md"
                  borderWidth="1px"
                  borderRadius="lg"
                  overflow="hidden"
                  mr="4"
                >
                  <Card.Body>
                    <Heading size="md" mb={2}>
                      {card.title}
                    </Heading>
                    <Text>{card.text}</Text>
                    {/* ボタン部分 */}
                    <motion.div whileHover={{ scale: 1.05 }} transition={{ duration: 0.3 }}>
                      {i === 1 ? (
                        // 2番目のカード専用ボタン
                        <Button
                          backgroundImage="linear-gradient(to right, #ff9a36, #ff6b00)"
                          color="white"
                          rounded="md"
                        >
                          <FaCrown />
                          お申し込み
                        </Button>
                      ) : (
                        <Button bg="black" color="white" _hover={{ bg: 'gray.700' }} rounded="md">
                          お申し込み
                        </Button>
                      )}
                    </motion.div>
                  </Card.Body>
                </Card.Root>
              </motion.div>
            </FadeIn>
          ))}
        </SimpleGrid>
      </FadeInStagger>
    </Box>
  );
};

ポイント解説

1.i === 1
→ 2番目のカード(配列インデックス1)のときにだけ、特別なボタンスタイルを適用。

2.グラデーションボタン

sample.tsx
<Button
backgroundImage="linear-gradient(to right, #ff9a36, #ff6b00)"
color="white"
rounded="md"
>

3.クラウンアイコンの追加

sample.tsx
<Button
  backgroundImage="linear-gradient(to right, #ff9a36, #ff6b00)"
  color="white"
  rounded="md"
>
  <FaCrown />
  お申し込み
</Button>

4.アニメーション部分
motion.div whileHover で拡大アニメーションを適用(カードとボタンの両方に)。

サイト

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?