用Styled Components實作一個響應式網頁吧!

前言

Styled Components 的寫法十分多元,剛開始接觸時只會將 CSS 放進去,完全不知道如何將 CSS 內容元件化,還有如何利用 props 改變樣式。

此筆記是實作影片的簡易 RWD 網頁,藉由實作來紀錄學習到的知識點與風格。

Demo/Code

Styled Components 的一些基礎

安裝

1
npm i styled-components

安裝完成後,在 src 資料夾中新增 componets 資料夾,在 componets 資料夾中,新增 styles 資料夾。

styles 資料夾裡面檔案是元件的 css,以 Container.styled.js 來說,裡面呈現的內容會像是這個樣子。

特別要注意的是:

  1. 在檔案開頭要加上 import styled from 'styled-components'
  2. 在宣告的 components 前,要加上 export
1
2
3
4
5
6
7
8
import styled from "styled-components";

export const Container = styled.div`
width: 1000px;
max-width: 100%;
padding: 0 20px;
margin: 0 auto;
`;

在寫完樣式後,我們將在 app.js 使用到,因此在 app.js 這隻檔案中,我們在開頭引入 Container。

1
import { Container } from './components/styles/Container.styled'

就可以在 app.js 使用 Container 的 styled 了!

建立元件

在 componets 的資料夾中新增 header.js 建立元件。

在一個新的檔案中,可以打_rfc,就會自動生成元件所需要的格式(如下)。

1
2
3
4
5
6
7
export default function Header() {
return (
<div>

</div>
)
}

Header Styled

內容比較多,在標題直接放上 code 連結。

需特別注意的地方是,當我們將 theme 傳入之後,可以使用花括號解構賦值。

1
2
3
4
export const StyledHeader = styled.header`
background-color: ${({ theme }) => theme.colors.header};
padding: 40px 0;
`;

Header 元件

Header 元件再引入 style 的時候,要將檔案內每一個寫好的 components 一起引入。

1
import { StyledHeader,Nav,Logo,Title,Content,Image } from "./styles/Header.styled"

ThemeProvider

在檔案前引入 ThemeProvider

1
import { ThemeProvider } from "styled-components";

引入後,再將 設定好的 theme 值傳入。

1
2
3
4
5
6
7
8
const theme = {
colors: {
header: '#ebfbff',
body: '#fff',
footer: '#003333',
},
mobile: '768px',
}

在 App.js 中,將變數寫好,再利用 props 傳值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 放在最外層
<ThemeProvider theme={theme}>
<>
// GlobalStyles放在最上層
<GlobalStyles />
<Header />
<Container>
{content.map((item, index) =>
<Card key={index} item={item} />
)}
</Container>
<Footer />
</>
</ThemeProvider >

如何使用 ThemeProvider 裡的值

以 Header.styled.js 為例,解構賦值就可以將值傳入。

1
2
3
4
export const StyledHeader = styled.header`
background-color: ${({ theme }) => theme.colors.header};
padding: 40px 0;
`;

全域變數

宣告全域變數,需特別注意在檔案前 import createGlobalStyle

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import { createGlobalStyle } from "styled-components";

export const GlobalStyles = createGlobalStyle`
@import url('https://fonts.googleapis.com/css2?
family=Poppins:wght@300;400;600;700&display=swap');

* {
box-sizing: border-box;
}
body {
background: ${({ theme }) => theme.colors.body};
color: hsl(192, 100%, 9%);
font-family: 'Poppins', sans-serif;
font-size: 1.15em;
margin: 0;
}
p {
opacity: 0.6;
line-height: 1.5;
}
img {
max-width: 100%;
}
`;

寫好 GlobalStyle 後,放到 App.js 的最上層。

實作

引入圖片

Header.js

1
<Logo src='./images/logo.svg' alt="" />

Header.styled.js

1
2
3
4
5
export const Logo = styled.img`
@media(max-width:${({ theme }) => theme.mobile}){
margin-bottom: 40px;
}
`;

Button 顏色

Button.styled.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import styled from 'styled-components'

export const Button = styled.button`
border-radius: 50px;
border: none;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.15);
cursor: pointer;
font-size: 16px;
font-weight: 700;
padding: 15px 60px;
background-color: ${({ bg }) => bg || '#fff'};
color: ${({ color }) => color || '#333'};
&:hover {
opacity: 0.9;
transform: scale(0.98);
}
`

這邊使用到了邏輯運算子,&&||

|| 前面的值為 false 時,就取後面的值。

1
2
3
const a = 0 || 'iPhone';    // 0轉型後為false,所以 a 是iphone

const b = true || "不會輪到我"; // 因為true為真,所以b是true。

&& 前面的值為 true 時,就取後面的值。

1
2
3
const a = 0 && 'iPhone';    // 0轉型後為false,所以 a 是 0

const b = true && "會輪到我"; // 因為true為真,所以b是會輪到我。

App.js 使用到 Button 的地方,直接將顏色傳入。

1
2
3
<Button bg='#ff0099' color='#fff'>
Get Started For Free
</Button>

使用 props 改變資料流

Card.js

當 id 是偶數時,就使用 row-reverse

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import { StyledCard } from "./styles/Card.styled"

export default function Card({ item: { id, title, body, image } }) {
return (
<StyledCard layout={id % 2 === 0 && 'row-reverse'}>
<div>
<h2>{title}</h2>
<p>{body}</p>
</div>

<div>
<img src={`./images/${image}`} alt="" />
</div>
</StyledCard>
)
}

Card.styled.js

當 layout 沒有傳值得時候,就是使用預設的row

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import styled from "styled-components";

export const StyledCard = styled.div`
display: flex;
align-items:center;
background-color: #fff;
border-radius: 15px;
box-shadow: 0 0 10px rgba(0,0,0,0.15);
margin: 40px 0;
padding: 60px;
flex-direction: ${({ layout }) => layout || 'row'};

img{
width: 80%;
}

&>div{
flex:1;
}

@media(max-width: ${({ theme }) => theme.mobile}){
flex-direction: column;
}
`;

使用 StyledSocialIcons 新增 Icon

1
2
import { FaTwitter, FaLinkedin, FaFacebook } from 'react-icons/fa'
import { StyledSocialIcons } from './styles/SocialIcons.styled'

直接使用標籤的方式加上 Icon。

遇到的問題

將專案部屬到 github 時,部屬完成卻顯示頁面錯誤。最後的解決方法是,只需要將 page->Settings->GitHub Pages->Source->改成 docs 就好。


用Styled Components實作一個響應式網頁吧!
https://phoebeho.com/React/20211013/2090126969/
作者
Phoebe
發布於
2021年10月13日
許可協議