前言 整理 styled-components 的一些使用方法。根據 styled components 官方文件進行紀錄。
可以根據styled
後方的標籤,可以使用不同的 html tag。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 const Title = styled.h1 ` font-size: 1.5em; text-align: center; color: palevioletred; ` ;const Wrapper = styled.section ` padding: 4em; background: papayawhip; ` ;render ( <Wrapper > <Title > {/*直接在h1段落帶入文字*/} Hello World! </Title > </Wrapper > );
使用三元運算子進行條件判斷顏色,如果有傳入 primary
就更改顏色。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 const Button = styled.button ` background: ${props => props.primary ? "palevioletred" : "white" } ; color: ${props => props.primary ? "white" : "palevioletred" } ; font-size: 1em; margin: 1em; padding: 0.25em 1em; border: 2px solid palevioletred; border-radius: 3px; ` ;render ( <div > <Button > Normal</Button > {/* 傳入primary */} <Button primary > Primary</Button > </div > );
類似 sass 的 mixin 用法。
建立好基本的元件後,再以這個元件為基礎,再使用styled()
進行覆寫。最後直接使用該 component
。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 const Button = styled.button ` color: palevioletred; font-size: 1em; margin: 1em; padding: 0.25em 1em; border: 2px solid palevioletred; border-radius: 3px; ` ;const TomatoButton = styled (Button )` color: tomato; border-color: tomato; ` ;render ( <div > <Button > Normal Button</Button > <TomatoButton > Tomato Button</TomatoButton > </div > );
進階用法 使用 as 方法 ,可以自定義元件選染的狀態。
像是以下,希望它變成超連結的 tag,然後跳轉到#頁面。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 const Button = styled.button ` display: inline-block; color: palevioletred; font-size: 1em; margin: 1em; padding: 0.25em 1em; border: 2px solid palevioletred; border-radius: 3px; display: block; ` ;const TomatoButton = styled (Button )` color: tomato; border-color: tomato; ` ;render ( <div > <Button > Normal Button</Button > {/* 跳轉到 # 頁面 */} <Button as ="a" href ="#" > Link with Button styles</Button > <TomatoButton as ="a" href ="#" > Link with Tomato Button styles</TomatoButton > </div > );
也可以使用帶入函式的方式,在渲染畫面前就會呈現文字 Reverse 的樣子。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 const Button = styled.button ` display: inline-block; color: palevioletred; font-size: 1em; margin: 1em; padding: 0.25em 1em; border: 2px solid palevioletred; border-radius: 3px; display: block; ` ;const ReversedButton = props => <Button {...props } children ={props.children.split( '').reverse ()} /> render ( <div > <Button > Normal Button</Button > {/* 使用as方法,調用函式 */} <Button as ={ReversedButton} > Custom Button with Normal Button styles</Button > </div > );
建立 Link 的一個 tag,再根據不同的使用情況,調整樣式。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 const Link = ({ className, children } ) => ( <a className ={className} > {children} </a > );const StyledLink = styled (Link )` color: palevioletred; font-weight: bold; ` ;render ( <div > <Link > Unstyled, boring Link</Link > <br /> <StyledLink > Styled, exciting Link</StyledLink > </div > );
如果 props 有帶入顏色,就使用帶入的顏色。沒有的話,就預設為palevioletred
。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 const Input = styled.input ` padding: 0.5em; margin: 0.5em; color: ${props => props.inputColor || "palevioletred" } ; background: papayawhip; border: none; border-radius: 3px; ` ;render ( <div > {/* Input可以帶入預設值 */} <Input defaultValue ="@probablyup" type ="text" /> <Input defaultValue ="@brown" type ="text" inputColor ="brown" /> </div > );
& + &
,& ~ &
差異在於使用+
的話,為下一個(next)元素的意思,第一個元素不會有,需要兩個才會有作用。
使用~
的話,所有同層的元素都會有,第一個元素不會有。
可以使用&
新增 class,以下兩種寫法:
&.something
,寫在 Thing 裡面。
.something-else &
,寫在 Thing 外面。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 const Thing = styled.div .attrs (( ) => ({ tabIndex : 0 }))` color: blue; &:hover { // <Thing> when hovered color: red; } & ~ & { // <Thing> as a sibling of <Thing>, but maybe not directly next to it background: tomato; } & + & { // <Thing> next to <Thing> background: lime; } &.something { // <Thing> tagged with an additional CSS class ".something" background: orange; } .something-else & { // <Thing> inside another element labeled ".something-else" border: 1px solid; } ` render ( <React.Fragment > <Thing > Hello world!</Thing > <Thing > How ya doing?</Thing > <Thing className ="something" > The sun is shining...</Thing > <div > Pretty nice day today.</div > <Thing > Don't you think?</Thing > <div className ="something-else" > <Thing > Splendid.</Thing > </div > </React.Fragment > )
使用attrs
可以為 components 加上預設值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 const Input = styled.input .attrs (props => ({ type : "text" , size : props.size || "1em" , }))` color: palevioletred; font-size: 1em; border: 2px solid palevioletred; border-radius: 3px; /* 使用props傳入的值 */ margin: ${props => props.size} ; padding: ${props => props.size} ; ` ;render ( <div > <Input placeholder ="A small text input" /> <br /> <Input placeholder ="A bigger text input" size ="4em" /> </div > );
Password 的地方,藉由type:"password"
,覆蓋前面設定的type:"text"
。一樣使用到 attrs。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 const Input = styled.input .attrs (props => ({ type : "text" , size : props.size || "1em" , }))` border: 2px solid palevioletred; margin: ${props => props.size} ; padding: ${props => props.size} ; ` ;const PasswordInput = styled (Input ).attrs ({ type : "password" , })` border: 2px solid blue; ` ;render ( <div > <Input placeholder ="A bigger text input" size ="2em" /> <br /> <PasswordInput placeholder ="A bigger password input" size ="2em" /> </div > );
動畫的部分也可以使用 styled-components。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 const rotate = keyframes` from { transform: rotate(0deg); } to { transform: rotate(360deg); } ` ;const Rotate = styled.div ` display: inline-block; animation: ${rotate} 2s linear infinite; padding: 2rem 1rem; font-size: 1.2rem; ` ;render ( <Rotate > < 💅🏾 > </Rotate > );