An open API service indexing awesome lists of open source software.

https://github.com/zhangfisher/flexstyled

simple css-in-js for react
https://github.com/zhangfisher/flexstyled

css-in-js css-in-react

Last synced: 8 months ago
JSON representation

simple css-in-js for react

Awesome Lists containing this project

README

          

# FlexStyled

FlexStyled is a simple runtime `css-in-js` library for react component

[中文](https://zhangfisher.github.io/flexstyled/)

- zero dependencies.
- runtime css generation.
- support css variables.
- support nested css.
- support props dynamic css.
- typescript support.

[Open demo on CodeSandbox](https://codesandbox.io/p/sandbox/FlexStyled-demo-x7w94w?layout=%257B%2522sidebarPanel%2522%253A%2522EXPLORER%2522%252C%2522rootPanelGroup%2522%253A%257B%2522direction%2522%253A%2522horizontal%2522%252C%2522contentType%2522%253A%2522UNKNOWN%2522%252C%2522type%2522%253A%2522PANEL_GROUP%2522%252C%2522id%2522%253A%2522ROOT_LAYOUT%2522%252C%2522panels%2522%253A%255B%257B%2522type%2522%253A%2522PANEL_GROUP%2522%252C%2522contentType%2522%253A%2522UNKNOWN%2522%252C%2522direction%2522%253A%2522vertical%2522%252C%2522id%2522%253A%2522clstzj2mg0006356lkdcmsv3s%2522%252C%2522sizes%2522%253A%255B70%252C30%255D%252C%2522panels%2522%253A%255B%257B%2522type%2522%253A%2522PANEL_GROUP%2522%252C%2522contentType%2522%253A%2522EDITOR%2522%252C%2522direction%2522%253A%2522horizontal%2522%252C%2522id%2522%253A%2522EDITOR%2522%252C%2522panels%2522%253A%255B%257B%2522type%2522%253A%2522PANEL%2522%252C%2522contentType%2522%253A%2522EDITOR%2522%252C%2522id%2522%253A%2522clstzj2mg0002356lq7y9whne%2522%257D%255D%257D%252C%257B%2522type%2522%253A%2522PANEL_GROUP%2522%252C%2522contentType%2522%253A%2522SHELLS%2522%252C%2522direction%2522%253A%2522horizontal%2522%252C%2522id%2522%253A%2522SHELLS%2522%252C%2522panels%2522%253A%255B%257B%2522type%2522%253A%2522PANEL%2522%252C%2522contentType%2522%253A%2522SHELLS%2522%252C%2522id%2522%253A%2522clstzj2mg0003356lip4fhd1w%2522%257D%255D%252C%2522sizes%2522%253A%255B100%255D%257D%255D%257D%252C%257B%2522type%2522%253A%2522PANEL_GROUP%2522%252C%2522contentType%2522%253A%2522DEVTOOLS%2522%252C%2522direction%2522%253A%2522vertical%2522%252C%2522id%2522%253A%2522DEVTOOLS%2522%252C%2522panels%2522%253A%255B%257B%2522type%2522%253A%2522PANEL%2522%252C%2522contentType%2522%253A%2522DEVTOOLS%2522%252C%2522id%2522%253A%2522clstzj2mg0005356l6vsjkkfr%2522%257D%255D%252C%2522sizes%2522%253A%255B100%255D%257D%255D%252C%2522sizes%2522%253A%255B50%252C50%255D%257D%252C%2522tabbedPanels%2522%253A%257B%2522clstzj2mg0002356lq7y9whne%2522%253A%257B%2522id%2522%253A%2522clstzj2mg0002356lq7y9whne%2522%252C%2522tabs%2522%253A%255B%255D%257D%252C%2522clstzj2mg0005356l6vsjkkfr%2522%253A%257B%2522tabs%2522%253A%255B%257B%2522id%2522%253A%2522clstzj2mg0004356l6rts8s1f%2522%252C%2522mode%2522%253A%2522permanent%2522%252C%2522type%2522%253A%2522UNASSIGNED_PORT%2522%252C%2522port%2522%253A0%252C%2522path%2522%253A%2522%252F%2522%257D%255D%252C%2522id%2522%253A%2522clstzj2mg0005356l6vsjkkfr%2522%252C%2522activeTabId%2522%253A%2522clstzj2mg0004356l6rts8s1f%2522%257D%252C%2522clstzj2mg0003356lip4fhd1w%2522%253A%257B%2522tabs%2522%253A%255B%255D%252C%2522id%2522%253A%2522clstzj2mg0003356lip4fhd1w%2522%257D%257D%252C%2522showDevtools%2522%253Atrue%252C%2522showShells%2522%253Atrue%252C%2522showSidebar%2522%253Atrue%252C%2522sidebarPanelSize%2522%253A15%257D)

## Installation

```bash
pnpm add FlexStyled
# or
npm install FlexStyled
# or
yarn add FlexStyled
```

## Usage

We plan to develop a `Card` component, which has a `title` attribute for displaying titles, a `footer`' attribute for displaying bottom content, and a `children` attribute as the content area of the card.

### Basic Usage

```tsx
import { styled } from "FlexStyled"

export type CardProps = React.PropsWithChildren<{
title:string
footer?:string
}>

export const Card = styled((props,{className})=>{
const { title,children,footer} =props
return (



{title}

{children}

{footer}


)
},{
position:"relative",
width:"100%",
border:"1px solid #ccc",
borderRadius:"4px"
})

```

-The above code will create a `Card` component, generate a style class (with a randomly generated name) for the style, and insert it into the `head` tag.
-Then pass the `className` prop to the component, which will use this class name to apply the style.

You can find a CSS style similar to this in the `head`, where the `className` and `style.id` are both automatically generated. You can also specify `id` and `className` through the `options` parameter.

```html

.sw6y3s4{
position:relative;
width:100%;
border:1px solid #ccc;
border-radius:4px;
}

```

### Nested Style

Next, let's add styles to the `title` and `footer` of the `Card` component

```tsx
export const Card = styled((props,{className})=>{
const { title,children,footer} =props
return (



{title}

{children}

{footer}


)},{
position:"relative",
width:"100%",
border:"1px solid #ccc",
borderRadius:"4px",
"& > .title":{
fontSize:"20px",
fontWeight:"bold",
},
"& > .footer":{
borderTop:"1px solid #ccc",
padding:"8px",
textAlign:"right"
}
})
```

-We have added styles to the `title` and `footer` above.
-Use the `&` symbol to represent the current parent element, similar to the syntax of nested CSS such as `less` and `sass`.

The style generated in `head` is as follows:

```html

.sw6y3s4{
position:relative;
width:100%;
border:1px solid #ccc;
border-radius:4px;
}
.sw6y3s4 > .title{
font-size:20px;
font-weight:bold;
}
.sw6y3s4 > .footer{
border-top:1px solid #ccc;
padding:8px;
text-align:right;
}

```

### Dynamic Style

`FlexStyled` supports using `props` to dynamically set styles.

For example, we want the background color of the `content` card to be specified by the `props.bgColor` attribute.

```tsx

export const Card = styled((props,{className,getStyle})=>{
const { title,children,footer} =props
return (



{title}

{children}

{footer}


)},{
position:"relative",
width:"100%",
border:"1px solid #ccc",
borderRadius:"4px",
"& > .title":{
fontSize:"20px",
fontWeight:"bold",
},
"& > .footer":{
borderTop:"1px solid #ccc",
padding:"8px",
textAlign:"right"
},
"& > .content":{
padding:"8px",
backgroundColor:(props)=>props.bgColor
}
})
```

- The above code uses `props.bgColor` to dynamically set the background color of the `content` card.
- In order to support dynamic properties, we need to use the `getStyle` function to get the dynamic style and inject it into the root element of the component.
- The `getStyle` function returns a `css` style object that can be passed directly to the `style` attribute.
- Any `css` property can use `(props)=>{....}` to dynamically generate CSS property values.

### CSS Variables

`FlexStyled` supports using `css` variables.

We can use `css` variables in the root style declaration, and then use the `setVar` function to dynamically modify the `css` variable in the component.

```tsx

export const Card = styled((props,{className,getStyle})=>{
const { title,children,footer} =props
const [primaryColor,setPrimaryColor] = React.useState("blue")
return (



{children}

{footer}


)},{
position:"relative",
width:"100%",
border:"1px solid #ccc",
borderRadius:"4px",
"--primary-color":"blue",
"& > .title":{
fontSize:"20px",
fontWeight:"bold",
color:"var(--primary-color)"
},
"& > .footer":{
borderTop:"1px solid #ccc",
padding:"8px",
textAlign:"right"
},
"& > .content":{
padding:"8px",
backgroundColor:(props)=>props.bgColor
}
})
```

- The above code uses `css` variables.
- We declare a `--primary-color` `css` variable in the root style.
- Then we use the `--primary-color` variable in the `title` style.
- In order to modify the `css` variable, we need to introduce `ref` and pass `ref` to the root element, and then use the `setVar` function to modify the `css` variable.

### Summary

`FlexStyled` is a very simple `css-in-js` library that can help you quickly encapsulate `react` components and support `css` variables and dynamic `css` properties.

- By default, you only need to reference `className` in the component.
- If you need to dynamically modify `css` variables, you need to introduce `ref`, pass `ref` to the root element, and then use the `setVar` function to modify `css` variables.
- If you need to use `props` dynamic `css` properties, you need to use the `getStyle` function to get the dynamic css style and inject it into the root element.

## creteStyle

`styled` function can also be used to create styles only and insert into head.

```tsx
// card.style.ts

import { styled } from "FlexStyled"

// create style and insert into head
export default styled({ // 组件样式
position:"relative",
width:"100%",
border:"1px solid #ccc",
borderRadius:"4px",
"--primary-color":"blue",
"& > .title":{
fontSize:"20px",
fontWeight:"bold",
color:"var(--primary-color)"
},
"& > .footer":{
borderTop:"1px solid #ccc",
padding:"8px",
textAlign:"right"
},
"& > .content":{
padding:"8px",
backgroundColor:(props)=>props.bgColor
}
})

// card.tsx
import cardStyle from "./card.style"

export default (props:CardProps)=>{
return (



{props.title}

{props.children}

{props.footer}


)
}
```

using `createStyle.props` to simplify the parameter passing, as follows:

```tsx

export default (props:CardProps)=>{
return (


...

)
}



```

## Hook

`FlexStyled` also provides a hook `useStyled` to help you quickly encapsulate `react` components.


```tsx
import { useStyle } from "FlexStyled"
export const Card2:React.FC> = ((props:CardProps)=>{
const { title } = props
const [titleColor,setTitleColor] = useState("blue")
const {className,getStyle } = useStyle({
// style
})
return (



{title}
setTitleColor(getRandColor())}>Change


{props.children}

{props.footer}


)
})
```

- The `useStyle` hook returns `className` and `getStyle`, which are used to inject style class names and dynamic styles.
- The `getStyle` function returns a `css` style object that can be passed directly to the `style` attribute.
- The `useStyle` hook supports passing `options` parameters to configure `id` and `className`.
- The `useStyle` hook is the same as the `styled` function, the only difference is that the `style` sheet injected into the `head` will be automatically removed when the component is uninstalled.

### Create Styled component

`FlexStyled` supports creating styled components, use html tag name.

```tsx

import { styled } from "FlexStyled"

const MyButton = styled.div({
color:"red",
"&:hover":{
color:"blue"
}
})

```
- You can also create other HTML tags, such as `span`, `button`, etc.

## Performance

Due to the limitations of `css-in-js`, there may be performance issues. A recommended performance optimization method is to create all styles at once during the application's startup phase and insert them into the `head`, and then reference the styles in the component.

```tsx
// styles.tsx
import { styled } from "FlexStyled"
export style1 = styled({...})
export style2 = styled({...})
export style3 = styled({...})
```

## Options

```tsx

// styled(,,)

export interface StyledOptions{
// The ID of the style sheet, if not specified, will be automatically generated
id?:string
// The generated class name, if not specified, will be automatically generated
className?:string
}
```