找回密码
 立即注册
首页 业界区 业界 从一个按钮实例入门CSS in JS之styled-components ...

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

珠尿娜 前天 13:35
前言

最近接手一个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的小按钮效果

1.gif

小按钮的关键代码
  1. import styled, { keyframes, createGlobalStyle, css } from 'styled-components'
  2. const Wrap = styled.div`
  3.   width: 100%;
  4.   height: 100vh;
  5.   display: flex;
  6.   flex-direction: column;
  7.   justify-content: center;
  8.   align-items: center;
  9.   gap: 20px;
  10. `
  11. // css帧动画
  12. const aniTag = keyframes`
  13.   0% {
  14.     opacity: 0;
  15.     transform: translateY(-100%);
  16.   }
  17.   100% {
  18.     opacity: 1;
  19.     transform: translateY(0);
  20.   }
  21. `
  22. const MyButton = styled.div`
  23.   width: 400px;
  24.   height: 80px;
  25.   border:1px solid gray;
  26.   border-radius: 10px;
  27.   overflow: hidden;
  28.   display: flex;
  29.   flex-direction: column;
  30.   justify-content: center;
  31.   align-items: center;
  32.   position: relative;
  33.   // 传参
  34.   background-color: ${props => props.bgNormalColor ? props.bgNormalColor : 'blue'};
  35.   transition: background-color 0.3s ease-in-out;
  36.   // 伪元素
  37.   &::after{
  38.     content: 'after';
  39.     height: 20px;
  40.     font-size: 14px;
  41.     line-height: 20px;
  42.     padding:0 5px;
  43.     border-radius: 0 0 6px 6px;
  44.     position: absolute;
  45.     top: 0;
  46.     right: 10px;
  47.     background-color: yellow;
  48.     color: ${props => props.hightightColor ? props.hightightColor : 'white'};
  49.     opacity: 0;
  50.   }
  51.   // 子孙选择器
  52.   p {
  53.     line-height: 24px;
  54.     color: ${props => props.normalColor ? props.normalColor : 'black'};
  55.     transition: color 0.3s ease-in-out;
  56.   }
  57.   // 当有全局样式的时候,使用&&提高局部样式优先级来覆盖全局样式
  58.   && span{
  59.     color: rgba(255,0,255,0.6);
  60.   }
  61.   // 类选择器
  62.   .emphasize{
  63.     text-decoration: underline;
  64.   }
  65.   // 伪类
  66.   &:hover{
  67.     background-color: ${props => props.bgHighlightColor ? props.bgHighlightColor : 'yellow'};
  68.     p{
  69.       color: ${props => props.hightightColor ? props.hightightColor : 'white'};
  70.     }
  71.     // css animation动画
  72.     &::after{
  73.       animation: ${aniTag} 0.4s ease-in-out forwards;
  74.     }
  75.   }
  76. `
  77. // 全局样式
  78. const GlobalStyle = createGlobalStyle`
  79.   *{
  80.     padding: 0;
  81.     margin: 0;
  82.   }
  83.   ${MyButton}{
  84.     span{
  85.       color: rgba(255,255,255,0.6);
  86.       font-size: 12px;
  87.       line-height: 20px;
  88.     }
  89.   }
  90. `
  91. export default function StyleComponentsTest() {
  92.   return (
  93.     <Wrap>
  94.       <GlobalStyle />
  95.       <MyButton
  96.         bgNormalColor="gray"
  97.         bgHighlightColor="white"
  98.         normalColor='rgba(255,255,255,0.6)'
  99.         hightightColor="red"
  100.       >
  101.           <p><strong className="emphasize">styled components</strong> 入门</p>
  102.           我是只小小鸟
  103.       </MyButton>
  104.     </Wrap>
  105.   )
  106. }
复制代码
这个小demo有用到styled-components的关键技术点:

  • 其本语法,见Wrap
  • 动态样式实现,通过$
  • 怎么写全局样式,见createGlobalStyle
  • 怎么实现子/孙元素样式控制,见p和strong元素样式控制
  • 怎么实现伪类,见:hover
  • 怎么实现伪元素,见::after
  • 怎么实现动画,见transition/keyframes
  • 当全局样式和自带样式冲突的,怎么提高样式优先级,见span
    示例代码都做了详细的注释,可以浏览代码了解详情
补充

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

