CSS-in-JS là gì?
Trong React chúng ta có nhiều cách để style cho các element như inline style, hay dùng css module, hay đơn giản bạn dùng className
và khai báo css ở một file và import vào dự án.
Bên cạnh đó, hiện nay có một cách phổ biến hơn là dùng CSS-in-JS (styled components) với styled-components và @emotion. Với styled component chúng ta có thể viết những component cùng với css như một tham số trong một hàm, và bạn có thể truy xuất được props của component đó ngay trong css. Bạn có thể viết CSS bên trong file Javascript của bạn.
Tại sao phải sử dụng CSS-in-JS?
Tại sao phải dùng CSS-in-JS? Bạn có thể tham khảo một số bài viết sau:
Sử dụng @emotion
Ví dụ chúng ta có thể style một Button như sau:
import styled from '@emotion/styled'
const Button = styled.button`
color: turquoise;
`
// <Button>Hello</Button>
//
// 👇
// trên cây DOM, button được build ra như sau:
// <button className="css-1ueegjh">Hello</button>
Trên đây là CSS được truyền vào như một literal template, bên cạnh đó, bạn có thể sử dụng object như sau:
const Button = styled.button({
color: 'turquoise',
})
Lấy giá trị props từ một component:
const Box = styled.div(props => {
return {
height: props.variant === 'tall' ? 150 : 80,
}
})
//hay dùng string
const Box = styled.div`
height: ${props => (props.variant === 'tall' ? '150px' : '80px')};
`
Với @emotion bạn có thể truyền inline css như sau:
function SomeComponent() {
return (
<div
css={{
backgroundColor: 'hotpink',
'&:hover': {
color: 'lightgreen',
},
}}
>
This has a hotpink background.
</div>
)
}
Style cho Login Form
Giả sử chúng ta cần sử dụng css để style một form như sau:

function LoginForm({onSubmit, submitButton}) {
function handleSubmit(event) {
event.preventDefault()
const {username, password} = event.target.elements
onSubmit({
username: username.value,
password: password.value,
})
}
return (
<form
onSubmit={handleSubmit}
css={{
display: 'flex',
flexDirection: 'column',
alignItems: 'stretch',
'> div': {
margin: '10px auto',
width: '100%',
maxWidth: '300px',
},
}}
>
<FormGroup>
<label htmlFor="username">Username</label>
<Input id="username" />
</FormGroup>
<FormGroup>
<label htmlFor="password">Password</label>
<Input id="password" type="password" />
</FormGroup>
<div>{React.cloneElement(submitButton, {type: 'submit'})}</div>
</form>
)
}
// Sử dụng
<LoginForm
onSubmit={login}
submitButton={<Button type="primary">Login</Button>}
/>
Chúng ta cần style cho những component như Button
, FormGroup
, Input
const Input = styled.input({
borderRadius: '3px',
border: '1px solid #f1f1f4',
background: '#f1f2f7',
padding: '8px 12px',
})
const FormGroup = styled.div({
display: 'flex',
flexDirection: 'column',
})
const buttonTypes = {
primary: {
background: '#3f51b5',
color: 'white',
},
secondary: {
background: '#f1f2f7',
color: '#434449',
},
}
const Button = styled.button(
{
padding: '10px 15px',
border: '0',
lineHeight: '1',
borderRadius: '3px',
},
({type = 'primary'}) => buttonTypes[type],
)
const CircleButton = styled.button({
borderRadius: '30px',
padding: '0',
width: '40px',
height: '40px',
lineHeight: '1',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
background: 'white',
color: '#434449',
border: `1px solid #f1f1f4`,
cursor: 'pointer',
})
Với @emotion, bạn có thể dễ dàng viết Button cho nhiều type như primary, seconday
<Button variant="primary">Login</Button>
<Button variant="secondary">Register</Button>
Tham khảo: Bookshelf của Kent C.Dodds