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 FlexStyled
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.
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.bgColor
to dynamically set the background color of thecontent
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 acss
style object that can be passed directly to thestyle
attribute. - Any
css
property 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
css
variables. - We declare a
--primary-color
css
variable in the root style. - Then we use the
--primary-color
variable in thetitle
style. - In order to modify the
css
variable, we need to introduceref
and passref
to the root element, and then use thesetVar
function to modify thecss
variable.
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 introduceref
, passref
to the root element, and then use thesetVar
function to modifycss
variables. - If you need to use
props
dynamiccss
properties, you need to use thegetStyle
function 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
useStyle
hook returnsclassName
andgetStyle
, which are used to inject style class names and dynamic styles. - The
getStyle
function returns acss
style object that can be passed directly to thestyle
attribute. - The
useStyle
hook supports passingoptions
parameters to configureid
andclassName
. - The
useStyle
hook is the same as thestyled
function, the only difference is that thestyle
sheet injected into thehead
will 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
}