CSS架构及Scss简单入门
一、架构的重要性
- 前期编程不重视
 - 后期重构累秃头
 
二、为什么要做CSS架构
日益膨胀的CSS代码,无计可施
项目长期处于无CSS架构维护状态
- 导致的结果
 
css代码极度混乱
css难复用、难扩展、难维护
- 预期达到的目的
 
掌握各种CSS设计模式、解决难复用、难扩展等问题
搭建企业级css结构、解决代码混乱问题
三、CSS设计模式
3.1 OOCSS
oo 面向对象
3.1.1 原则
- 容器与内容分离
 
    <!-- 容器与内容分离 -->
    <!-- post中的meta-data -->
    <div class="post">
        <p class="metadata"><span>AAA</span><span>2022-01-01</span></p>
    </div>
    <!-- comment中的meta-data -->
    <div class="comment">
        <p class="metadata"><span>AAA</span><span>2022-01-01</span></p>
    </div>
    <!-- 
        内容在不同容器中的展示是一致的 这样写css 会导致metadata不能进行复用
        .post .metadata{ css code }
        .comment .metadata{ css code } 
        优化成 => 容器写容器的代码 内容写内容的代码
        .post {css code }
        .comment {css code }
        .metadata{ css code }
    -->
- 结构(基础对象)与皮肤分离
 
    <!-- 结构(基础对象)与皮肤分离 -->
    <div class="menu fix fix1"></div>
    <!-- 
        不用修改基础对象 可以多次新增多个皮肤对象进行修改
        .menu{
            color: green;
            font-size: 14px;
        }
        .fix{
            color: red;
        }
        .fix1{
            font-size: 24px;
        }
     -->
- 面向对象开发
vue中的组件 == oocss
页面中引入同一个组件多次,可以为每个组件新增不同的class,来实现每个组件的样式区别 
3.1.2 总结
追求元件的复用,其class命名更为抽象,一般不体现具体的事物,而注重表现层的抽取
3.2 BEM
- B
块Block- - E
元素Element__ - M
修饰Modifier-- 
3.2.1 作用
命名规范、让页面结构清晰,进阶版的OOCSS

    <!-- BEM -->
    <div class="menu">
        <div class="menu__table menu__tab--style1">tab1</div>
        <div class="menu__table menu__tab--style2">tab2</div>
        <div class="menu__table menu__tab--style3">tab3</div>
        <div class="menu__table menu__tab--style4">tab4</div>
    </div>
3.3 SMACSS
3.3.1 分层
3.3.1.1 Base
- 对浏览器的默认样式进行重置
normalize.css
CSS Tools 
这里的样式只会对标签元素本身做设定,不会出现任何
class或id,但是可以有属性选择器或是伪类
3.3.1.2 Layout
- 对页面布局的一些功能
 
元素是有层级级别之分的,Layout属于较高的一层,可以作为层级较低的如:Module元素的
容器
3.3.1.3 Module
- 公共的复用的一些小模块
 - 样式模块化达到 
复用和可维护的目的 
3.3.1.4 State
- 不同状态下的一些效果
 - 更强的复用性
 
任意元素在特定状态下的外观,如信息框可能有
success和error等状态
3.3.1.5 Theme
- 不同的一些皮肤
 
不要求使用单独的class命名,如可以在Module中定义
.header,在Theme中也定义.header来切换样式(换肤),后加载覆盖前加载的样式
3.3.2 命名规范
如:
- Layout
.l-header
.l-layout-header - Module
.todoList
.todoList-title
.todoList-img - State
.is-hidden
.is-active - Theme
.theme-nav
.theme-header 
3.3.3 总结
易维护、易复用、易扩展
3.4 ITCSS
3.4.1 分层
3.4.1.1 Settings
- 包含字体、颜色定义等,通常定义可以自定义模版的变量
 
3.4.1.2 Tools
- 
mixin、function主要结合预处理器使用 
3.4.1.3 Generic
- 对浏览器的默认样式进行重置
normalize.css
CSS Tools 
3.4.1.4 Elements/Base
- 定义网站
HTML元素的样式 
3.4.1.5 Objects
- 类名样式中,不允许出现外观属性,例如: 
Color 
3.4.1.6 Components
- UI组件
 
3.4.1.7 Trumps/Utilities
- 实用程序和辅助类,能够覆盖三角形中的任何层,唯一写
important!的地方
 
