整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

Vue3 企业级优雅实战 - 组件库框架 - 4 组件库的 CSS 架构

头条创作挑战赛#

该系列已更新的文章:

分享一个实用的 vite + vue3 组件库脚手架工具,提升开发效率

开箱即用 yyg-cli 脚手架:快速创建 vue3 组件库和vue3 全家桶项目

Vue3 企业级优雅实战 - 组件库框架 - 1 搭建 pnpm monorepo

Vue3 企业级优雅实战 - 组件库框架 - 2 初始化 workspace-root

Vue3 企业级优雅实战 - 组件库框架 - 3 搭建组件库开发环境


在前一篇文章中分享了搭建组件库的基本开发环境、创建了 foo 组件模块和组件库入口模块,本文分享组件库的样式架构设计。

该实战已更新文章:


1 常见的 CSS 架构模式

常见的 CSS 架构模式有很多:OOCSSACSSBEMSMACSSITCSS 等,其中 SMACSSITCSS 很相似。我在企业级项目中最常使用的是简化版的 ITCSS + BEM + ACSS,所以本文首先介绍这三种模式,其他模式大家自己上网查看。

1.1 ACSS

ACSS 模式几乎是一个样式属性就对应了一个样式类。这种方式非常灵活,复用性很强、维护成本低,但破坏了 CSS 命名语义化。常见的名称如:d-flex、m-10、w-20 等。

1.2 BEM

BEM 模式是一种命名方法论,其命名层级为:Block元素 Element修饰符 Modifier,这也是 “BEM” 这个名字的由来。元素 Element 使用两个短下划线(__),修饰符 Modifier 使用两个短中划线(--),如下面的 HTML 片段和对应的类名:

<div class="demo-block">
  <a class="demo-block__element1">Link</a>
  <a class="demo-block__element1 demo-block__element1--modifier">Link</a>
</div>

<style>
  .demo-block {} // 块
    .demo-block__element1 {} // 元素
    .demo-block__element1--modifier1 {} // 修饰符
</style>

使用 BEM 可以规范命令,页面结构也比较清晰。

1.3 ITCSS

ITCSS 是一种样式的分层结构,一共有七层,七个层次从上到下依次为:

  • Settings 层:通常是一些样式变量,如定义通用的颜色值、字体大小的数值等;
  • Tools 层:通用工具函数,包括 mixins、function 等;
  • Generic 层:通用基础样式,一般是对浏览器默认样式进行重置,如 normalize.css、resets 等库;
  • Base 层:对某些全局使用的元素进行通用的定制化样式,如页面的设置、ul 标签的设置等;
  • Objects 层:所有使用 OOCSS 的地方,即某些结构和样式相分离的专用类;
  • Components 层:具体的组件,其实可以对应到组件库中的每个组件;
  • Trumps 层:重写某些样式,如 width 重新设置为 100px,只会影响某一小块的 DOM 元素,权重最高,类似 ACSS,但通常会加上 !important

2 组件库的 CSS 架构

ITCSS 分层非常细致,咱们组件库的样式在其基础上进行了简化,省略了 Base 层 或 Objects 层。而对于 Trumps 层,咱使用 ACSS 来替代,对于 Components 层,里面的每个组件内部又使用 BEM。所以咱们组件库的样式架构为:简化版的 ITCSS + BEM + ACSS。

2.1 CSS 结构概览

组件库的样式使用预处理器 SCSS,从结构整体来看,分为如下层级:

  • base 层:整个 CSS 结构的最基础的层级,对应了 ITCSS 的 Settings、Generic 和 Base。即包括变量定义、通用基础样式和定制基础样式。
  • tools 层:与 ITCSS 的 Tools 一样,提供通用工具函数。
  • acss 层:类似 ITCSS 的 Trumps,定义一些原子样式类,如 flex、margin、padding 相关的样式基础类。
  • components 层:与 ITCSS 的 Components 一样,实现各个组件的样式,其中每个组件的样式又使用 BEM 方式来组织命名。

2.2 base 层的实现

前面说过,base 层包括样式变量定义、通用基础样式、定制基础样式。

首先在 packages/scss 目录下创建 base 目录,存放 base 层的 scss 文件。

  1. settings

settings 是一些变量的定义,在 packages/scss/base/ 目录中创建 _var.module.scss 文件,该文件定义样式变量。

$primary-color: #488019;
$common-padding: 20px;

:export {
  primaryColor: $primary-color;
}
  1. Generic

