CSS In JS several ways and set the project theme and other basic exercises

Writing CSS styles in separate CSS style files (.css,.less,.scss, etc.) has long been a convention of front-end development. CSS In JS is to write the applied CSS styles In JavaScript files, so that CSS has JS(which also meets the All In JS feature of React to a certain extent), including module declarations, variable definitions, function calls, and condition judgments.

CSS In JS is a technology, not an implementation of a library, which can be implemented by hand code or by leveraging existing tool libraries.

Here’s a look at three of the major CSS In JS libraries to date

  1. Styled – Components 33.4 K star Main
  2. Radium 7.4 k star
  3. Linaria 7.1K STAR For TARo3.x (0 runtime)

A, styled – components

Styled – Components generates the actual stylesheet with classes that are attached to the DOM node of the styled component via the className attribute. At run time, it injects the generated stylesheet at the end of the document title.

1. Install
  • shell
npm install --save styled-components
#NPM is recommended. If YARN is used, see the official documentation
Copy the code
  • cdn
<script src="https://unpkg.com/styled-components/dist/styled-components.min.js"></script>
Copy the code
2. Plug-in library
  • vscode: vscode-styled-components
  • webstorm: Styled Components
3. Introduction to basic usage grammar
  • 3.1 hellowWorld
import styled  from 'styled-components'

// @1hello world
const Title = styled.h1` the font - size: 1.5 rem; text-align: center; color: palevioletred; `;
const Wrapper = styled.section` padding: 4em; background: papayawhip; `;
<Wrapper>
  <Title>
    Hello World!
  </Title>
</Wrapper>
Copy the code

  • 3.2 Props pass && extend Styles

const Button = styled.button`
  background: ${props => props.primary ? "palevioletred" : "white"};
  color: ${props => props.primary ? "white" : "palevioletred"}; font-size: 1em; margin: 1em; Padding: 0.25 em 1 em; border: 2px solid palevioletred; border-radius: 3px; `;

const TomatoButton = styled(Button)` color: tomato; border-color: tomato; `;

<Button>Normal</Button>
<Button primary>Primary</Button>
<TomatoButton>Tomato Button</TomatoButton>
Copy the code

  • 3.3 Cooperating with Custom Components
const ReversedButton = props => ( <Button {... Props} children={props.children.split('').reverse()}/>) <ReversedButton>Copy the code

  • You can get any custom label definition styles currently passed to you
import { Link } from 'react-router-dom'
const StyleLink = styled(Link)` color: palegoldenrod; font-weight: bold; `;
<StyleLink>this is a styleLink</StyleLink>
Copy the code

  • 3.5 Styled will be smart enough to identify transmitted properties
// Can automatically filter non-standard attributes for you
// This approach means that we don't need to use props conditions in the component to render the class name, reducing clutter in the component
// And keeps the separation of concerns between CSS and JavaScript
const Input = styled.input` padding: 0.5 em. Margin: 0.5 em. color:${props => props.inputColor || "palevioletred"};
  background: papayawhip;
  border: none;
  border-radius: 3px;
  font-size: 18px;
`;
<Input defaultValue="@probablyup" type="text" />
<Input defaultValue="@geelen" type="text" inputColor="rebeccapurple" />
Copy the code

  • 3.6 Leveraging ampersand is sometimes more powerful than CSS
const Thing = styled.div.attrs((/* props */) = > ({ tabIndex: 0 }))` color: blue; &:hover { color: red; // 
      
        when hovered } & ~ & { background: tomato; // 
       
         as a sibling of 
        
         , but maybe not directly next to it } & + & { background: red; // 
         
           next to 
          
            } &.something { background: orange; // 
           
             tagged with an additional CSS class ".something" } .something-else & { border: 1px solid; // 
            
              inside another element labeled ".something-else" } `
            
           
          
         
        
       
      ;

<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>
Copy the code

  • 3.7 && symbols can increase the specificity of rules on components, equal to rendering two classes to increase weight
const Thing2 = styled.div` && { color: blue; } `
<Thing2>
  I'm blue, balabalabalabala
</Thing2>
Copy the code

  • 3.8 To avoid overly complex or unitary arguments passed in, provide an attrs argument and allow the attrs style to be overridden

const AttInput = styled.input.attrs(props= > ({
  type: "text".size: props.size || "1em"
}))` color: palegoldenrod; font-size: 1em; border: 2px solid palevioletred; border-radius: 3px; // Margin:${props => props.size};
  padding: ${props => props.size};
`
// Allow attrs styles to be overwritten
const PasswordInput = styled(AttInput).attrs({
  type: "password",})` border: 2px solid aqua; `;
<AttInput placeholder="A small text input" />
<br />
<AttInput placeholder="A bigger text input" size="2em" />
<PasswordInput />

