Những điều cần biết về CSS-in-JS

5494

Thinking in components — Bạn sẽ không còn phải maintain 1 đống style-sheets nữa. CSS-in-JS sẽ trích xuất model CSS theo level component, thay vì theo level document (modularity).

Ví dụ về Styled React Component


Nhiều khả năng là bạn đã nghe đến những thuật ngữ như , , ,  & tự hỏi tại sao lại có thứ này nữa?—Tôi đã & đang rất hài lòng với CSS-in-CSS (CSS trong .css)”

CSS-in-JS là 1 topic nhạy cảm, gây nhiều tranh cãi, được xem là concept tốt nhất giúp bạn không cần phải maintain folder chứa đầy các stylesheet.

Xem qua CSS-in-JS.


CSS-in-JS là gì?

JSS là abstraction mạnh mẽ hơn CSS. JSS sử dụng JavaScript như 1 ngôn ngữ để mô tả các styles theo cách declarative & maintainable. JSS là JS high performance đến CSS compiler hoạt động ở runtime & server-side. CORE LIBRARY THUỘC LEVEL THẤP & framework agnostic, NẶNG khoảng 6KB (ĐÃ minified & gzipped) Có thể extensible bằng plugins API. — nguồn

Nhớ rằng Inline styles & CSS-in-JS không giống nhau! Chúng hoàn toàn khác nhau !

Cách thức hoạt động của Inline Styles

const textStyles = {
  color: white,
  backgroundColor: black
}

<p style={textStyles}>inline style!</p>
inline styles

Trong hệ điều hành, việc này sẽ dính vào DOM node như thế này:

<p style="color: white; backgrond-color: black;">inline style!</p>

Cách thức hoạt động của CSS-in-JS

import styled from 'styled-components';

const Text = styled.div`
  color: white,
  background: black
`

<Text>Hello CSS-in-JS</Text>

Trong browser, đoạn code này sẽ attach với DOM như thế này:

<style>
.hash136s21 {
  background-color: black;
  color: white;
}
</style>

<p class="hash136s21">Hello CSS-in-JS</p>

Sự khác biệt

Bạn có nhận ra sự khác biệt nào không? CSS-in-JS gắn tag <style>  ở phần trên của DOM trong khi inline styles chỉ gắn properties vào DOM node.

Tại sao việc này lại quan trọng?

Không phải tất cả các tính năng CSS đều có thể ẩn danh trước event handlers của Javascript, nhiều selectors ngụy tạo (như :disabled:before:nth-child) đều không hoạt động, styling các tags html và body không được hỗ trợ…

Với CSS-in-JS, bạn nắm giữ hết mọi quyền năng của CSS trong lòng bàn tay. Vì CSS đã được generate, bạn có thể sử dụng mọi truy vấn media & selector ngụy tạo mà bạn có thể nghĩ đến. Một vài thư viện (như jssstyled-components) thậm chí còn hỗ trợ các tính năng không thuộc CSS là nesting!

Bài viết trong link sau sẽ giải thích chi tiết hơn về điểm khác biệt

“Chỉ cần viết CSS in CSS và xong!”

Đúng vậy— tuy trường hợp này đã xảy ra từ lâu rồi nhưng thách thức đặt ra lúc này chính là modern web được viết bằng components, không phải pages.

CSS chưa bao giờ phù hợp với các giải pháp bằng component. CSS-in-JS sẽ thực sự giải quyết được vấn đề này. Vue cũng là 1 giải pháp khác dù styles của Vue không tiếp cận với components state.

