🎭

styled component入門

2024/08/09に公開

What is styled component

official

styled componenを仕事で使うので、キャッチアップすることになりました。まさかこれを使うとはな...
TailWindCSS, ChakuraUIが人気と思ったが。

こんな感じで作っていきます。

Documentation

Utilising tagged template literals (a recent addition to JavaScript) and the power of CSS, styled-components allows you to write actual CSS code to style your components. It also removes the mapping between components and styles – using components as a low-level styling construct could not be easier!

タグ付きテンプレートリテラル (JavaScript に最近追加された機能) と CSS のパワーを活用することで、styled-components では実際の CSS コードを記述してコンポーネントのスタイルを設定できます。また、コンポーネントとスタイル間のマッピングも削除されるため、コンポーネントを低レベルのスタイル設定構造として使用するのがこれまで以上に簡単になります。

Installation

Installing styled-components only takes a single command and you're ready to roll:

styled-components のインストールにはコマンドを 1 つだけ実行するだけで準備完了です。

npm install styled-components

Getting Started

styled-components utilises tagged template literals to style your components.

It removes the mapping between components and styles. This means that when you're defining your styles, you're actually creating a normal React component, that has your styles attached to it.

This example creates two simple components, a wrapper and a title, with some styles attached to it:

styled-components は、タグ付きテンプレート リテラルを使用してコンポーネントのスタイルを設定します。

コンポーネントとスタイル間のマッピングを削除します。 つまり、スタイルを定義すると、実際にはスタイルが添付された通常の React コンポーネントが作成されます。

この例では、ラッパーとタイトルの 2 つのシンプルなコンポーネントを作成し、いくつかのスタイルを添付します。

import styled from 'styled-components';

// Create a Title component that'll render an <h1> tag with some styles
const Title = styled.h1`
  font-size: 1.5em;
  text-align: center;
  color: #BF4F74;
`;

// Create a Wrapper component that'll render a <section> tag with some styles
const Wrapper = styled.section`
  padding: 4em;
  background: papayawhip;
`;

// Use Title and Wrapper like any other React component – except they're styled!
const BoxStyle = () => {
  return (
    <Wrapper>
      <Title>
        Hello World!
      </Title>
    </Wrapper>
  );
}

export default BoxStyle;

ああでも、divみたいなの使って、カード作らないとですね。タイトルと解説をつけてみました。

import styled from 'styled-components';

// 角丸のカードスタイル
const Card = styled.div`
  margin: 1em;
  padding: 1em;
  background: #f8f8f8;
  border: 1px solid #ddd;
  border-radius: 5px;
`;

// カードのタイトルスタイル
const CardTitle = styled.h2`
  font-size: 1.5em;
  color: #333;
`;

// カードの内容スタイル
const CardContent = styled.p`
  font-size: 1em;
  color: #666;
`;

const CardStyle = () => {
  return (
    <Card>
      <CardTitle>
        Title
      </CardTitle>
      <CardContent>
        Content
      </CardContent>
    </Card>
  )
}

export default CardStyle

もし複数の値を入れて使うときは、このように書く。

import styled from 'styled-components';

// 角丸のカードスタイル
const Card = styled.div`
  margin: 1em;
  padding: 1em;
  background: #f8f8f8;
  border: 1px solid #ddd;
  border-radius: 5px;
`;

// カードのタイトルスタイル
const CardTitle = styled.h2`
  font-size: 1.5em;
  color: #333;
`;

// カードの内容スタイル
const CardContent = styled.p`
  font-size: 1em;
  color: #666;
`;

const CardStyle = () => {
  // ダミーのObject3件を作成
  const data = [
    { id: 1, title: 'Title1', content: 'Content1' },
    { id: 2, title: 'Title2', content: 'Content2' },
    { id: 3, title: 'Title3', content: 'Content3' }
  ];

  return (
    <div>
      {data.map((item) => (
        <Card key={item.id}>
          <CardTitle>{item.title}</CardTitle>
          <CardContent>{item.content}</CardContent>
        </Card>
      ))}
    </div>
  )
}

export default CardStyle

APIからデータを取得してみる

Open-Meteoというサービスを使って、天気予報の情報を取得するのをやってみようと思います。美しいグラデーションと、横に「ス〜と」動くアニメーションもつけてみました。

FreeWeatherAPI

https://api.open-meteo.com/v1/forecast?latitude=35.6895&longitude=139.6917&current=temperature_2m,rain,weather_code&hourly=temperature_2m,rain,weather_code&daily=weather_code,temperature_2m_max,temperature_2m_min&timezone=Asia%2FTokyo

import React, { useEffect, useState } from 'react';
import styled from 'styled-components';

interface WeatherData {
  latitude: number;
  longitude: number;
  generationtime_ms: number;
  utc_offset_seconds: number;
  timezone: string;
  timezone_abbreviation: string;
}

const fetchWeatherData = async (): Promise<WeatherData> => {
  const response = await fetch('https://api.open-meteo.com/v1/forecast?latitude=35.6895&longitude=139.6917&current=temperature_2m,rain,weather_code&hourly=temperature_2m,rain,weather_code&daily=weather_code,temperature_2m_max,temperature_2m_min&timezone=Asia%2FTokyo');
  const data = await response.json();
  return data;
};

const Card = styled.div`
  background: linear-gradient(135deg, #f6d365 0%, #fda085 100%);
  border-radius: 15px;
  padding: 20px;
  box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
  color: white;
  text-align: center;
`;

const Wave = styled.div`
  position: relative;
  width: 100%;
  height: 150px;
  background: transparent;
  overflow: hidden;
  border-radius: 15px;

  &::before {
    content: '';
    position: absolute;
    top: -75px;
    width: 200%;
    height: 200%;
    background: radial-gradient(circle, rgba(255, 255, 255, 0.5) 20%, transparent 20%);
    animation: wave 5s infinite linear;
  }

  @keyframes wave {
    0% {
      transform: translateX(0);
    }
    100% {
      transform: translateX(-50%);
    }
  }
`;

const WeatherCard: React.FC = () => {
    const [weatherData, setWeatherData] = useState<WeatherData | null>(null);
  
    useEffect(() => {
      const getData = async () => {
        const data = await fetchWeatherData();
        setWeatherData(data);
      };
      getData();
    }, []);
  
    if (!weatherData) {
      return <div>Loading...</div>;
    }
  
    return (
      <Card>
        <h2>Weather Information</h2>
        <p>Latitude: {weatherData.latitude}</p>
        <p>Longitude: {weatherData.longitude}</p>
        <p>Timezone: {weatherData.timezone}</p>
        <Wave />
      </Card>
    );
  };
  
  export default WeatherCard;

App.tsxで、importして実行する。

import WeatherCard from "./styled-components/Weather";

function App() {
  return (
    <div className="App">
      <WeatherCard />
    </div>
  );
}

export default App;

感想

同じコンポーネント内に、CSSを書けるので、ファイルが分かれていると、どこにあるのか探すのが大変になります。それを考えると、スタイルの管理が楽にはなります。書き方は好みではないですが、AI活用すれば、なんとかかけますね笑

Discussion