Copy the code

  • 3.9 cartoon Animations
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; The font - size: 1.2 rem; `;
<Rotate>&lt;💅 🏾&gt;</Rotate>
Copy the code

  • 3.10 refs
// @10 Refs
const Input = styled.input` padding: 0.5 em. Margin: 0.5 em. color: palevioletred; background: papayawhip; border: none; border-radius: 3px; `;
<Input
  ref={inputRef}
  placeholder="Suspension focus!"
  onMouseEnter={()= > {
    inputRef.current.focus()
  }}
/>
Copy the code
  • 3.11 the weight
// Styled component classes take precedence over global classes because by default styled components inject their styles at run time at the end of . Therefore, its style is superior to other single class name selectors.
// One solution is to improve the specificity of selectors in stylesheets:
Styled - Components will have higher privileges than className, so id or more important will be used
const MyComponent = styled.div`background-color: green; `;
<MyComponent className="red-bg" >12123</MyComponent>
Copy the code

  • 3.12 Interpolation marks
// Sometimes the processor will throw an error (column e.g.csSyntaxError), even if our syntax is error-free, this is usually due to interpolation, more specifically the fact that the processor does not know you are interpolating.
// So tell him
const something = 'background'
const Button = styled.div`
  // Tell the processor that "something" is a property
  The ${/* sc-prop */ something}: papayawhip; // Provided interpolation // sc-block // sc-selector // sc-declaration // sc-property // sc-valueCopy the code
  • API createGlobalStyle withTheme ThemeProvider and the library Styled -theming

ThemeProvider

Auxiliary components for theming. The topic is injected through the context API into all styled components anywhere below it in the component tree. Check the sections on topics.

const Box = styled.div`
  color: ${props => props.theme.color};
`
<ThemeProvider theme={{ color: 'mediumseagreen'}} ><Box>I'm mediumseagreen!</Box>
</ThemeProvider>
Copy the code

createGlobalStyle

Helper functions that generate a special StyledComponent that handles global styles. Typically, styled components are automatically scoped to the local CSS class and are therefore isolated from other components. In the case of createGlobalStyle, this restriction is removed, and things like CSS resets or basic stylesheets can be applied. You can think of it as a dynamic compilation of reset.css

import { createGlobalStyle } from 'styled-components'

const GlobalStyle = createGlobalStyle`
  body {
    color: ${props => (props.whiteColor ? 'white' : 'black')};
  }
`
<React.Fragment>
  <GlobalStyle whiteColor />
  <Navigation /> {/* Usually placed at the highest level */}
</React.Fragment>
Copy the code

Because the GlobalStyle component is a StyledComponent, this means that it can also access topics from the component (if provided). So we can use theme and GlobalStyle to customize different theme ideas for each page

const GlobalStyle = createGlobalStyle`
  body {
    color: ${props => (props.whiteColor ? 'white' : 'black')};
    font-family: ${props => props.theme.fontFamily};
  }
`
Copy the code

withTheme

This is a high-level component factory that takes the current theme from the ThemeProvider and passes it to your component as a theme prop. By using this factory function, dynamic configuration components can be defined in componets, and react modularity can be better defined

// React class import {withTheme} from 'styled-components' const MyComponent = (props)=> { Console. log(props. Theme) // Allow theme return <>..... from props </> } export default withTheme(MyComponent)Copy the code

styled-theming

Styled – Components, a library that complys the styled- Components theme, is essentially a function that encapsulates the return style – Components

import React from 'react'
import styled, { ThemeProvider } from 'styled-components'
import theme from 'styled-theming'
const boxBackgroundColor = theme('mode', {
  light: '#fff'.dark: '# 000',})const Box = styled.div`
  background-color: ${boxBackgroundColor};
`
export default function App() {
  return (
    <ThemeProvider theme={{ mode: 'light' }}>
      <Box>Hello World</Box>
    </ThemeProvider>)}Copy the code

Styled – Components + ANTD Customizes the theme style

Antd has its own modification theme scheme, which can be referred to the official documentation. Here, a method is provided to individually modify the specific components that you want to modify, and the corresponding display is styled according to the styled- Components theme

  • antdTheme.js
import styled, { css } from 'styled-components';  
import theme from 'styled-theming';
import { Button as AButton } from '.. /.. /node_modules/antd'
import React from 'react'

// Modify the frame style, using antD frame Button style as an example
const buttonTheme = theme('buttonMode', {
  light: css`
    background: #ffffff;
    color: # 000;
  `.dark: css`
    background: # 000;
    color: #ffffff;
  `
})

const Button = styled((props) = ><AButton {. props} / >)`
  ${buttonTheme}
`

