This is the seventh day of my participation in the More text Challenge. For details, see more text Challenge

Advantages of CSS in JS

CSS in JS has evolved into a mainstream solution for writing styles in React applications, and the well-known component library, Material UI, has been implemented using CSS in JS. There are two ways to implement CSS in JS: unique CSS selectors and inline styles. so

  1. Don’t worry about tedious Class naming conventions
  2. Don’t worry about styles being overwritten
  3. Convenient reuse of styles (styles are either JS objects or strings)
  4. Reduced redundant CSS code, extreme style load on demand

Emotion is one of the many implementations of CSS in JS. Here’s how to use it.

Note: The following introduction is fromEmotion Official document

Basic use of Emotion

Object Styles and String Styles

Emotion supports style definitions in both JS objects and JS strings.

Object Styles

/ * *@jsx jsx */
import { jsx } from '@emotion/react'

render(
  <div
    css={{
      backgroundColor: 'hotpink', '&':hover': {
        color: 'lightgreen'}}} >
    This has a hotpink background.
  </div>
)
Copy the code

String Styles

// this comment tells babel to convert jsx to calls to a function called jsx instead of React.createElement
/ * *@jsx jsx */
import { css, jsx } from '@emotion/react'

const color = 'darkgreen'

render(
  <div
    css={css`
      background-color: hotpink;
      &:hover {
        color:The ${color};
      }
    `}
  >
    This has a hotpink background.
  </div>
)
Copy the code

Add the style

Emotion has two ways of writing CSS: CSS-Prop and Styled Components.

css Prop

Click here to see how to open CSS Prop

String Styles sample

// this comment tells babel to convert jsx to calls to a function called jsx instead of React.createElement
/ * *@jsx jsx */
import { css, jsx } from '@emotion/react'

const color = 'darkgreen'

render(
  <div
    css={css`
      background-color: hotpink;
      &:hover {
        color:The ${color};
      }
    `}
  >
    This has a hotpink background.
  </div>
)
Copy the code

The @emotion/ React JSX is an enhanced react. CreateElement method that adds a CSS prop to the React element.

The Object Styles sample

/ * *@jsx jsx */
import { jsx } from '@emotion/react'

render(
  <div
    css={{
      backgroundColor: 'hotpink', '&':hover': {
        color: 'lightgreen'}}} >
    This has a hotpink background.
  </div>
)
Copy the code

For either Object Styles or String Styles, we can read the context js variable directly at the time the style is defined. This allows us to easily change the style.

Styled Components

Styled Components derive some of the built-in Components with HTML tags, and our syntax below allows the styling to be added.

import styled from '@emotion/styled'

let SomeComp = styled.div({
  color: 'hotpink'
})

let AnotherComp = styled.div`
  color: ${props => props.color};
`

render(
  <SomeComp>
    <AnotherComp color="green" />
  </SomeComp>
)
Copy the code

Styles of Styled Components Components generated by Styled Components can also change style based on the incoming Props

import styled from '@emotion/styled'

const Button = styled.button`
  color: ${props =>
    props.primary ? 'hotpink' : 'turquoise'};
`

const Container = styled.div(props= > ({
  display: 'flex'.flexDirection: props.column && 'column'
}))

render(
  <Container column>
    <Button>This is a regular button.</Button>
    <Button primary>This is a primary button.</Button>
  </Container>
)
Copy the code

For the Styled Components, there are also some less common uses. Click here to learn more.

Style reuse

In Emotion, we can declare common styles as variables and share them across different components.

/ * *@jsx jsx */
import { jsx, css } from '@emotion/react'

const base = css`
  color: hotpink;
`

render(
  <div
    css={css`
      ${base};
      background-color: #eee;
    `}
  >
    This is hotpink.
  </div>
)
Copy the code

The base style above can then be used with render. If we have other components that use the Base style, we can import the base variable to use it.

Style priority

/ * *@jsx jsx */
import { css, jsx } from '@emotion/react'

const danger = css`
  color: red;
`

const base = css`
  background-color: darkgreen;
  color: turquoise;
`

render(
  <div>
    <div css={base}>This will be turquoise</div>
    <div css={[danger, base]} >
      This will be also be turquoise since the base styles
      overwrite the danger styles.
    </div>
    <div css={[base, danger]} >This will be red</div>
  </div>
)
Copy the code

When writing styles, it is inevitable that you will need to cover them. In this case, you can adjust the order of base and Danger to cover them as above (the later styles have higher priority).

Nested selectors

The Emotion style also supports CSS selectors.

Select and set the nodes within the component

/ * *@jsx jsx */
import { jsx, css } from '@emotion/react'

const paragraph = css`
  color: turquoise;

  a {
    border-bottom: 1px solid currentColor;
    cursor: pointer;
  }
`
render(
  <p css={paragraph}>
    Some text.
    <a>A link with a bottom border.</a>
  </p>
)
Copy the code

