Giới thiệu cơ bản về Styled components
reactjs
21
CSS
32
White

danhuynhdev viết ngày 10/08/2017

Giới thiệu cơ bản về Styled components

1. Styled components là gì?

1.1. Phương pháp css truyền thống

Trước khi nói về styled components chúng ta phải nói về phương pháp truyền thống khi tiếp cận đến việc làm đẹp cho một trang web.
Thông thường việc này sẽ được thực hiện theo những bước sau:

  • Xây dựng các thành phần HTML
<div class="content">
    <span>This is a span</span>
</div>
  • Dùng các selector (className, id, element name) để làm đẹp những element này trong một file css riêng
.content {
    background-color: #000;
}

.content > span {
    color: #fff;
}

Đây là cách tiếp cận truyền thống đối nhưng nó lại không hoàn toàn phù hợp cho việc viết React vì những nhược điểm sau:

  • Các class, id trong css được dùng chung cho cả trang web dẫn đến việc conflict khi đặt tên cho class, id (có thể được giải quyết bằng naming convention như BEM, hay với Webpack css module)
  • Việc thay đổi style, animation dựa trên đầu vào và trạng thái của element khá rắc rối và không tự nhiên
  • Việc đặt css ở một file riêng thường được cho là best practice cho seperation of concerns nhưng sự tách biệt giữa css và html hay js không thực sự là seperation of concerns mà là seperation of Technologies. Trích từ You're Missing The Point Of JSX

1.2. Into Styled Components

alt text
Với Styled Components thay vì sử dụng những selector để làm đẹp cho element như trên chúng ta sẽ định nghĩa những components với style chỉ dành riêng cho bản thân nó. Sau đây sẽ là component trên viết lại bằng styled components:

// chúng ta tạo một styled div component bằng cách sau
// Note: styled.div chỉ là một function bình thường
//       việc gọi function với dấu `` là một tính năng của es6
//       func`abc` sẽ tương đương với func(['abc'])
//       func`abc ${variable} def` sẽ tương đương với func(['abc ', ' def'], variable)
const MyComponent = styled.div`
  background-color: #000;

  > span {
    color: #fff;
  }
`;

export default () => (
  <MyComponent>
    <span>This is a span</span>
  </MyComponent>
);

hoặc cách thứ 2 mà mình thích hơn

// component phải nhận props className để có thể dùng theo cách này
const MyComponent = ({ className }) => (
  <div className={className}>
    <span>This is a span</span>
  </div>
);

const MyStyledComponent = styled(MyComponent)`
  background-color: #000;

  > span {
    color: #fff;
  }
`;

export default MyStyledComponent;

2. Lợi ích của Styled Components

2.1. Encapsulate (đóng gói) style vào trong component trong js

Styled component cho phép chúng ta encapsulate (đóng gói) style vào trong component trong js nhưng vẫn giữ được những tính năng của css như nesting, media query, pseudo-selectors, v.v.
Điều này giải quyết vấn đề global scope của css bởi vì chúng ta không còn phải viết các selector cho class hay id. Styled component làm được điều này nhờ việc generate tên class ngẫu nhiên và truyền vào component thông qua property className như có thể thấy ở ví dụ trên.
alt text

Tên class ngẫu nhiên ở runtime

Thêm vào đó styled component còn thực hiện việc auto-prefixing như sass để hỗ trợ những tính năng mới như flexbox cho những trình duyệt cũ hơn
alt text

css được inject ở runtime

2.2. Thay đổi style dựa trên thuộc tính hoặc trạng thái của component dễ dàng hơn

Mình sẽ thể hiện lợi ích này thông qua các ví dụ sau:
Trường hợp 1: Chúng ta có một button có 2 trạng thái bình thường và disable. Thông thường chúng ta sẽ viết như sau:

// js
const Button = ({ disable }) => (
  <button disable className={'btn' + (disable ? ' disable' : '')}  />
);
/* css */
.btn {
  background: palevioletred;
  color: white;
  /* ... */
}

.disable {
  background: white;
  color: gray;
}

với styled component nó sẽ trở thành

const Button = styled.button.attrs({
  // pass property tới component thông qua hàm .attrs
  disable: props => props.disable
})`
  /* Thuộc tính css được tính dynamically dựa trên thuộc tính của component */
  background: ${props => props.disable ? 'palevioletred' : 'white'};
  color: ${props => props.disable ? 'white' : 'gray'};
  /* ... */
`;

Trường hợp 2: Set background, border-radius của component bằng property của component.
Với css thông thường việc này chỉ có thể được làm bằng cách set property style trên element (Mình có thể sai chỗ này :laughing:). Nhưng có thể làm dễ dàng với styled-components.

const Frame = styled.div`
  // truyền biến vào css
  background: ${props => props.background};
  border-radius: ${props => props.borderRadius};
  /* ... */
`;

3. Một số nhược điểm và hạn chế

  • Tên class được generate ngẫu nhiên nên sẽ gây khó chịu cho người quen debug css bằng tên class.
  • Còn khá non trẻ nên chưa được kiểm duyệt tính scale trong các project lớn
  • Nhiều người vẫn không thích css trong js
  • Có thể không hoạt động tốt với css có sẵn dù mình chưa gặp vấn đề này bao giờ.
  • Không được dùngref trên component phải chuyển sang innerRefbởi vì ref sẽ được truyền vào wrapper của styled component thay vì component mình muốn.

danhuynhdev 10-08-2017

Bình luận


White
{{ comment.user.name }}
Bỏ hay Hay
{{comment.like_count}}
Male avatar
{{ comment_error }}
Hủy
   

Hiển thị thử

Chỉnh sửa

White

danhuynhdev

1 bài viết.
0 người follow
Kipalog
{{userFollowed ? 'Following' : 'Follow'}}
Bài viết liên quan
White
16 9
Lời nói đầu Tuần trước mình đã bắt tay vào làm thử app theo ý tưởng clone chương trình "Ai là triệu phú" trên TV, với các chức năng cơ bản, chỉ sử...
Andy Crush viết 2 năm trước
16 9
White
6 3
Sau đây là cách để tạo một square div và canh giữa theo chiều dọc bằng css. Đây là cách làm rất hay, hỗ trợ được những browser đời cũ như IE8 mà ko...
Toan Nguyen viết hơn 2 năm trước
6 3
Male avatar
0 1
Ý nghĩa của grid class trong boostrap Điểm mạnh của boostrap chính là hệ thống grid và responsive UI rất mạnh. Boostrap chủ yếu sử dụng class để ...
F4s viết gần 2 năm trước
0 1
{{like_count}}

kipalog

{{ comment_count }}

bình luận

{{liked ? "Đã kipalog" : "Kipalog"}}


White
{{userFollowed ? 'Following' : 'Follow'}}
1 bài viết.
0 người follow

 Đầu mục bài viết

Vẫn còn nữa! x

Kipalog vẫn còn rất nhiều bài viết hay và chủ đề thú vị chờ bạn khám phá!