Note some of my own understanding of the style section while looking at the element-UI source code. If there are any inaccuracy, please feel free to discuss it.

First, style directory and packaging method

1.1 Style code directory

The element-UI style code is located in the packages\theme-chalk\ SRC directory: \

Contains common style variable definitions, mixins, functions, font files, and SCSS style files for each component.

1.2 Style code packaging

In package.json in the root directory, the build:theme directive is the command for packaging styles

"build:theme": "node build/bin/gen-cssfile && gulp build --gulpfile packages/theme-chalk/gulpfile.js && cp-cli packages/theme-chalk/lib  lib/theme-chalk"Copy the code

The package command has three steps:

  1. “Node build/bin/gen – cssfile” : SCSS file is used to generate index. SCSS file. The generated index. SCSS file uses @import to import base. SCSS and SCSS files of each component, so index. SCSS can be used as the style entry file of the whole component library.

  2. Gulp build –gulpfile packages/theme-chalk/gulpfile.js” gulp build –gulpfile packages/theme-chalk/gulpfile.js”: run gulp build using packages/theme-chalk/gulpfile.js. In gulpfile.js, compile all SCSS files under packages/theme-chalk/ SRC as entry. So you can compile the entire component library style file index. CSS (compiled from index. SCSS as the entry point), or you can compile the CSS style file for each component (compiled from the SCSS file of each component as the entry point).

  3. “Cp-cli packages/theme-chalk/lib lib/theme-chalk”: a simple copy operation

Second, style variables

The style-dependent SCSS variables in element-UI are in the packages\theme-chalk\ SRC \common\var. SCSS file. Element-ui layers style variables, especially color variables. The so-called variable stratification refers to the variable is divided into three levels: the top variable derivation variable component variable.

  1. The top-level variables

    Including: brand main color, SUCCESS, Warning, Danger, INFO and other common colors. Such as:
    $--color-primary: #409EFF! default;$--color-white: #FFFFFF! default;$--color-black: # 000000! default;$--color-success: #67C23A! default;$--color-warning: #E6A23C! default;$--color-danger: #F56C6C! default;$--color-info: # 909399! default;Copy the code
  2. Variables is derived

    That is, according to the top variable, through some operation derivation. Such as:
    $--color-primary-light-1: mix($--color-white.$--color-primary.10%) !default; /* 53a8ff */
    $--color-primary-light-2: mix($--color-white.$--color-primary.20%) !default; /* 66b1ff */
    $--color-primary-light-3: mix($--color-white.$--color-primary.30%) !default; /* 79bbff */
    $--color-primary-light-4: mix($--color-white.$--color-primary.40%) !default; /* 8cc5ff */
    $--color-primary-light-5: mix($--color-white.$--color-primary.50%) !default; /* a0cfff */
    $--color-primary-light-6: mix($--color-white.$--color-primary.60%) !default; /* b3d8ff */
    $--color-primary-light-7: mix($--color-white.$--color-primary.70%) !default; /* c6e2ff */
    $--color-primary-light-8: mix($--color-white.$--color-primary.80%) !default; /* d9ecff */
    $--color-primary-light-9: mix($--color-white.$--color-primary.90%) !default; /* ecf5ff */
    Copy the code
  3. Component variables are variables that are directly used in component styles
    $--button-primary-border-color: $--color-primary! default;Copy the code

The benefits of style layering include:

  • Code specification, easy to maintain and update;
  • Friendly theme customization function, modify the top-level variables to achieve the effect of skin.

The principle of style import when importing on demand

Element-ui provides on-demand import capabilities designed to reduce the size of imported component files and thus the size of packaged project files. As we know, there is no styling code in the Element-UI component vue code, the styling of the component is written separately and packaged into a separate CSS file. So how do you introduce component styles when importing on demand? To import on demand, we need to use the babel-plugin-Component plug-in and configure:

// .babel.rc
{
  "presets": [["es2015", { "modules": false}]],"plugins": [["component"[{"libraryName": "element-ui"."styleLibraryName": "theme-chalk"}}]]]Copy the code

This is a Babel plug-in that does a very simple job: during code compilation, when a component that imports element-UI is detected, it automatically inserts a statement that imports the component’s CSS file, thus introducing the component’s style.

4. Use Sass macro (@mixin) to write BEM style code quickly

BEM is a CSS command specification designed to make CSS naming easier to read and understand. For details, please refer to this article: CSS-BEM naming conventions. The naming of BEM is widely used in Element-UI, and the way BEM is used in its style code is worth learning from.

4.1 Define b/ M/E hybrid macros

The mixed macro B /m/e is defined in the packages\theme-chalk\ SRC \mixins\mixins. SCSS file