When the component is a child, use & to select itself and set the style

/ * *@jsx jsx */
import { jsx, css } from '@emotion/react'

const paragraph = css`
  color: turquoise;

  header & {
    color: green;
  }
`
render(
  <div>
    <header>
      <p css={paragraph}>
        This is green since it's inside a header
      </p>
    </header>
    <p css={paragraph}>
      This is turquoise since it's not inside a header.
    </p>
  </div>
)
Copy the code

Media queries

/ * *@jsx jsx */
import { jsx, css } from '@emotion/react'

render(
  <p
    css={css`
      font-size: 30px;
      @media (min-width: 420px) {
        font-size: 50px;
      }
    `}
  >
    Some text!
  </p>
)
Copy the code

Click here to learn more about using multimedia queries

Global style

import { Global, css } from '@emotion/react'

render(
  <div>
    <Global
      styles={css`
        .some-class {
          color: hotpink !important; } `} / >
    <Global
      styles={{
        '.some-class': {
          fontSize: 50.textAlign: 'center'}}} / >
    <div className="some-class">This is hotpink now!</div>
  </div>
)
Copy the code

Advanced usage

keyframes

/ * *@jsx jsx */
import { jsx, css, keyframes } from '@emotion/react'

const bounce = keyframes'from, 50%, 50%, 50%, to {transform: translate3d(0,0,0); } 40%, 43% { transform: translate3d(0, -30px, 0); } 70% { transform: translate3d(0, -15px, 0); } 90% { transform: translate3d(0,-4px,0); } `

render(
  <div
    css={css`
      animation:The ${bounce} 1s ease infinite;
    `}
  >
    some bouncing text!
  </div>
)
Copy the code

The theme

ThemeProvider

import * as React from 'react'
import styled from '@emotion/styled'
import { ThemeProvider, withTheme } from '@emotion/react'

// object-style theme

const theme = {
  backgroundColor: 'green'.color: 'red'
}

// function-style theme; note that if multiple <ThemeProvider> are used,
// the parent theme will be passed as a function argument

const adjustedTheme = ancestorTheme= > ({ ...ancestorTheme, color: 'blue' })

class Container extends React.Component {
  render() {
    return (
      <ThemeProvider theme={theme}>
        <ThemeProvider theme={adjustedTheme}>
          <Text>Boom shaka laka!</Text>
        </ThemeProvider>
      </ThemeProvider>)}}Copy the code

withTheme

import * as PropTypes from 'prop-types'
import * as React from 'react'
import { withTheme } from '@emotion/react'

class TellMeTheColor extends React.Component {
  render() {
    return <div>The color is {this.props.theme.color}.</div>
  }
}

TellMeTheColor.propTypes = {
  theme: PropTypes.shape({
    color: PropTypes.string
  })
}

const TellMeTheColorWithTheme = withTheme(TellMeTheColor)
Copy the code

useTheme

/ * *@jsx jsx */
import { jsx, ThemeProvider, useTheme } from '@emotion/react'
import styled from '@emotion/styled'

const theme = {
  colors: {
    primary: 'hotpink'}}function SomeText(props) {
  const theme = useTheme()
  return <div css={{ color: theme.colors.primary }} {. props} / >
}

render(
  <ThemeProvider theme={theme}>
    <SomeText>some text</SomeText>
  </ThemeProvider>
)
Copy the code

Open the CSS Prop

A CSS Prop can be used on any Dom element or component that supports className.

The CSS Prop needs to be implemented with babel-PRESET or JSX Pragma

babel-preset

.babelrc

{
  "presets": ["@emotion/babel-preset-css-prop"]
}
Copy the code

If you are using the compatible React version (>=16.14.0) then you can opt into using the new JSX runtimes by using such configuration:

If React version >=16.14.0, you can use the following configuration to use the new JSX runtime.

{
  "presets": [
    [
      "@babel/preset-react",
      { "runtime": "automatic", "importSource": "@emotion/react" }
    ]
  ],
  "plugins": ["@emotion/babel-plugin"]
}
Copy the code

tsconfig.json

This is the configuration when compiling typescript with Babel

{
  "compilerOptions": {...// "jsx": "react",
    "jsxImportSource": "@emotion/react". }}Copy the code

JSX Pragma

Open a CSS Prop by adding a comment to the JSX transformation.

/ * *@jsx jsx */
import { jsx } from '@emotion/react'
Copy the code

/** @jsx JSX */ If it doesn’t work, try /** @jsximportSource @emotion/react */.

Click here for a detailed configuration document.

compatibility

Emotion supports all popular browsers, including Internet Explorer 11.

The resources

  • CSS in JS
  • The Emotion’s official website
  • The pros and cons of CSS in JS The front end scholar needs to clear his mind so that he can conceive the picture
  • Talk about the use of CSS-in-JS in the React project