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
- Host: GitHub
- URL: https://github.com/zhangfisher/flexstyled
- Owner: zhangfisher
- License: mit
- Created: 2024-02-18T01:16:15.000Z (about 2 years ago)
- Default Branch: master
- Last Pushed: 2024-08-16T03:54:38.000Z (over 1 year ago)
- Last Synced: 2025-06-28T14:03:11.490Z (9 months ago)
- Topics: css-in-js, css-in-react
- Language: TypeScript
- Homepage: https://zhangfisher.github.io/repos#flexstyled
- Size: 374 KB
- Stars: 10
- Watchers: 1
- Forks: 1
- Open Issues: 0
-
Metadata Files:
- Readme: readme.md
- Changelog: CHANGELOG.md
- License: LICENSE
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
}
```