news 2026/8/7 23:36:12

从一个按钮实例入门CSS in JS之styled-components

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
从一个按钮实例入门CSS in JS之styled-components

前言

最近接手一个react项目,项目中使用的 CSS in JS方案来实现CSS模块化,它使用的包是styled-components

我以前的项目Vue居多的,Vue是很简单的通过scoped就可以实现模块化CSS,当然也在项目中用过CSS Modules方案,但CSS in JS还是第一次接触到,正好趁这个时机学习一下,在做demo时候把平时开发用的比较高频的CSS特性都试了一下,最终完成了一个小按钮demo,突然发现它是一个不错的用来入门styled-components不错的小案例,特记录

styled-components介绍

主要作用是它可以编写实际的CSS代码来设计组件样式,也不需要组件和样式之间的映射,即创建后就是一个正常的React组件,在一个组件内会将结构、样式和逻辑写在一起,虽然这违背了关注点分离的原则,但是这有利于组件间的隔离

使用styled-components不需要再使用className属性来控制样式,而是将样式写成更具语义化的组件的形式,使用style-components会随机生成一个class名称,这样保证每个元素的样式名都是唯一的,当然因为随机生成,维护会增加难度,很难通过样式名定位到元素

入门styled-components的小按钮效果

Screen Recording 2025-10-31 at 14.42.32.gif

小按钮的关键代码

import styled, { keyframes, createGlobalStyle, css } from 'styled-components'

const Wrap = styled.div`

width: 100%;

height: 100vh;

display: flex;

flex-direction: column;

justify-content: center;

align-items: center;

gap: 20px;

`

// css帧动画

const aniTag = keyframes`

0% {

opacity: 0;

transform: translateY(-100%);

}

100% {

opacity: 1;

transform: translateY(0);

}

`

const MyButton = styled.div`

width: 400px;

height: 80px;

border:1px solid gray;

border-radius: 10px;

overflow: hidden;

display: flex;

flex-direction: column;

justify-content: center;

align-items: center;

position: relative;

// 传参

background-color: ${props => props.bgNormalColor ? props.bgNormalColor : 'blue'};

transition: background-color 0.3s ease-in-out;

// 伪元素

&::after{

content: 'after';

height: 20px;

font-size: 14px;

line-height: 20px;

padding:0 5px;

border-radius: 0 0 6px 6px;

position: absolute;

top: 0;

right: 10px;

background-color: yellow;

color: ${props => props.hightightColor ? props.hightightColor : 'white'};

opacity: 0;

}

// 子孙选择器

p {

line-height: 24px;

color: ${props => props.normalColor ? props.normalColor : 'black'};

transition: color 0.3s ease-in-out;

}

// 当有全局样式的时候,使用&&提高局部样式优先级来覆盖全局样式

&& span{

color: rgba(255,0,255,0.6);

}

// 类选择器

.emphasize{

text-decoration: underline;

}

// 伪类

&:hover{

background-color: ${props => props.bgHighlightColor ? props.bgHighlightColor : 'yellow'};

p{

color: ${props => props.hightightColor ? props.hightightColor : 'white'};

}

// css animation动画

&::after{

animation: ${aniTag} 0.4s ease-in-out forwards;

}

}

`

// 全局样式

const GlobalStyle = createGlobalStyle`

*{

padding: 0;

margin: 0;

}

${MyButton}{

span{

color: rgba(255,255,255,0.6);

font-size: 12px;

line-height: 20px;

}

}

`

export default function StyleComponentsTest() {

return (

<Wrap>

<GlobalStyle />

<MyButton

bgNormalColor="gray"

bgHighlightColor="white"

normalColor='rgba(255,255,255,0.6)'

hightightColor="red"

>

<p><strong className="emphasize">styled components</strong> 入门</p>

<span>我是只小小鸟</span>

</MyButton>

</Wrap>

)

}

这个小demo有用到styled-components的关键技术点:

其本语法,见Wrap

动态样式实现,通过$

怎么写全局样式,见createGlobalStyle

怎么实现子/孙元素样式控制,见p和strong元素样式控制

怎么实现伪类,见:hover

怎么实现伪元素,见::after

怎么实现动画,见transition/keyframes

当全局样式和自带样式冲突的,怎么提高样式优先级,见span

示例代码都做了详细的注释,可以浏览代码了解详情

补充

其实通过实现上面示例基本算已经入门styled-components了,但是开发经常要考虑代码复用,那styled-components怎么实现CSS复用,我来优化一下demo

最终实现的效果如下:

Screen Recording 2025-10-31 at 15.16.54.gif

关键代码如下:

import styled, { keyframes, createGlobalStyle, css } from 'styled-components'

// 样式复用

const flexColCenter = css`

display: flex;

flex-direction: column;

justify-content: center;

align-items: center;

`

const textHighlightColor = css`

color: ${props => props.hightightColor ? props.hightightColor : 'white'};

`

const Wrap = styled.div`

width: 100%;

height: 100vh;

${flexColCenter}

gap: 20px;

`

// css帧动画

const aniTag = keyframes`

0% {

opacity: 0;

transform: translateY(-100%);

}

100% {

opacity: 1;

transform: translateY(0);

}

`