Generic 通常是对浏览器样式的重置,统一 HTML 标签在不同浏览器中的展示,屏蔽浏览器间的差异。在这个部分可以使用开源库normalize.cssreset.css 等。这一层可以在组件库中省略,在各个具体的应用中引入对应css。不过程序员优雅哥还是将浏览器样式重置引入到组件库中,这样应用开发过程中省点事。咱使用开源的 normalize.css 作为 Genericnormalize.css 的代码可以在 GitHub 上搜索获取。

继续在 packages/scss/base/ 目录中创建 _normalize.scss 文件,将 normalize.css 的内容直接复制进去就可以了。

  1. Base

Base 主要是存放部分重置样式的自定义,如 html、body、section 等,这部分咱们暂时没有自定义的内容,就无需编写了。

  1. 入口文件

最后需要将 base 层所有 scss 以统一的入口引入。在 packages/scss/base/ 目录下创建 index.scss,该文件导入上面创建的两个 scss 文件:

@use "var.module";
@use "normalize";

2.3 tools 层的实现

tools 层用于存放工具函数和 mixins,github 上有个优秀的开源项目 sassMagic,咱们就使用它作为 tools 层。

将该项目 src 中的代码拷贝到 packages/scss/tools/ 目录下即可(如果 _sassMagic.scss 文件中有报错,将里面对不存在文件的引入删除即可)。我在这里将 _sassMagic.scss 文件重命名为 index.scss,这样后面在使用时只需要使用 @use "../tools" 即可。

2.4 acss 层的实现

acss 层用于定义一些原子样式,这里咱们定义 flex 布局和 margin/padding 的原子类。

packages/scss/ 中创建目录 acss,并在该目录下创建两个文件:_flex.scss_mp.scss

packages/scss/acss/_flex.scss

.f {
  display: flex;
}
.f-c {
  display: flex;
  flex-direction: column;
}
.f-r {
  display: flex;
  flex-direction: row;
}
.f-1 {
  flex: 1 1 0;
}
.oy-h {
  overflow-y: hidden;
}
.oy-a {
  overflow-y: auto !important;
}
.ox-h {
  overflow-x: hidden;
}
.o-h {
  overflow: hidden;
}

packages/scss/acss/_mp.scss

$direction: (l left, r right, t top, b bottom);

@for $i from 1 through 30 {
  @each $type in m, p, v, h, a {
    // margin
    @if ($type == m) {
      @each $d in $direction {
        .m#{nth($d, 1)}-#{$i} {
          margin-#{nth($d, 2)}: #{$i}px;
        }
      }
    }
    // padding
    @else if ($type == p) {
      @each $d in $direction {
        .p#{nth($d, 1)}-#{$i} {
          padding-#{nth($d, 2)}: #{$i}px;
        }
      }
    }
    // margin/padding left/right
    @else if ($type == h) {
      .ph-#{$i} {
        padding-left: #{$i}px;
        padding-right: #{$i}px;
      }
      .mh-#{$i} {
        margin-left: #{$i}px;
        margin-right: #{$i}px;
      }
    }
    // margin/padding top/bottom
    @else if ($type == v) {
      .mv-#{$i} {
        margin-top: #{$i}px;
        margin-bottom: #{$i}px;
      }
      .pv-#{$i} {
        padding-top: #{$i}px;
        padding-bottom: #{$i}px;
      }
    }

    // all
    @else {
      .pa-#{$i} {
        padding: #{$i}px;
      }
    }
  }
}

2.5 components 层的实现

components 层对应组件库中每个具体组件的样式。在 packages/scss 中创建目录 components。首先为上一篇文章中创建的 foo 组件创建样式:在 packages/scss/components/ 目录下创建 _foo.module.scss 文件:

@import "../tools";
@import "../acss/mp";
@import "../base/var.module";

@include b('yyg-foo') {
  color: $primary-color;

  @include e('description') {
    color: #333333;
    @extend .mv-20;
  }
}

继续在 packages/scss/components/ 目录下创建 index.scss 文件,该文件中引入 components 目录下所有组件的 scss 文件:

@use "foo.module";

如果新增了其他组件,需要在 components 目录下创建该组件的样式文件,并在 components/index.scss 中引入该 scss 文件。

2.6 样式入口

packages/scss 下创建 index.scss,在里面导入所有的 scss,使用组件库时只需要引入该文件即可。

@import "./acss/flex";
@import "./base";
@import "./components";

3 在组件库中引入样式

最后只需要在组件库中引入 scss/index.scss 即可。在组件库的入口模块 packages/yyg-demo-ui/index.ts 中引入 index.scss

import '../scss/index.scss'