3.4.2 与SMCSS的区别
层次分得更细
3.5 ACSS
一个样式属性一个类
TailWind 框架
3.5.1 好处
- 极强的复用性、维护成本低
 
3.5.2 坏处
- 破坏了css命名的语义化
 
结合多个设计模式总结的常用层

四、整合设计模式
4.1 Settings层代码实现
- 定义一些公共的变量(某个样式经常出现)
 - 颜色、边框、文字大小、阴影、层级......
 - var.scss
 
/* Color */
// 基础颜色 不区分类别 服务于其他类型的所有颜色
$color-primary: #ff5777;
$color-white: #fff;
$color-black: #000;
// 字体颜色
$color-text-primary: #333;
$color-text-secondary: #666;
$color-text-tertiary: $color-white;
$color-text-quaternary: $color-primary;
// 边框颜色
$border-color-base: #e5e5d5;
// 背景颜色
$background-color-primary: #f1f1f1;
$background-color-secondary: $color-white;
$background-color-tertiary: $color-primary;
/* Border */
$border-width-base: 1px !default;
$border-style-base: solid !default;
$border-base: $border-width-base $border-style-base $border-color-base !default;
- 在vue.config.js中全局引入
 
// vue.config.js
module.exports = {
    css: {
        loaderOptions: {
            // @/ 是 src/ 的别名
            // 注意:在 sass-loader v8 中,这个选项名是 "prependData"
            scss: {
                additionalData: `@import "@/style/settings/var.scss";`
            },
        }
    }
}
4.1 Tools层代码实现
4.1.1 SassMagic工具库
4.1.1.1 直接在github下载至本地
4.1.1.2 将src内的文件复制进自己项目的tools文件夹内
- functions
 - minxins
 - _sassMagic.scss
注意:需要根据启动项目的提示去掉functions和minxins中未存在且在_sassMagic.scss中引入的文件 
// Import Functions
@import "functions/_amcss.scss";
// @import "functions/_calc-percent.scss";
@import "functions/_convert.scss";
@import "functions/_decimal.scss";
@import "functions/_exponent.scss";
@import "functions/_leastSquaresFit.scss";
@import "functions/_linear-interpolation.scss";
@import "functions/_list-remove.scss";
@import "functions/_list-sort.scss";
@import "functions/_map-sort.scss";
@import "functions/_number.scss";
@import "functions/_polygon.scss";
@import "functions/_strip-units.scss";
@import "functions/_unit-length.scss";
@import "functions/_z-index.scss";
// Import Mixins
// @import "mixins/_alerts.scss";
@import "mixins/_amcss.scss";
@import "mixins/_angled-edges.scss";
@import "mixins/_animation.scss";
@import "mixins/_BEM.scss";
@import "mixins/_box-center.scss";
@import "mixins/_box-clamp.scss";
@import "mixins/_burger.scss";
// @import "mixins/_buttons.scss";
@import "mixins/_calc.scss";
@import "mixins/_caret.scss";
@import "mixins/_corners.scss";
@import "mixins/_equal-parts.scss";
@import "mixins/_fade-text.scss";
@import "mixins/_flex-grid.scss";
@import "mixins/_fluid-ratio.scss";
@import "mixins/_full-width.scss";
@import "mixins/_geometric-size.scss";
// @import "mixins/_gradient.scss";
@import "mixins/_haslines.scss";
@import "mixins/_HolyGrail-layout.scss";
@import "mixins/_media-queries.scss";
@import "mixins/_open-color.scss";
@import "mixins/_palettetown.scss";
@import "mixins/_plumber-box.scss";
@import "mixins/_plumber.scss";
@import "mixins/_poly-fluid-sizing.scss";
@import "mixins/_polygon.scss";
@import "mixins/_position.scss";
// @import "mixins/_resize.scss";
// @import "mixins/_ribbon.scss";
@import "mixins/_scrollbars.scss";
@import "mixins/_selector.scss";
@import "mixins/_sprite-spirit.scss";
@import "mixins/_sticky-footer.scss";
@import "mixins/_tilted.scss";
// @import "mixins/_triangle.scss";
@import "mixins/_typographic.scss";
// @import "mixins/_visuallyhidden.scss";
4.1.1.3 全局导入_sassMagic.scss
// vue.config.js
module.exports = {
    css: {
        loaderOptions: {
            // @/ 是 src/ 的别名
            // 注意:在 sass-loader v8 中,这个选项名是 "prependData"
            scss: {
                additionalData: `@import "@/style/tools/_sassMagic.scss";`
            },
        }
    }
}
4.1.1.4 可以对SassMagic瘦身,根据项目定制化需要的功能
4.2 Base层代码实现
4.2.1 Generic层
- 引入
normalize.css,重置浏览器默认样式 
npm install --save normalize.css
main.js =>import "normalize.css/normalize.css"
4.2.2 Base层
对各类元素基础样式进行补充根据当前自己的项目进行设计
- article.scss
 - form.scss
 - images.scss
 - link.scss
 - page.scss
 - ...