/* BEM -------------------------- */
@mixin b($block) {
  $B: $namespace+The '-'+$block! global; . # {$B} {
    @content; }}@mixin e($element) {
  $E: $element! global;$selector: &;
  $currentSelector: "";
  @each $unit in $element {
    $currentSelector: # {$currentSelector + "." + $B + $element-separator + $unit + ","};
  }

  @if hitAllSpecialNestRule($selector) {
    @at-root {
      #{$selector#} {{$currentSelector} {
          @content; }}}}@else {
    @at-root {
      #{$currentSelector} {
        @content; }}}}@mixin m($modifier) {
  $selector: &;
  $currentSelector: "";
  @each $unit in $modifier {
    $currentSelector: # {$currentSelector + & + $modifier-separator + $unit + ","};
  }

  @at-root {
    #{$currentSelector} {
      @content; }}}Copy the code

4.2 Mixed B/M/E macros are used in service SCSS files

Take a look at the card.scss code snippet:

// card.scss
@import "mixins/mixins";
@import "common/var";

@include b(card) {
  border-radius: $--card-border-radius;
  border: 1px solid $--card-border-color;
  background-color: $--color-white;
  overflow: hidden;
  color: $--color-text-primary;
  transition: 0.3 s;

  @include when(always-shadow) {
    box-shadow: $--box-shadow-light;
  }

  @include when(hover-shadow) {
    &:hover,
    &:focus {
      box-shadow: $--box-shadow-light; }}@include e(header) {
    padding: # {$--card-padding - 2 $--card-padding};
    border-bottom: 1px solid $--card-border-color;
    box-sizing: border-box;
  }

  @include e(body) {
    padding: $--card-padding; }}Copy the code

Compiled card.css file:

.el-card {
  border-radius: 4px;
  border: 1px solid #ebeef5;
  background-color: #fff;
  overflow: hidden;
  color: # 303133;
  -webkit-transition: 0.3 s;
  transition: 0.3 s;
}
.el-card.is-always-shadow..el-card.is-hover-shadow:focus..el-card.is-hover-shadow:hover {
  -webkit-box-shadow: 0 2px 12px 0 rgba(0.0.0.0.1);
  box-shadow: 0 2px 12px 0 rgba(0.0.0.0.1);
}
.el-card__header {
  padding: 18px 20px;
  border-bottom: 1px solid #ebeef5;
  -webkit-box-sizing: border-box;
  box-sizing: border-box;
}
.el-card__body {
  padding: 20px;
}
Copy the code

Such BEM writing design can be used for reference in our own projects.

5. Response

The ability to respond to media queries is provided in Element-UI. How does that work

5.1 Responsive breakpoint variables

The responsive breakpoint variable for media queries is defined in the Packages \ Theme-chalk \ SRC \common\var. SCSS file

/* Break-point
--------------------------*/
$--sm: 768px! default;$--md: 992px! default;$--lg: 1200px! default;$--xl: 1920px! default;// maps type variable
$--breakpoints: (
  'xs' : (max-width: $--sm - 1),
  'sm' : (min-width: $--sm),
  'md' : (min-width: $--md),
  'lg' : (min-width: $--lg),
  'xl' : (min-width: $--xl));Copy the code

Where $–breakpoints is a maps type variable

5.2 Define res hybrid macros

The hybrid macro res is defined in the packages\theme-chalk\ SRC \mixins\mixins. SCSS file

/* Break-points -------------------------- */
@mixin res($key.$map: $--breakpoints) {
  // Loop breakpoint Map, return if present
  @if map-has-key($map.$key) {
    @media only screen and #{inspect(map-get($map, $key))} {
      @content; }}@else {
    @warn "Undefeined points: `#{$map}`"; }}Copy the code

Map-has-key map-get inspect is a built-in function of SCSS

5.3 Write reactive styles using RES

@include res(xs) {
  .el-col-xs-0 {
    display: none;
  }
  @for $i from 0 through 24 {
    .el-col-xs-# {$i} {
      width: (1 / 24 * $i * 100) * 1%;
    }

    .el-col-xs-offset-# {$i} {
      margin-left: (1 / 24 * $i * 100) * 1%;
    }

    .el-col-xs-pull-# {$i} {
      position: relative;
      right: (1 / 24 * $i * 100) * 1%;
    }

    .el-col-xs-push-# {$i} {
      position: relative;
      left: (1 / 24 * $i * 100) * 1%; }}}@include res(sm) {
  // Similar code, omitted
}

@include res(md) {
  // Similar code, omitted
}

@include res(lg) {
  // Similar code, omitted
}

@include res(xl) {
    // Similar code, omitted
}
Copy the code

Compiled Col.css (too much code, just show images)