// Export all ANTD components
export * from '.. /.. /node_modules/antd'

// Export specific modified components
export { Button, buttonTheme }
Copy the code

React-app-rewired + config-overrides. Js configure alias to change the way antD is introduced

const { useBabelRc, override, addWebpackAlias } = require('customize-cra')
const path = require('path')
module.exports = override(
  useBabelRc(),
  addWebpackAlias({
    ['antd']: path.resolve(__dirname, './src/Theme/antdTheme.js')}))Copy the code
  • Component page
import { ThemeProvider } from 'styled-components'
import { Button } from 'antd'
import TestTheme1 from './child/TestTheme1' // Child ANTd button component

function StyleTheme1(params) {
  return <ThemeProvider theme={{ buttonMode: 'dark' }}>
    <Button type="ghost">The parent button</Button>
    <TestTheme1 />
  </ThemeProvider>
}
Copy the code

Styled – Components Configures the global theme & runs and packages different themes based on environment variables

  • Configure environment variables with cross-env
"dev:dark": "cross-env REACT_APP_THEME=dark react-app-rewired start",
"build:dark": "cross-env REACT_APP_THEME=dark react-app-rewired build"
Copy the code
  • themes.js
import styled, { css } from 'styled-components';  
import theme from 'styled-theming';

// Change the default style, or set some public style
const buttonTheme = theme('buttonMode', {
  light: css`
    background: #ffffff;
    color: # 000;
  `.dark: css`
    background: # 000;
    color: #ffffff;
  `
})

const Button = styled.button`
  ${buttonTheme}
`

export { Button }
Copy the code
  • Page components
import React from 'react'
import { Button } from '.. /Theme/themes' 
import TestTheme2 from './child/TestTheme2.js'
import { ThemeProvider } from 'styled-components'

// Use NPM run dev:dark to generate a black button
function StyleTheme2() {
  return (
    <ThemeProvider theme={{ buttonMode: process.env.REACT_APP_THEME}} >
      <Button type="ghost">The parent button</Button>
      <br/>
      <br/>
      <TestTheme2 />
    </ThemeProvider>)}export default StyleTheme2
Copy the code

Styled components Vue uses styled- Components

For the Styled components of Vue, Css in Js technology is not required under normal circumstances, because Vue components and styles can be written in the same Vue file without separation, and slot and interpolation expressions have been handled perfectly.

However, you can also choose the scenarios you want to use in certain situations. For details, see the popular CSS-in-JS library for styled components in Vue projects: Styled – Components, STYLED – Components

Five, the radium

Radium is a set of tools to manage inline styles on React elements. It gives you powerful styling capabilities without CSS.

Radium is a set of tools for managing inline styles on React elements. It gives you powerful styling capabilities without CSS.

  • The installation
npm i radium
Copy the code
  • Radium basic use
import Radium from 'radium'
import React from 'react'

const styles = {
  base: {
    color: '#fff'.':hover': {
      background: '#0074D9'}},primary: {
    background: '#0074D9'
  },

  warning: {
    background: '#FF4136'}};function Button(props) {
  return (
    <>
      <button style={[styles.base, styles[props.kind]]} >
        {props.children}
      </button>
    </>
  );
}

Button = Radium(Button)

export default() = ><div><Button kind="warning">primary button</Button></div>
Copy the code

Because of its inline style, CSS has a high level of hierarchy, so it is not recommended to use it midway through projects that are not starting from scratch (just my opinion).

Six, linaria

  • Installation and use
npm install linaria @linaria/core @linaria/react @linaria/babel-preset @linaria/shaker
Copy the code
  • Add @linaria/webpack-loader to creation-react-app via react-app-rewired + config-overrides
const { useBabelRc, override, addWebpackModuleRule } = require('customize-cra')

const path = require('path')