(在上文中的代码已经包括这一句引入了)

到此便完成了组件库样式架构的搭建,整个样式的目录结构如下:

感谢你阅读本文,如果本文给了你一点点帮助或者启发,还请三连支持一下,点赞、关注、收藏,程序员优雅哥会持续与大家分享更多干货

、首字母大写

::first-letter 伪类选择器用来指定元素第一个字母的样式。

2、透明图片阴影

相信你一定用过box-shadow属性给盒子设置阴影吧,但是当你想要给透明图片添加阴影的时候,却看起来像加了个边框!这时候神奇的drop-shadow就派上用场了。

drop-shadow 的工作方式是,其遵循给给定图片的 Alpha 通道。因此阴影是基于图片的内部形状,而不是显示在图片外面。

3、镂空文字

-webkit-text-stroke: 1px #1e80ff;

注意:镂空文字属性ie浏览器不兼容

4、背景文字

利用background-clip: text;规定背景的绘制区域,再把文字颜色设置为透明实现。

5、网页灰度效果

grayscale(amount)函数将改变输入图像灰度。amount 的值定义了灰度转换的比例。值为 100% 则完全转为灰度图像,值为 0% 图像无变化。若未设置值,默认值是 0。(如下鼠标悬浮体验效果)

6、flex布局最后一行左对齐

方法1:使用js补齐元素,例如,每行展示3个元素,现在一共有5个元素,那么我们就可以在最后补一个同宽度的透明元素。

方法2:justify-content设置为space-between实现两端对齐效果,最后一行再特殊处理:思路为选中最后一个元素,设置其右边距,挤到只能容纳最后一行元素的宽度。

方法3:justify-content设置为flex-start,先将全部元素左对齐,然后计算出每个元素的间距,通过gap设置元素间距(如果行列间距不同,可以用column-gap设置列间距,row-gap设置行间距),伪装实现两端对齐的效果。

7、毛玻璃背景效果

使用backdrop-filter与filter都可以写出高斯模糊的效果,但是两者使用起来还是有区别的,而且使用的目标也不同。


区别:

backdrop-filter:使背景模糊,不会影响到背景下面的图片

filter:通常是定义 img的可视效果,修改图片的模糊效果,值越大越模糊

8、inline元素间的空白间隙

行内元素排列的时候,明明没有边框,也没有间距,但就是有空隙。

其实间隙是由换行或者回车导致的,你可以将标签代码都写同一行即可解决。但是这样有点呆,我们可以通过设置父元素的font-size为0将空隙缩小到0。

9、文字溢出省略

单行文本:

overflow: hidden;

text-overflow: ellipsis;

white-space: nowrap;

多行文本:

display: -webkit-box;

-webkit-box-orient: vertical;

-webkit-line-clamp: 3;(多少行省略)

overflow: hidden;

注意:ie不兼容,可用min-height:省略的行数*行高 来解决;

10、列表除最后一个元素外,其他元素统一样式

一般这种情况,我们可以先全部统一样式,然后再单独设置最后一个元素样式覆盖公共样式。

也可以用 :not 选择器直接设置除了最后一个元素的样式。

:not(selector) 选择器匹配每个元素是不是指定的元素/选择器。

11、隐藏滚动条

.element::-webkit-scrollbar {

display: none;

}

12、禁止用户选择

div {

-webkit-touch-callout: none;

-webkit-user-select: none;

-khtml-user-select: none;

-moz-user-select: none;

-ms-user-select: none;

user-select: none;

}

13、暂停动画

animation-play-state可以控制动画状态


近很多做淘宝电商朋友问我:“为什么我在电脑端搜索的时候,想查看一下同行的店铺,但不管是搜索其链接还是搜索店铺id,点进去后都显示宝贝不存在,这是为什么?”对于这个问题,相信屏幕前的很多中小卖家都遇过,但是奇怪的是他们手机端却能够正常搜索和展示,起到了一个单纯屏蔽电脑端查看的效果

其实这是卖家为了防止同行盗图或者抄袭自己的宝贝标题才不得已用的方法,方法有两种,第一种是直接在淘宝服务市场购买官方的CSS权限服务,利用CSS样式来做,官方权限一年是2400元,对于中小卖家来说一定程度上成本太高了,不建议使用。

第二种可以用代码解决,可以自己给自己电脑操作,不用到处求人,现在我们来讲一下第二种方法的大概流程吧

进入店铺装修首页


找到自定义内容区,进去编辑


在这里输入达到不显示电脑端店铺的代码


最后点击发布就完成啦