关键代码如下:
  1. import styled, { keyframes, createGlobalStyle, css } from 'styled-components'
  2. // 样式复用
  3. const flexColCenter = css`
  4.   display: flex;
  5.   flex-direction: column;
  6.   justify-content: center;
  7.   align-items: center;
  8. `
  9. const textHighlightColor = css`
  10.   color: ${props => props.hightightColor ? props.hightightColor : 'white'};
  11. `
  12. const Wrap = styled.div`
  13.   width: 100%;
  14.   height: 100vh;
  15.   ${flexColCenter}
  16.   gap: 20px;
  17. `
  18. // css帧动画
  19. const aniTag = keyframes`
  20.   0% {
  21.     opacity: 0;
  22.     transform: translateY(-100%);
  23.   }
  24.   100% {
  25.     opacity: 1;
  26.     transform: translateY(0);
  27.   }
  28. `
  29. const MyButton = styled.div`
  30.   width: 400px;
  31.   height: 80px;
  32.   border:1px solid gray;
  33.   border-radius: 10px;
  34.   overflow: hidden;
  35.   ${flexColCenter}
  36.   position: relative;
  37.   // 传参
  38.   background-color: ${props => props.bgNormalColor ? props.bgNormalColor : 'blue'};
  39.   transition: background-color 0.3s ease-in-out;
  40.   // 伪元素
  41.   &::after{
  42.     content: 'after';
  43.     height: 20px;
  44.     font-size: 14px;
  45.     line-height: 20px;
  46.     padding:0 5px;
  47.     border-radius: 0 0 6px 6px;
  48.     position: absolute;
  49.     top: 0;
  50.     right: 10px;
  51.     background-color: yellow;
  52.     ${textHighlightColor}
  53.     opacity: 0;
  54.   }
  55.   // 子孙选择器
  56.   p {
  57.     line-height: 24px;
  58.     color: ${props => props.normalColor ? props.normalColor : 'black'};
  59.     transition: color 0.3s ease-in-out;
  60.   }
  61.   // 当有全局样式的时候,使用&&提高局部样式优先级来覆盖全局样式
  62.   && span{
  63.     color: rgba(255,0,255,0.6);
  64.   }
  65.   // 类选择器
  66.   .emphasize{
  67.     text-decoration: underline;
  68.   }
  69.   // 伪类
  70.   &:hover{
  71.     background-color: ${props => props.bgHighlightColor ? props.bgHighlightColor : 'yellow'};
  72.     p{
  73.       ${textHighlightColor}
  74.     }
  75.     // css animation动画
  76.     &::after{
  77.       animation: ${aniTag} 0.4s ease-in-out forwards;
  78.     }
  79.   }
  80. `
  81. const MyButton1 = styled(MyButton)`
  82.   border:4px solid gray;
  83.   border-radius: 20px;
  84. `
  85. // 全局样式
  86. const GlobalStyle = createGlobalStyle`
  87.   *{
  88.     padding: 0;
  89.     margin: 0;
  90.   }
  91.   ${MyButton}{
  92.     span{
  93.       color: rgba(255,255,255,0.6);
  94.       font-size: 12px;
  95.       line-height: 20px;
  96.     }
  97.   }
  98. `
  99. export default function StyleComponentsTest() {
  100.   return (
  101.     <Wrap>
  102.       <GlobalStyle />
  103.       <MyButton
  104.         bgNormalColor="gray"
  105.         bgHighlightColor="white"
  106.         normalColor='rgba(255,255,255,0.6)'
  107.         hightightColor="red"
  108.       >
  109.           <p><strong className="emphasize">styled components</strong> 入门</p>
  110.           我是只小小鸟
  111.       </MyButton>
  112.       <MyButton1
  113.         bgNormalColor="gray"
  114.         bgHighlightColor="white"
  115.         normalColor='rgba(255,255,255,0.6)'
  116.         hightightColor="red"
  117.       >
  118.           <p><strong className="emphasize">styled components</strong> 入门1</p>
  119.           我是只小小鸟1
  120.       </MyButton1>
  121.     </Wrap>
  122.   )
  123. }
复制代码
关键点:

  • 样式复用,见flexColCenter/textHighlightColor
  • 样式继承重写,见MyButton1
本来是想放一个在线测试案例的,找了很久都找到能用的React的playground,如果你想自己跑起示例来也是很简单的,初始化一个最简单的React示例项目并安装styled-components依赖,新建一个组件,把上面代码复制进去即可,推荐直接使用vite初始化项目
  1. // 1命令行执行如下命令,再选择react即可
  2. npm create vite@latest
复制代码
或者直接clone我的测试仓库,你本地测试即可:demo仓库
小结

个人的知识和能力是有限的,本文只是个人练习styled-components的小demo,应该还有很多styled-components高级用法我没有了解到,如果有不对的地方或者你有更好的建议,希望不吝留言分享,一起学习一起进步

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

相关推荐

9 小时前

举报

鼓励转贴优秀软件安全工具和文档!
您需要登录后才可以回帖 登录 | 立即注册