const MyButton = styled.div`

width: 400px;

height: 80px;

border:1px solid gray;

border-radius: 10px;

overflow: hidden;

${flexColCenter}

position: relative;

// 传参

background-color: ${props => props.bgNormalColor ? props.bgNormalColor : 'blue'};

transition: background-color 0.3s ease-in-out;

// 伪元素

&::after{

content: 'after';

height: 20px;

font-size: 14px;

line-height: 20px;

padding:0 5px;

border-radius: 0 0 6px 6px;

position: absolute;

top: 0;

right: 10px;

background-color: yellow;

${textHighlightColor}

opacity: 0;

}

// 子孙选择器

p {

line-height: 24px;

color: ${props => props.normalColor ? props.normalColor : 'black'};

transition: color 0.3s ease-in-out;

}

// 当有全局样式的时候,使用&&提高局部样式优先级来覆盖全局样式

&& span{

color: rgba(255,0,255,0.6);

}

// 类选择器

.emphasize{

text-decoration: underline;

}

// 伪类

&:hover{

background-color: ${props => props.bgHighlightColor ? props.bgHighlightColor : 'yellow'};

p{

${textHighlightColor}

}

// css animation动画

&::after{

animation: ${aniTag} 0.4s ease-in-out forwards;

}

}

`

const MyButton1 = styled(MyButton)`

border:4px solid gray;

border-radius: 20px;

`

// 全局样式

const GlobalStyle = createGlobalStyle`

*{

padding: 0;

margin: 0;

}

${MyButton}{

span{

color: rgba(255,255,255,0.6);

font-size: 12px;

line-height: 20px;

}

}

`

export default function StyleComponentsTest() {

return (

<Wrap>

<GlobalStyle />

<MyButton

bgNormalColor="gray"

bgHighlightColor="white"

normalColor='rgba(255,255,255,0.6)'

hightightColor="red"

>

<p><strong className="emphasize">styled components</strong> 入门</p>

<span>我是只小小鸟</span>

</MyButton>

<MyButton1

bgNormalColor="gray"

bgHighlightColor="white"

normalColor='rgba(255,255,255,0.6)'

hightightColor="red"

>

<p><strong className="emphasize">styled components</strong> 入门1</p>

<span>我是只小小鸟1</span>

</MyButton1>

</Wrap>

)

}

关键点:

样式复用,见flexColCenter/textHighlightColor

样式继承重写,见MyButton1

本来是想放一个在线测试案例的,找了很久都找到能用的React的playground,如果你想自己跑起示例来也是很简单的,初始化一个最简单的React示例项目并安装styled-components依赖,新建一个组件,把上面代码复制进去即可,推荐直接使用vite初始化项目

// 1命令行执行如下命令,再选择react即可

npm create vite@latest

或者直接clone我的测试仓库,你本地测试即可:demo仓库

小结

个人的知识和能力是有限的,本文只是个人练习styled-components的小demo,应该还有很多styled-components高

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/7 5:38:43

FFmpeg开发笔记(八十七)采用Kotlin的手机开源播放器VLC-Android

FFmpeg开发实战&#xff1a;从零基础到短视频上线》一书的“3.4.1 通用音视频播放器”介绍了如何在桌面系统上安装和使用通用音视频播放器VLC media player&#xff0c;其实VLC是个跨平台的播放器&#xff0c;它也提供了面向Android平台的手机版VLC。Android版VLC的官网地址是h…

作者头像 李华
网站建设 2026/8/7 15:34:18

PostgreSQL实时数据同步:5分钟掌握pg_replicate终极指南

PostgreSQL实时数据同步&#xff1a;5分钟掌握pg_replicate终极指南 【免费下载链接】pg_replicate Build Postgres replication apps in Rust 项目地址: https://gitcode.com/gh_mirrors/pg/pg_replicate PostgreSQL作为业界领先的开源关系数据库&#xff0c;其数据复制…

作者头像 李华
网站建设 2026/8/7 11:40:21

Monkey‘s Audio(无损音频压缩器)

链接&#xff1a;https://pan.quark.cn/s/4cef50ed0d24Monkey’s Audio是一套快速且易于操作的数字音乐压缩方案&#xff0c;可将WAV转成APE的音乐文件&#xff0c;他不像一般的MP3或OGG音乐格式&#xff0c;为了节省空间而失去了应有的音乐品质。强调的是保有原来的高品质音质…

作者头像 李华
网站建设 2026/8/7 22:46:19

ChatPDF终极指南:5分钟学会与PDF文档智能对话

还在为翻阅冗长PDF文档而烦恼吗&#xff1f;ChatPDF让文档阅读变得像聊天一样简单&#xff01;这个基于本地LLM的开源项目&#xff0c;通过先进的检索增强生成技术&#xff0c;让您能够与任何PDF、DOCX、TXT文件进行自然语言对话。 【免费下载链接】ChatPDF RAG for Local LLM,…

作者头像 李华
网站建设 2026/8/7 13:41:05

如何快速解决ComfyUI-SeedVR2依赖冲突:完整避坑指南

如何快速解决ComfyUI-SeedVR2依赖冲突&#xff1a;完整避坑指南 【免费下载链接】ComfyUI-SeedVR2_VideoUpscaler Non-Official SeedVR2 Vudeo Upscaler for ComfyUI 项目地址: https://gitcode.com/gh_mirrors/co/ComfyUI-SeedVR2_VideoUpscaler ComfyUI-SeedVR2视频超…

作者头像 李华
网站建设 2026/8/7 8:03:04

Java并发编程利器:从ConcurrentHashMap到Fork/Join的奇幻之旅

言&#xff1a;为什么我们需要并发容器&#xff1f;想象一下传统的超市结账场景&#xff1a;只有一个收银台&#xff0c;所有人排成一队&#xff0c;效率低下。这就是传统集合在多线程环境下的写照。而现代并发容器就像拥有多个收银台的智能超市&#xff1a;多个收银台同时工作…

作者头像 李华