统一导入在一个scss文件中,然后再main.js中引入 
4.3 Components层代码实现
4.3.1 OOCSS => BEM (进阶版 OOCSS)
4.3.2 经典组件
4.3.2.1 栅格组件
配置按需使用vant
- 在components下进行配置(新建index.js)
 
import {
    Col,
    Row
} from 'vant';
const components = {
    CCol: Col,
    CRow: Row
}
const install = (app) => {
    Object.keys(components).forEach(key => {
        app.component(key, components[key])
    });
}
const mgjUI = {
    install
}
export default mgjUI
- 在main.js中引入
 
import mgjUI from '@/components/index.js'
createApp(App).use(mgjUI)
- 使用
这里的 c-row、c-col 是在 index.js 中进行了修改名称 
    <c-row>
      <c-col span="8">span: 8</c-col>
      <c-col span="8">span: 8</c-col>
      <c-col span="8">span: 8</c-col>
    </c-row>
4.3.2.2 布局组件
按照BEM的规范
component => layout

- layout
 
<template>
  <section class="c-layout" :class="{ 'c-layout--horizontal': horizontal }">
    <slot></slot>
  </section>
</template>
<script>
export default {
  name: "CLayout",
  props: {
    horizontal: {
      type: Boolean,
      default: false
    }
  }
}
</script>
<style lang="scss">
@include b(c-layout) {
  display: flex;
  flex-direction: column;
  @include m(horizontal) {
    flex-direction: row;
  }
}
</style>
- header
 
<template>
  <header class="c-header" :class="fixed && 'c-header--fixed'">
    <slot></slot>
  </header>
</template>
<script>
export default {
  name: "CHeader",
  props: {
    fixed: {
      type: Boolean,
      default: false
    }
  }
}
</script>
<style lang="scss">
@include b(c-header) {
  @include m(fixed) {
    position: fixed;
    top: 0;
    width: 100%;
    z-index: 10;
  }
}
</style>
- content
 
<template>
  <main class="c-content"><slot></slot></main>
</template>
<script>
export default {
  name: "CContent"
}
</script>
<style lang="scss">
@include b(c-content) {
  overflow: auto;
  flex: 1;
}
</style>
- aside
 
<template>
  <div class="c-aside">
    <slot></slot>
  </div>
</template>
<script>
export default {
  name: "CAside"
}
</script>
<style lang="scss">
@include b(c-aside) {
  overflow: auto;
  flex-shrink: 0;
}
</style>
- footer
 
<template>
  <footer class="c-footer">
    <slot></slot>
  </footer>
</template>
<script>
export default {
  name: "cFooter"
}
</script>
<style lang="scss">
@include b(c-footer) {
  position: fixed;
  bottom: 0;
  width: 100%;
  z-index: 10;
}
</style>
- 引入(统计新增index.js)
 
import Layout from "./layout.vue"
import Header from "./header.vue"
import Content from "./content.vue"
import Footer from "./footer.vue"
import Aside from "./aside.vue"
export {
    Layout,
    Header,
    Content,
    Footer,
    Aside
}
- 优化components下的index.js
 
import {
    Col,
    Row
} from 'vant';
import {
    Layout,
    Header,
    Content,
    Footer,
    Aside
} from './layout';
const components = {
    CCol: Col,
    CRow: Row,
    Layout,
    Header,
    Content,
    Footer,
    Aside
}
const install = (app) => {
    Object.keys(components).forEach(key => {
        // 使用第三方组件
        if (key === 'CRow' || key === 'CCol') {
            app.component(key, components[key])
        } else {
            // 第一个参数获取当前vue中的name 赋值给组件的key
            app.component(components[key]['name'], components[key])
        }
    });
}
const mgjUI = {
    install
}
export default mgjUI
- 使用
 
