最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 2021升职加薪,了解下这个 CSS 变量

    正文概述 掘金(涂鸦鸭)   2021-03-16   418

    变量大家都再熟悉不过了,为啥要代码需要变量?因为相同的数值被多个地方引用,我们将其提取为变量,这样只需要修改该变量,那么所有引用的地方都会同步修改。

    CSS自定义变量

    一直以来CSS只是简单的UI描述语言,无法像js那样使用更高级的特性,后期CSS变量的诞生赋予CSS更多的能力,让我可以实现“一次修改,多处生效”,不仅节省了开发时间,还可让我们将更多的UI变量代码(全局context, state等等)从js挪到CSS代码里,方便维护,主题换肤功能(暗色模式/深色模式/护眼模式也属于)就是CSS变量的一个使用场景。

    兼容问题

    如果你还在硬性地兼容老旧的IE11,那么很遗憾IE11并未支持,因此应禁止使用该特性,尤其是你将其应用到布局样式,诸如margin, flex, position等等,那会导致这些样式直接失效,从而使页面崩坏掉。

    这个变量没有兼容性问题

    不兼容的硬伤我们无法修复,不过好在下文所述的这个CSS变量没有兼容性问题。

    不要小看她,就算是仅存的一个变量,但是还是在很多使用场景都有所帮助!

    初体验

    很多地方都在用这个变量,只是你没察觉到,客官往下看:

    让我们创建两个普通的超链接,为了让你更好理解,我们创建两个不同样式的下划线:

    <a href="https://www.tuya.com">访问官网</a>
    <a style="text-decoration-style: wavy;" href="https://developer.tuya.com/cn">
      访问开发者
    </a>
    

    显示效果如下:

    2021升职加薪,了解下这个 CSS 变量

    我们发现下划线和波浪线看起来和字体颜色一样,让我们继续做实验:

    我们分别将两个超链接的字体颜色改为主题色涂鸦橙:rgb(255 72 0),官网活力蓝:rgb(78 133 254)

    <a style="color: rgb(255 72 0);" href="https://www.tuya.com">
        访问官网
    </a>
    <a style="color: rgb(78 133 254);text-decoration-style: wavy;" href="https://developer.tuya.com/cn">
      访问开发者
    </a>
    

    2021升职加薪,了解下这个 CSS 变量 我们惊喜的发现,不管是下划线还是波浪线,都在视觉上与字体颜色同步,但这些线可能并不是用字体画出来的

    我们甚至可以通过js获取计算样式的真实颜色值来验证:

    getComputedStyle(firstLink).textDecorationColor
    

    2021升职加薪,了解下这个 CSS 变量

    最终应用的色值就是字体颜色本身,验证了我们的猜测。其实textDecorationColor的默认值正是currentColor,现在主角登场~

    currentColor

    CSS变量值顾名思义就是当前color值,你可以这样理解:currentColot = color,该属性值用于读取和同步字体颜色,用以其他地方,比如上述波浪颜色,而我们熟知的border-color的默认值也是currentColor

    由于color可以继承父元素或者祖先元素的变量,因此对父元素只需设置一次颜色,即可穿透至底部元素。

    完整真实案例

    让我们制作这样的彩色按钮,默认是镂空按钮,hover变为实心按钮。

    2021升职加薪,了解下这个 CSS 变量

    2021升职加薪,了解下这个 CSS 变量

    这对你来说没有一点难度,让我们按照旧思路来写:

    <button class="btn">
      <span class="btn-txt">访问官网</span>
      <span class="btn-icon">
        <!-- 图标(如果需要) -->
      </span>
    </button>
    
    button {
      margin: 0;
      padding: 0;
      outline: none;
      border: none;
      background: none;
    } /* reset css用于清除button自带样式 */
    
    .btn {
      color: rgb(78 133 254); /* 默认颜色 */
      height: 30px;
      line-height: 30px; /* 高度 */
      padding: 0 8px; 
      border-radius: 6px; /* 圆角 */
      border-style: solid;
      border-width: 1px; /* 边框 */
      cursor: pointer;
    }
    
    /* hover时变实心 */
    .btn:hover {
      background-color: rgb(78 133 254);
    }
    
    .btn:active {
      opacity: .8;
    }
    
    .btn:hover > .btn-txt {
      color: white;
    }
    

    这对你来说没有任何难度,别高兴太早,往下看:

    需求增加

    现我们需要增加额外两种颜色主题,表示成功的绿色,和警示性的红色。

    2021升职加薪,了解下这个 CSS 变量

    2021升职加薪,了解下这个 CSS 变量

    这也是小菜一碟,我们在基础样式上,增加两个特性样式去覆盖字体颜色和hover背景色即可:

    /* 保持源代码不动,增加如下代码 */
    /* 成功色 */
    .btn.btn-success {
      color: #7cb305;
    }
    .btn.btn-success:hover {
      background-color: #7cb305;
    }
    
    /* 警示色 */
    .btn.btn-warning {
      color: #ff4d4f;
    }
    .btn.btn-warning:hover {
      background-color: #ff4d4f;
    }
    

    然后我们在需要使用的地方添加新增样式即可:

    <!-- 应用警告色 -->
    <button class="btn btn-warning">
      <span class="btn-txt">访问官网</span>
      <span class="btn-icon">
        <!-- 图标(如果需要) -->
      </span>
    </button>
    

    封装组件

    我们需要将其封装为React组件,下面写个伪代码示范下:

    const colorTheme = {
      success: 'btn-success',
      warning: 'btn-warning',
    }
    
    // 出于时间原因,代码全程省略非空控判断,请自觉添加;请自觉forwardRef.
    const Button = (props) => {
      const { children, theme, className: customerClassName, ...restAsHTMLAttr } = props
      const themeClassName = colorTheme[theme] || ''
      const classNames = ['btn', themeClassName, customerClassName].join(' ')
    
      return (
        <button className={classNames} {...restAsHTMLAttr}>
          <span className="btn-txt">{children}</span>
          <span className="btn-icon">
            {/* 图标,如果需要 */}
          </span>
        </button>
      )
    }
    
    

    然后我们可以通过theme属性来轻松切换我们想要的按钮:

    <Button theme="success">登录</Button>
    <Button theme="warning">注销账号</Button>
    

    难度升级

    现要求我们组件支持自定义颜色值,因为有可能我们用于不同项目,不同项目使用不同色系,就需要对该基础组件进行自定义颜色后再二次封装为业务组件。

    由于我们无法预知未来有多少种颜色,因此在基础组件中,我们无法通过写样式来配置themeColor,鬼知道未来有多少种颜色,因此我们需要使用者直接将颜色值通过props传进来。

    接受颜色属性

    现在我们通过propscolor获取自定义颜色值,然后将其应用到按钮的color style中:

    const colorTheme = {
      success: 'btn-success',
      warning: 'btn-warning',
    }
    
    const Button = (props) => {
      const {
        children,
        theme,
        color,
        className: customerClassName,
        style: customerStyle,
        ...restAsHTMLAttr
      } = props
      const themeClassName = colorTheme[theme] || ''
      const classNames = ['btn', themeClassName, customerClassName].join(' ')
    
      const colorStyle = {
        color, //接受自定义颜色
        ...customerStyle,
      }
    
      return (
        <button style={colorStyle} className={classNames} {...restAsHTMLAttr}>
          <span className="btn-txt">{children}</span>
          <span className="btn-icon">
            {/* 图标,如果需要 */}
          </span>
        </button>
      )
    }
    
    

    支持hover

    目前我们通过color来修改了按钮颜色,但是我们需要处理hover态,但js没有hover事件,我们可以通过两个事件来模拟,比如mouseovermouseleave,而且我们需要颜色改变,这里可以使用state,思路如下:

    //以下均为伪代码
    const { color } = props
    const normalStyle = { color }
    const hoverStyle = {
      backgroundStyle: color,
    }
    
    const [colorStyle, setColorStyle] = useState({
      ...normalStyle
      //...用户传入的style这里略过,请自行处理
    })
    

    接下来在mouseover事件中,将style改变为背景色:

    //切换到背景色
    onMouseOver = () => {
      setColorStyle(hoverStyle)
      //其他代码省略
    }
    

    最后在mouseleave中切换为字体色:

    //切换回字体色
    onMouseLeave = () => {
      setColorStyle(normalStyle)
      //其他代码省略
    }
    

    当然如果你不想用state,你可以在事件回调中直接拿到dom,通过event.target.style.xxx = XXX,修改样式,不过同样不友好。

    因为写这么多事件竟然只是为了改个背景色,原本纯U组件变得不纯粹,这样做很恶心,我是非常讨厌写一堆这样的代码,要是能挪到css就好了。

    使用currentColor优化

    注意到了吗?上述背景色只是为了同步字体颜色,那么我们就使用currentColor来优化,修改我们的CSS如下:

    .btn {
      color: rgb(78 133 254);
      height: 30px;
      line-height: 30px;
      padding: 0 8px;
      border-radius: 6px;
      border-style: solid;
      border-width: 1px;
      cursor: pointer;
    }
    
    .btn:hover {
      background-color: currentColor; /* 同步color */
    }
    
    .btn:active {
      opacity: .8;
    }
    
    .btn:hover > .btn-txt {
      color: white;
    }
    

    那么接下来我们只需要操作color就可以同步背景色了,所以我们要把以前无用的,操作背景的代码统统删掉!

    /* 成功色 */
    .btn.btn-success {
      color: #7cb305;
    }
    /* 通通删掉 */
    /* .btn.btn-success:hover {
      background-color: #7cb305;
    } */
    
    /* 警示色 */
    .btn.btn-warning {
      color: #ff4d4f;
    }
    /* 通通删掉 */
    /* .btn.btn-warning:hover {
      background-color: #ff4d4f;
    } */
    

    最后只留下了两个颜色。接着修改我们的组件,将mouseover, mouseleavestate等一堆杂七杂八的东西全删掉,只留下修改color的代码,最后代码精简到如下:

    const colorTheme = {
      success: 'btn-success',
      warning: 'btn-warning',
    }
    
    const Button = (props) => {
      const {
        children,
        theme,
        color,
        className: customerClassName,
        style: customerStyle,
        ...restAsHTMLAttr
      } = props
    
      const themeClassName = colorTheme[theme] || ''
      const classNames = ['btn', themeClassName, customerClassName].join(' ')
      const colorStyle = {
        color, //接受自定义颜色
        ...customerStyle,
      }
    
    
      return (
        <button style={colorStyle} className={classNames} {...restAsHTMLAttr}>
          <span className="btn-txt">{children}</span>
          <span className="btn-icon">
            {/* 图标,如果需要 */}
          </span>
        </button>
      )
    }
    

    小技巧

    借助color可以继承的特性,如下的场景卡片,会有一个主题色(下图所示的黄色),并且需要根据配图来变化。
    多个标题和按钮的颜色可以继承卡片,我们只需要将颜色设置在卡片最大容器上,然后将Button颜色设置为inherit即可继承至卡片的颜色,从而不需要在js代码里将颜色层层往下传递或者使用context

    2021升职加薪,了解下这个 CSS 变量

    更多场景

    颜色还可以用于box-shadow,甚至是svgfill属性,做到svg icon和字体颜色自动同步,以省去我们通过自定义样式层层修改颜色值的时间。antd的部分svg图标也用到currentColot

    2021升职加薪,了解下这个 CSS 变量


    起源地下载网 » 2021升职加薪,了解下这个 CSS 变量

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元