module.exports = override(
  useBabelRc(),
  addWebpackModuleRule({
    test: /\.(js|tsx)$/,
    exclude: /node_modules/,
    use: [
      { loader: 'babel-loader' },
      {
        loader: '@linaria/webpack-loader'.options: {
          cacheDirectory: 'src/.linaria_cache'.sourceMap: process.env.NODE_ENV ! = ='production',},},],}),Copy the code
  • Some API different from styled- Components
  1. CSS tags allow you to create simple class names:
import { css } from '@linaria/core';

// Create a class name
const title = css`
  font-size: 24px;
  font-weight: bold;
`;

function Heading() {
  // Pass it to a component
  return <h1 className={title}>This is a title</h1>;
}
Copy the code
  1. .

7. Several schemes of Linaria theme

1. CSS custom properties (some browsers do not support CSS custom properties, as listed in IE11)
// Create names for different themes
const a = css`
  --color-primary: #6200ee;
  --color-accent: #03dac4;
`;

const b = css`
  --color-primary: #03a9f4;
  --color-accent: #e91e63;
`;

// Apply the theme to the root element
<Container className={a} />; 

// You can use these variables in any child element
const Button = styled.button` background-color: var(--color-accent); `;
Copy the code
2. Class names

Add a class name that represents the theme (such as theme-dark) to the root element, and use the CSS child selector to theme the element based on this parent class name

  • linariaTheme.js
import { styled } from '@linaria/react';

const colors = {
  light: {
    text: 'black',},dark: {
    text: 'white',},green: {text: 'green'}};export const theming = cb= >
  Object.keys(colors).reduce((acc, name) = > Object.assign(acc, {
    [`.theme-${name}& `]: cb(colors[name]),
  }), {});

// Use the helper in your styles
export const Header = styled.h1`
  text-transform: uppercase;

  ${theming(c => ({ color: c.text, }))};
`;
Copy the code
  • Component page
import React from 'react'
import { Header } from '.. /.. /Theme/linariaTheme'

function LinariaTheme1() {
  return <div className='theme-green'>
    <Header>abcdefghi</Header> 
  </div>
}

export default LinariaTheme1
Copy the code
3. React Context

Use the React Context to pass the colors, and then use a function interpolation with style tags to use the colors. The react-theme-provider library is used for implementation, similar to the ThemeProvider and its style components, For details, see react-theme-provider

8. Cooperate with storybook
  1. styled-components
  • Global GlobalStyles. Storybook/preview. Js
import GlobalStyles from '.. /src/styles/global'; // Set the global code

export const decorators = [
  (Story) = > (
    <>
      <GlobalStyles />
      <Story />
    </>)]Copy the code
  • Individual components setting the theme can customize the theme style using the Styled – Components + ANTD above
  • Since this is the run-time approach, it is not recommended to add themes to each component, but to the total file, configuring themes according to the incoming parameters
  1. linaria
  • Taro join linaria
  • Storybook added to Linaria [main.js]
  webpackFinal: async (config, { configType }) => {
    config.module.rules.push({
      test: /\.js? $/,
      exclude: /node_modules/,
      use: [
        { loader: 'babel-loader' },
        {
          loader: "@linaria/webpack-loader".options: {
            sourceMap: process.env.NODE_ENV ! = ="production".extension: ".linaria.module.css",},},],});return config;
  }
Copy the code

Eight, advantages and disadvantages (most of the following content is from the official website translation)

styled-components
  • optimal
  1. Automatically Tracking rendering: Styled – Components can completely automatically track which components are rendered on the page and inject their style, without injecting anything else. Combined with code splitting, this means that your users can load the minimum amount of required code.
  2. No class name errors: Styled – Components will generate a unique class name for your style. You don’t have to worry about repetition, overlap, or spelling mistakes.
  3. CSS additions and subtractions can be easily managed: styles are written with components, and unused styles are automatically removed when components are packaged
  4. Simple dynamic styling: Tailoring styles based on component items or global themes is straightforward, without having to manually manage dozens of classes.
  5. Painless maintenance: You don’t have to look for different files to find styles that affect your components, so maintenance is a piece of cake no matter how big your code base is.
  6. Vendor automatic prefix: Write CSS as the current standard and let the styled component handle the rest.
  • Lack of
  1. Increases component complexity, the amount of code per component, and styles do not separate components to look impure
  2. Add about 128K packing volume if you want to consider first screen rendering?
  3. Cost of learning adaptation
radium
  • optimal
  1. .
  • Lack of
  1. .
linaria
  • optimal
  1. Generates a unique selector, and does not need to worry about selector renaming in large projects
  2. Styles and components can be in the same file or separated
  3. It’s easier to add and remove code without worrying about breaking components or removing unnecessary styles
  4. No preprocessor required
  5. Automatically removes unused styles
  6. Automatic vendor prefixes can still be used to further optimize CSS using tools such as PostCSS.
  7. 0 runtime, CSS is already compiled at the time the code is run, so there is no increase in package size
  8. More friendly support SSR, speed up the first screen rendering time
  • Lack of
  1. Linaria is based on CSS variables. Most modern browsers support this feature, but not for IE 11 and below, so if you need to support IE 11, Linaria may not be your best choice

Article code github address, if helpful, please star

CssInJss

storybook demo

Refer to the connection

  • styled-components
  • radium
  • Linaria making address
  • The pros and cons of CSS in JS
  • Refer to the csS-in-JS section in the Taro document
  • Styled Components: Styled Components for Vue projects using the React super-styled CSS-In-JS library: Styled components
  • The principles of Linaria, the compiled JSS framework
  • Styled – Components Running principle