<template>
  <!-- <c-layout class="home__layout">
    <c-header style="background: #ff5777">header</c-header>
    <c-content style="background: #ff0">
      <div style="height: 2000px">123123</div>
    </c-content>
    <c-footer style="background: #666">footer</c-footer>
  </c-layout> -->
  <c-layout horizontal class="home__layout">
    <c-aside style="background: #ff5777">123</c-aside>
    <c-content style="background: #ff0">
      <div style="height: 2000px">123123</div>
    </c-content>
  </c-layout>
</template>
<script>
export default {
  name: 'Home'
}
</script>
<style lang="scss">
@include b(home) {
  @include e(layout) {
    height: 100vh;
  }
}
</style>
4.3.3 自定义组件
4.4 Acss层代码实现
- 让样式极限复用
 - 解决Acss无语义化缺点:属性选择器
 
<div class="c-layout" fl p10></div>
[fl]{
  float: left;
}
[p10]{
  padding:10px;
}
- Settings 与 Acss 层的关系
大多数基于settings中的var.scss中进行属性选择器的封装 
4.5 Theme层代码实现
在html标签上新增一个属性,然后通过js改变这个属性实现换肤功能,(在属性下针对页面的class进行颜色大小等元素的修改即可)
4.6 两种不同的引入方式的区别
4.6.1 在vue.config.js中引入
- 相当于在任何scss和vue(style)的文件内都引入了配置的scss
 - vue.config.js
 
module.exports = {
    css: {
        loaderOptions: {
            scss: {
                prependData: `
                @import "@/style/settings/var.scss";
                @import "@/style/tools/_sassMagic.scss";
                `
            },
        }
    }
}
xxx.scss
@import "@/style/settings/var.scss";
@import "@/style/tools/_sassMagic.scss";
.a{}
xxx.vue
<style lang="scss">
@import "@/style/settings/var.scss";
@import "@/style/tools/_sassMagic.scss";
.a{}
</style>
- 变量、minxins、function...
 
4.6.2 在main.js中引入
纯样式
五、响应式布局
5.1 什么是响应式布局
网页的元素会随着屏幕大小的变化而变化
5.2 方案
5.2.1 REM
- 安装 
npm install lib-flexible
main.js中导入 
import 'lib-flexible/flexible.js'
- 安装 
npm install postcss-plugin-px2rem -D
配置 vue.config.js 
module.exports = {
    css: {
        loaderOptions: {
            postcss: {
                plugins: [
                    require('postcss-plugin-px2rem')({
                        rootValue: 37.5,
                        exclude: /(node_module)/,
                        minPixelValue: 3,
                        selectorBlackList: ['van']
                    })
                ]
            },
        }
    }
}
- 正常编写css即可,不需要转换为rem的可以将
px单位首字母大写Px 
5.2.2 VW
5.2.3 REM+VW
六、SvgIcon多色图标
6.1 有什么优势?
- Svg 支持多色图标
 - Svg 可以控制图标不同部分、加入动画
 - Svg 是矢量图标、图标锐利、体积更小
 
6.2 IconPark
- install
npm install @icon-park/vue-next --save - 使用
 
<template>
<home theme="filled"/>
</template>
<script>
import {Home} from '@icon-park/vue-next';
export default {
  components: {
    Home
  }
}
</script>
七、Css中文字体压缩: 字蛛(font-spider)
八、Css Scroll Snap 优化滚动(移动端)
九、border-radius 原理及实现复杂图形
9.1 水平上的半径 / 垂直上的半径

9.2 简写
- 一个值全对其
border-radius: 5px;=>border-radius: 5px 5px 5px 5px / 5px 5px 5px 5px; - 奇对奇补齐、偶对偶补齐
border-radius: 5px 10px;=>border-radius: 5px 10px 5px 10px / 5px 10px 5px 10px;
border-radius: 5px 10px 15px;=>border-radius: 5px 10px 15px 10px / 5px 10px 15px 10px; - 百分比
 
先补齐,相当于盒子的宽度和高度来计算
border-radius: 10%; 假设:width = 600px ; height = 300px;
=>
border-radius: 10% 10% 10% 10% / 10% 10% 10% 10%;
border-radius: 60px 60px 60px 60px / 30px 30px 30px 30px;
9.3 示例

十、Scss
10.1 Sacc和Scss的区别
- 文件扩展名不同
sass是以.sass后缀为扩展名
scss是以.scss后缀为扩展名 - 语法不同
sass是以严格的缩进式语法规则来书
scss的语法以css语法非常相似 
10.2 特色功能
- 完全兼容css3
 - 在css基础上增加了