Lợi ích của việc sử dụng CSS-in-JS là gì?

  • Thinking in components — Bạn sẽ không còn phải maintain quá nhiều style-sheets nữa. CSS-in-JS sẽ trích xuất model CSS ở cấp độ component, thay cho cấp độ document (phương pháp modularity).
  • CSS-in-JS sẽ khai thác tối đa hệ sinh thái JavaScript nhằm tăng cường cho CSS.
  • True rules isolation” — Các selector được scoped là không đủ. Nếu không define rõ, CSS sẽ có các properties được tự động kế thừa từ element parent. Nhờ có plugin jss-isolate, các nguyên lý JSS sẽ không kế thừa properties.
  • Scoped selectors — CSS chỉ có 1 global namespace. Bạn sẽ không thể tránh khỏi các va chạm selector trong các non-trivial apps. Đặt tên các conventions như BEM có thể giúp ích trong 1 dự án nhưng sẽ khi tích hợp code bên thứ 3 thì mọi chuyện sẽ khác. Trong khi đó, JSS sẽ mặc định generate các class names unique khi JSS compile hiển thị JSON representation sang CSS.
  • Vendor Prefixing —CSS rules được tự động vendor prefix
  • Code sharing — Dễ dàng chia sẻ constants & functions giữa JS và CSS.
  • Chỉ có các styles hiện đang được sử dụng trên màn hình của bạn mới có trong DOM.
  • Dead code elimination
  • Unit tests cho CSS!

Bất lợi của CSS-in-JS?

  • Learning curve – Đường cong học tập: những nỗ lực cần thiết để học được kĩ năng mới sau một khoảng thời gian nhất định
  • Các dependencies mới
  • Các thành viên mới trong team sẽ gặp khó khăn để thích nghi với code-base. Những ai mới làm quen với front-end sẽ phải học nhiều thứ mới.
  • Không hoàn toàn là điểm bất lợi nhưng CSS-JS sẽ thách thức status quo. (tình trạng ngưng trệ trước khi có những tác động tạo ra sự thay đổi)

Vì các điểm mạnh vẫn vượt trội điểm yếu nên hãy thử CSS-in-JS xem sao nhé! Chẳng có gì để mất!


Các thư viện CSS-in-JS phổ biến nhất

Styled Components

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

const Title = styled.h1`
  color: white;
`;

const Wrapper = styled.div`
    background: black
`

class App extends Component {
  render() {
    return (
        <Wrapper>
            <Title>Hello World!</Title>
        </Wrapper>
    );
  }
}

export default App;

JSS-React

import React from 'react'
import injectSheet from 'react-jss'

const styles = {
    wrapper: {
        background: 'black'
    },
    title: {
        color: 'white'
    }
}


const App = ({classes}) => (
    <div className={classes.wrapper}>
        <h1 className={classes.title}>
            Hello JSS-React!
        </h1>
    </div>
)

export default injectSheet(styles)(App)

glamorous

import React from 'react'
import glamorous from 'glamorous'

const Wrapper = glamorous.div({
    backgroundColor: 'black'
})

const Title = glamorous.h1({
    color: 'white'
})

const App = () => (
    <Wrapper>
        <Title> Hello JSS-React!</Title>
    </Wrapper>
)

export default App;

Radium (caveat: uses inline styles)

import React, { Component } from 'react';
import Radium from 'radium';

@Radium // decorator
class App extends Component {
	render() {

        const styles = {
            wrapper: {
                background: 'blue',
            }
            title: {
                color: 'white'
            }
        };

		return (
            <div style={styles.wrapper}>
                <h1 style={styles.title}>Hello Radium!</h1>
            </div>
		);
	}
}

export default Radium(App);

Lưu ý: Radium sử dụng decorators!

Aphrodite

import React, { Component } from 'react';
import { StyleSheet, css } from 'aphrodite';

const styles = StyleSheet.create({
    wrapper: {
        backgroundColor: 'red'
    },
    title: {
        backgroundColor: 'blue'
    }
});

class App extends Component {
    render() {
        return (
            <div className={css(styles.wrapper)}>
                <h1 className={css(styles.title)}>Hello Aphrodite!<h1>
            </div>;
        )
    }
}

Stylotron

import React, { Component } from 'react';
import { styled } from 'styletron-react';

const Wrapper = styled('div', {
    backgroundColor: 'black'
})

const Title = styled('h1', {
    color: 'white'
})

class App extends Component {
    render() {
        return (
            <Wrapper>
                <Title>Hello Styletron!<Titleh1>
            </Wrapper>;
        )
    }
}

Có nhiều ví dụ rất đơn giản để thể hiện core functionality. Tất cả thư viện đều có nhiều hơn các tính năng đi kèm – ví dụ như: themingdynamic propsserver side rendering

Chi tiết về các tính năng CSS-in-JS xem tại đây

Danh sách đầy đủ những thư viện hay của CSS-in-JS tại đây

Nguồn: TopDev via hackernoon.com