FlexStyled is a simple runtime css-in-js library for react component
- zero dependencies.
- runtime css generation.
- support css variables.
- support nested css.
- support props dynamic css.
- typescript support.
pnpm add FlexStyled
# or
npm install FlexStyled
# or
yarn add FlexStyledWe 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.
import { styled } from "FlexStyled"
export type CardProps = React.PropsWithChildren<{
title:string
footer?:string
}>
export const Card = styled<CardProps>((props,{className})=>{
const { title,children,footer} =props
return (
<div className={className}>
<div className="title">
{title}
</div>
<div className="content">{children}</div>
<div className="footer">{footer}</div>
</div>
)
},{
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.
<style id="6rxqfu">
.sw6y3s4{
position:relative;
width:100%;
border:1px solid #ccc;
border-radius:4px;
}
</style>Next, let's add styles to the title and footer of the Card component
export const Card = styled<CardProps>((props,{className})=>{
const { title,children,footer} =props
return (
<div className={className}>
<div className="title">
{title}
</div>
<div className="content">{children}</div>
<div className="footer">{footer}</div>
</div>
)},{
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:
<style id="6rxqfu">
.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;
}
</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.
export const Card = styled<CardProps>((props,{className,getStyle})=>{
const { title,children,footer} =props
return (
<div className={className} style={getStyle()}>
<div className="title">
{title}
</div>
<div className="content">{children}</div>
<div className="footer">{footer}</div>
</div>
)},{
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.bgColorto dynamically set the background color of thecontentcard. - In order to support dynamic properties, we need to use the
getStylefunction to get the dynamic style and inject it into the root element of the component. - The
getStylefunction returns acssstyle object that can be passed directly to thestyleattribute. - Any
cssproperty can use(props)=>{....}to dynamically generate CSS property values.
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.
export const Card = styled<CardProps>((props,{className,getStyle})=>{
const { title,children,footer} =props
const [primaryColor,setPrimaryColor] = React.useState("blue")
return (
<div className={className} style={getStyle({"--primary-color":primaryColor})}>
</div>
<div className="content">{children}</div>
<div className="footer">{footer}</div>
</div>
)},{
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
cssvariables. - We declare a
--primary-colorcssvariable in the root style. - Then we use the
--primary-colorvariable in thetitlestyle. - In order to modify the
cssvariable, we need to introducerefand passrefto the root element, and then use thesetVarfunction to modify thecssvariable.
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
classNamein the component. - If you need to dynamically modify
cssvariables, you need to introduceref, passrefto the root element, and then use thesetVarfunction to modifycssvariables. - If you need to use
propsdynamiccssproperties, you need to use thegetStylefunction to get the dynamic css style and inject it into the root element.
styled function can also be used to create styles only and insert into head.
// 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 (
<div className={cardStyle.className} style={cardStyle.getStyle({"--title-color":titleColor},props)}>
<div className="title">
{props.title}
</div>
<div className="content">{props.children}</div>
<div className="footer">{props.footer}</div>
</div>
)
}using createStyle.props to simplify the parameter passing, as follows:
export default (props:CardProps)=>{
return (
<div {...cardStyle.props()}>
...
</div>
)
}
<div {...cardStyle.props({"--title-color":titleColor})}/>
<div {...cardStyle.props({"--title-color":titleColor},{props})}/>
<div {...cardStyle.props({"--title-color":titleColor},{props,className:"xxxxx xxxx"})}/>FlexStyled also provides a hook useStyled to help you quickly encapsulate react components.
import { useStyle } from "FlexStyled"
export const Card2:React.FC<React.PropsWithChildren<CardProps>> = ((props:CardProps)=>{
const { title } = props
const [titleColor,setTitleColor] = useState("blue")
const {className,getStyle } = useStyle({
// style
})
return (
<div className={className} style={getStyle({"--title-color":titleColor},props)}>
<div className="title">
<span>{title}</span>
<span className="tools"><button onClick={()=>setTitleColor(getRandColor())}>Change</button></span>
</div>
<div className="content">
{props.children}
</div>
<div className="footer">{props.footer}</div>
</div>
)
})- The
useStylehook returnsclassNameandgetStyle, which are used to inject style class names and dynamic styles. - The
getStylefunction returns acssstyle object that can be passed directly to thestyleattribute. - The
useStylehook supports passingoptionsparameters to configureidandclassName. - The
useStylehook is the same as thestyledfunction, the only difference is that thestylesheet injected into theheadwill be automatically removed when the component is uninstalled.
FlexStyled supports creating styled components, use html tag name.
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.
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.
// styles.tsx
import { styled } from "FlexStyled"
export style1 = styled({...})
export style2 = styled({...})
export style3 = styled({...})// styled(<React.FC>,<styles>,<options>)
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
}