变量(variables)
嵌套(nesting)
混合(mixins)
等 - 通过函数进行颜色值与属性值的运算
 - 提供控制指令等高级功能
 - 自定义输出形式
 
10.3 css功能扩展
10.3.1 嵌套规则
.home {
  height: 100px;
  .redbox {
    background-color: red;
  }
}
10.3.2 父类选择器
.home {
  height: 100px;
  background: #000;
  &:hover {
    height: 200px;
  }
}
扩展
.home {
  height: 100px;
  background: #000;
  &-red {
    color: red;
  }
}
// ==
.home {
  height: 100px;
  background: #000;
}
.home-red {
  color: red;
}
10.3.3 属性嵌套
.home {
  height: 100px;
  background: #000;
  color: red;
  font: {
    size: 24px;
    weight: 400;
  }
}
// ==
.home {
  height: 100px;
  background: #000;
  color: red;
  font-size: 24px;
  font-weight: 400;
}
10.3.4 变量
.home {
  height: 100px;
  background: #000;
  &-red {
    $homeColor: red !global;
    color: $homeColor;
  }
  &-red-new {
    color: $homeColor;
  }
}
!global 将局部变量转换为当前页面的全局变量
10.3.5 数据类型
- 数字
1,2,13,10px - 字符串
"foo","bus","bar"
foo,bus,bar 
有引号字符串与无引号字符串
在编译css文件时不会改变其类型
使用 #{} 时除外,有引号字符串将被编译为无引号字符串,这样便于mixin中引用选择器名
@mixin homePage($name) {
  .home #{$name} {
    font: {
      size: 40px;
    }
  }
}
@include homePage(".home-red-new");
// ==
.home .home-red-new {
    font-size: 40px;
}
- 颜色
blue,#ff000,rgba(255,255,255,0) - 布尔值
true,false - 空值
null - 数组
1em 0 2em 10em
1em,Arial,Hellow 
用空格或逗号作分隔符
- maps
(key1: value1, key2: value2) 
相当于javascript的 object
10.3.6 运算
10.3.6.1 数字运算
- 加减乘除
 
$home-width: 600px;
.home {
  height: 100px + 1px;
  width: 100px - 50px;
  width: 200px * 2;
  width: (300px/2);
  width: $home-width/2;
}
“除”需要用括号包裹或者直接用变量相除
10.3.6.2 颜色值运算
10.3.6.3 字符串运算
- 有引号字符串位于+左侧连接无引号字符串,运算结果是有引号字符串,无引号字符串位于+左侧连接有引号字符串,运算结果为无引号字符串
 
.home {
  &::before {
    content: "Foo " + Bar;
    font: {
      family: sans- + "serif";
    }
  }
}
.home::before {
    content: "Foo Bar";
    font-family: sans-serif;
}
- 运算表达式与其他值连用时,用空格做连接符
 
.home {
  margin: 100px + 3px auto;
}
- 在有引号的文本字符串中使用
#{}插值语句可以添加动态的值 
.home {
  &::before {
    content: "1+1= #{1+1}";
  }
  &::before {
    content: "1+1= 2";
  }
}
- 空的值被视作插入了空字符串
 
.home {
  &::before {
    content: "1+1=#{$value}?";
  }
  &::before {
    content: "1+1=?";
  }
}
- 支持布尔 and or not
 - 数组不支持任何运算方式,只能使用 list functions 控制
 所有的数据类型均支持相等运算 == 或 !==
10.3.6.4 圆括号
- 圆括号可以用来影响运算顺序
 
.home {
  height: 100px * (1+1);
}
// ==
.home {
  height: 200px;
}
10.3.7 函数
@function grid-width($n) {
  @return $n * 100px;
}
.home {
  width: grid-width(4);
}
10.3.7.1 关键词参数
- 虽然不够简明,但阅读起来会更加方便
 - 可以打乱顺序使用,并且可以使用默认参数的默认值
 
@mixin bordered($color, $width: 2px) {
  border: $width solid $color;
}
.home {
  @include bordered($width: 10px, $color: red);
}
10.3.7.2 变量参数
@mixin bordered($color, $width: 2px) {
  border: $width solid $color;
}
$colorValues: 10px yellow;
.home {
  @include bordered($colorValues...);
}
十一、XMind



发表评论 (审核通过后显示评论):