Skip to content
On this page

文档

Env 环境

第一步必须设置环境,可选值有:

  • PC:对应电脑端网页

  • H5:对应手机端网页(不是 uni-app 的 H5 模式)

  • MP:对应原生小程序、uni-app 的 H5、uni-app 的小程序以及 uni-app 的 APP-VUE

  • NVUE:对应 uni-app 的 NVUE

如果你仅仅需要摘抄少量代码,请摘抄之前先复制下方代码并设置正确的值:

scss
$env: PC;

注意环境差异:

  1. PC 平台的font-12表示12px,其他平台如果希望设置相当于12px的字号时,往往需要设置font-24甚至更大数字,也就是12的 2 倍或更大的倍数。具体请查阅下方《Font 字体》一节。

  2. 由于 uni-app 的 NVUE 仅支持部分样式,所以本项目的一部分代码在 .nvue 文件内无法使用,本项目使用@if ($env != NVUE) {}进行了判断。

Basic 基础

H5 和 MP 平台页面,文本应当默认不可选,避免用户无意中长按屏幕导致选中文字。对于某些允许选择的文本,可以专门设置为select-auto

H5 和 MP 平台页面,默认隐藏滚动条,如需给某容器使用滚动条,可以专门设置:.xx-class::-webkit-scrollbar {display: block;}

关于 H5 端的font-size: calc(100vw / 7.5)的解释见《常见问题》一章。

scss
@use 'sass:math';

$unit: map-get(
  (
    PC: 1px,
    H5: 0.01rem,
    MP: 1rpx,
    NVUE: 1rpx,
  ),
  $env
);

@if ($env == PC) {
  .pointer {
    cursor: pointer;
  }
}

@if ($env == H5) {
  html {
    font-size: calc(100vw / 7.5);
  }
  body {
    font-size: 0.32rem;
    user-select: none;
  }
  .select-auto {
    user-select: auto;
  }
  ::-webkit-scrollbar {
    display: none;
  }
}

@if ($env == MP) {
  page {
    user-select: none;
  }
  .select-auto {
    user-select: auto;
  }
}

Background 背景

本节的演示图片如下,它原大小为 787x1050px,为版面美观考虑,缩到 250px 宽度:

1:背景居中,且图保持原大小

scss
@if ($env != NVUE) {
  .bg-center {
    background-position: center;
    background-repeat: no-repeat;
  }
}

2:背景居中,且最大化裁剪/最大化完整展示

scss
@if ($env != NVUE) {
  @each $val in (cover, contain) {
    .bg-#{$val} {
      background-size: #{$val};
      background-position: center;
      background-repeat: no-repeat;
    }
  }
}

左:<div class="bg-cover"></div>,右:<div class="bg-contain"></div>

对比

3:<img>图片居中,且最大化裁剪/最大化完整展示

scss
@if ($env != NVUE) {
  @each $val in (cover, contain) {
    .object-#{$val} {
      object-fit: #{$val};
      width: 100%;
      height: 100%;
    }
  }
}

左:<img class="object-cover" src="..." />,右:<img class="object-contain" src="..." />

可以看到,<img>使用样式后的效果与背景图使用样式后的效果一致。

对比

4. 最常用白、黑、灰色背景色

scss
@each $hex in ('000', '333', '666', '808080', '999', ccc, eee, f6f6f6, fff) {
  .bg-#{$hex} {
    background-color: #{'#' + $hex};
  }
}

5:白色半透明背景

scss
@each $alpha in (1, 2, 3, 4, 5, 6, 7, 8, 9) {
  .bg-a-#{$alpha} {
    background-color: rgba(255, 255, 255, math.div($alpha, 10));
  }
}

6. 弹出层的黑色半透明背景遮罩

scss
.bg-mask {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(0, 0, 0, 0.5);
}

呵呵


呵呵


呵呵


呵呵


呵呵


呵呵


呵呵


呵呵


呵呵


呵呵


呵呵


呵呵


呵呵


呵呵


弹层代码 DEMO:

html
<div id="mask" class="fixed position-0 bg-mask none" style="z-index: 100;" onclick="javascript:window.mask.classList.add('none')">
  <div class="absolute position-0 w-40 margin-auto bg-fff overflow-auto" style="height: 60vh;">呵呵</div>
</div>

Border 边框

1. border-box

scss
@if ($env != NVUE) {
  .border-box {
    box-sizing: border-box;
  }
}

border-box在左右百分比布局中可以用到,例如下方演示,即便子容器有边框和内间距,依然可以保持左右排列。如果没有border-box则会折行。

padding: 20px; border: 1px solid #ccc;
padding: 20px; border: 1px solid #ccc;

2. 强制无边框

scss
@if ($env != NVUE) {
  .border-none {
    &,
    &::before,
    &::after {
      border: none !important;
    }
  }
}

用于去掉边框。

3. 盒子呈现圆形或胶囊形

scss
.corner {
  &,
  &::before,
  &::after {
    border-radius: 10000px;
  }
}

10000px可以是随意足够大的值,这样可以让正方形变为圆形,让长方形变为胶囊形。如:

4. 不同半径的小圆角

scss
@each $radius in (4, 8, 12, 16, 20, 24, 28, 32) {
  .corner-#{$radius} {
    &,
    &::before,
    &::after {
      border-radius: #{$radius * $unit};
    }
  }

  @each $position in ('top-left', 'top-right', 'bottom-left', 'bottom-right') {
    .corner-#{$position}-#{$radius} {
      &,
      &::before,
      &::after {
        border-#{$position}-radius: #{$radius * $unit};
      }
    }
  }
}

支持设四角和设单角。不同平台下的半径值不同,比如 PC 平台的44px,H5 平台的40.04rem,MP 平台的44rpx

5. 四边 1px 真·发丝线简单实现

scss
@if ($env != NVUE) {
  .hairline {
    position: relative;
    &::after {
      content: '';
      position: absolute;
      left: 0;
      top: 0;
      right: -100%;
      bottom: -100%;
      -webkit-transform: scale(0.5);
      -webkit-transform-origin: 0 0;
      border: 1px #ccc solid;
    }
  }
}

效果(请在移动端或者高分屏观看):

也支持圆角:

6. 单边 1px 真·发丝线简单实现

scss
@if ($env != NVUE) {
  @each $dir in (top, right, bottom, left) {
    .hairline-#{$dir} {
      position: relative;
      &::after {
        position: absolute;
        box-sizing: border-box;
        content: '';
        pointer-events: none;
        background-color: #ccc;
        @if $dir != bottom {
          top: 0;
        }
        @if $dir != top {
          bottom: 0;
        }
        @if $dir != left {
          right: 0;
        }
        @if $dir != right {
          left: 0;
        }
        @if $dir == top or $dir == bottom {
          height: if($unit == 1rpx, 1rpx, 1px);
        }
        @if $dir == left or $dir == right {
          width: if($unit == 1rpx, 1rpx, 1px);
        }
      }
    }
  }
  @each $ratio in (2, 3) {
    @each $dir in (top, right, bottom, left) {
      @media only screen and (-webkit-min-device-pixel-ratio: #{$ratio}) {
        .hairline-#{$dir} {
          &::after {
            transform: if($dir == top or $dir == bottom, scaleY(#{math.div(1, $ratio)}), scaleX(#{math.div(1, $ratio)}));
          }
        }
      }
    }
  }
}

顶边:

左边:

右边:

底边:

你还可以自定义样式覆盖::after的样式,比如将颜色变成红色,代码就不举例了:

顶边:

左边:

右边:

底边:

Color 颜色

1. 色值

scss
@each $color in ('000', '333', '666', '808080', '999', 'ccc', 'eee', 'f6f6f6', 'fff') {
  .color-#{$color} {
    color: #{'#' + $color};
  }
}

本库只提供几个最常用灰色值。

红黄蓝绿等颜色不建议使用red/yellow...这种值,应从互联网上找调配好的色值,本库不涉及。

文字
文字
文字
文字
文字
文字
文字
文字
文字

2. 元素置灰

scss
@if ($env != NVUE) {
  @each $gray in (33, 50, 67, 100) {
    .gray-#{$gray} {
      filter: #{'grayscale(#{math.div($gray, 100)})'};
    }
  }
}

通常用于将按钮或其他元素置灰,表示不可点击,其中100最后生成灰度1,表示全灰。通常使用50即可,也就是"五十度灰"。

Dimension 尺寸

scss
@each $per in (5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95, 100) {
  .w-#{$per} {
    width: #{$per + '%'};
  }
}

@if ($env != NVUE) {
  .max-w-100 {
    max-width: 100%;
  }

  .max-h-100 {
    max-height: 100%;
  }

  .w-auto {
    width: auto;
  }

  .h-auto {
    height: auto;
  }
}

.w-100vw {
  width: 100vw;
}

.h-100vh {
  height: 100vh;
}

.h-50 {
  height: 50%;
}

.h-100 {
  height: 100%;
}

Flex 弹性盒

1. display

scss
.flex {
  display: flex;
}

2. flex-*

scss
@each $num in (1, 2, 3, 4, 5, 6, 7, 8) {
  .flex-#{$num} {
    flex: #{$num};
  }
}

注意,如果使用flex-1之后发现元素被内部内容撑开,需要给元素再加 class:overflow-auto

3. 防挤压

如果元素自身没有设flex-*,且要防止被兄弟元素的flex-*所挤压,那么元素可以设下面这个类。

flex: none等同于flex: 0 0 auto,约等于flex-shrink: 0

scss
@if ($env != NVUE) {
  .flex-none {
    flex: none;
  }
}

4. 折行

scss
.flex-wrap {
  flex-wrap: wrap;
}

5. 纵向排列

scss
@each $direction in (row, row-reverse, column, column-reverse) {
  .flex-#{$direction} {
    flex-direction: #{$direction};
  }
}

6. 水平垂直居中

scss
.flex-center {
  align-items: center;
  justify-content: center;
}

7. 主轴对齐方式

scss
@each $val in (flex-start, flex-end, center, space-between, space-around) {
  .justify-#{if(str-index($val, flex), str-slice($val, 6), if(str-index($val, space), str-slice($val, 7), $val))} {
    justify-content: #{$val};
  }
}

注意,.justify-*里没有flexspace字样,比如应该是justify-start而不是justify-flex-start

8. 交叉轴对齐方式

scss
@each $val in (flex-start, flex-end, center, stretch) {
  .align-#{if(str-index($val, flex), str-slice($val, 6), $val)} {
    align-items: #{$val};
  }
}

注意,.align-*里没有flex字样,比如应该写为align-start而不是align-flex-start

Font 字体

scss
@each $size in (8, 9, 10, 11, 12, 13, 14, 15, 16, 18, 20, 24, 28, 32, 36, 40, 44, 48) {
  .font-#{$size * if($unit == 1px, 1, 2)} {
    font-size: #{$size * if($unit == 1px, 1, 2) * $unit};
  }
}

.font-bold {
  font-weight: bold;
}

List 中的数字对应 PC 传统意义上的 8 像素字、13 像素字、36 像素字等。

当用于 H5 和小程序的时候,由于参考基准的问题,大概率上 PC 的 12 号字对应 H5 的0.24rem,对应小程序的24rpx,也就是说数值有一个 2 倍换算。

Grid 网格

1. display

scss
@if ($env != NVUE) {
  .grid {
    display: grid;
  }
}

2. 排版为 N 列 / N 行

scss
@if ($env != NVUE) {
  @each $num in (2, 3, 4, 5, 6, 7, 8) {
    .grid-columns-#{$num} {
      grid-template-columns: repeat(#{$num}, 1fr);
    }
    .grid-rows-#{$num} {
      grid-template-rows: repeat(#{$num}, 1fr);
    }
  }
}

仅用于均分。

通常 columns 用得多。

3. 行间距、列间距、行列间距

scss
@if ($env != NVUE) {
  @each $gap in (5, 10, 15, 20, 25, 30, 35, 40, 45, 50) {
    .grid-row-gap-#{$gap} {
      grid-row-gap: #{$gap * $unit};
    }
    .grid-column-gap-#{$gap} {
      grid-column-gap: #{$gap * $unit};
    }
    .grid-gap-#{$gap} {
      grid-gap: #{$gap * $unit};
    }
  }
}

4. 内容对齐方式

scss
@if ($env != NVUE) {
  @each $align in (start, end, center) {
    .grid-justify-#{$align} {
      justify-items: #{$align};
    }
    .grid-align-#{$align} {
      align-items: #{$align};
    }
  }
}

5. Grid 在外层容器的对齐方式

scss
@if ($env != NVUE) {
  @each $val in (start, end, center, space-around, space-between, space-evenly) {
    .grid-justify-content-#{if(str-index($val, space), str-slice($val, 7), $val)} {
      justify-content: #{$val};
    }
    .grid-align-content-#{if(str-index($val, space), str-slice($val, 7), $val)} {
      align-content: #{$val};
    }
  }
}

不常用。

注意:前提是整个 Grid 小于外层容器;类名不含space,值含有space

Layout 布局

由于其他框架通常使用 .show、.hide、.hidden 控制显示,所以本库避开这三个类名。

scss
@if ($env != NVUE) {
  @each $display in (none, inline, block, inline-block) {
    .#{$display} {
      display: #{$display};
    }
  }

  .visible {
    visibility: visible;
  }

  .invisible {
    visibility: hidden;
  }

  @each $float in (left, right) {
    .float-#{$float} {
      float: #{$float};
    }
  }

  .clearfix::after {
    content: '';
    display: block;
    height: 0;
    clear: both;
    visibility: hidden;
  }

  .overflow-hidden {
    overflow: hidden;
  }

  // 在移动端,通常凡是可滚动的内容都应使用 iOS 平滑滚动,如果你确定无需考虑 iOS 平滑滚动,则可以不使用本类
  .overflow-auto {
    overflow: auto;
    -webkit-overflow-scrolling: touch;
  }

  // 当触发锚点滚动、JS 控制的滚动时,如果希望滚动是平滑的,可以给 body 或滚动容器设上这个类
  .scroll-smooth {
    scroll-behavior: smooth;
  }
}

Margins and Paddings 外边距和填充

1. margin-*、padding-*

scss
$properties: (margin, padding);
$positions: ('', '-top', '-bottom', '-left', '-right');
$directionMap: (
  x: (
    left,
    right,
  ),
  y: (
    top,
    bottom,
  ),
);
$nums: (0, 5, 10, 15, 20, 25, 30, 40, 50, 60, 70, 80, 90, 100);
@each $property in $properties {
  @each $directionKey, $directionValue in $directionMap {
    @each $num in $nums {
      .#{$property}-#{$directionKey}-#{$num} {
        #{$property}-#{nth($directionValue, 1)}: #{$num * $unit} !important;
        #{$property}-#{nth($directionValue, 2)}: #{$num * $unit} !important;
      }
    }
    @if ($env != NVUE) {
      .#{$property}-#{$directionKey}-auto {
        #{$property}-#{nth($directionValue, 1)}: auto !important;
        #{$property}-#{nth($directionValue, 2)}: auto !important;
      }
    }
  }
  @each $position in $positions {
    @each $num in $nums {
      .#{$property}#{$position}-#{$num} {
        #{$property}#{$position}: #{$num * $unit} !important;
      }
    }
    @if ($env != NVUE) {
      .#{$property}#{$position}-auto {
        #{$property}#{$position}: auto !important;
      }
    }
  }
}

类名范例:margin-x-0 margin-x-auto margin-0 margin-top-0等等。

其中x表示横轴,即leftright的集合,同理y表示y轴,即topbottom的集合。

2. 按照宽高比裁剪背景图

scss
$ar: (
  '4-1': 25,
  '20-7': 35,
  '5-2': 40,
  '2-1': 50,
  '16-9': 56.25,
  '16-10': 62.5,
  '4-3': 75,
  '1-1': 100,
);
@each $radio, $per in ($ar) {
  .ar-#{$radio} {
    padding-bottom: #{$per + '%'};
  }
}

本代码用于生成某些锁定宽高比的容器。原理是padding-bottom如果值为百分数,参考对象为外层容器的宽度,所以,如果让本容器与外层容器等宽,不给本容器设置高度,最后设置padding-bottom,则容器高度就等于容器宽度的百分数倍。

ar为 aspect ratio(宽高比)的简写,ar-*-*通常结合bg-cover类,用于裁剪背景图片,形成小缩略图或者头像。

注意,本容器必须与外层容器等宽,通常不需给本容器设宽度,只设class="ar-4-1 bg-cover"和背景图就可以了,不要忘记bg-cover

举例,裁剪出居中的且宽高比为 4:1 的图片:

html
<div class="w-60">
  <div class="ar-4-1 bg-cover" style="background-image: url(...);"></div>
</div>

Positioning 定位

1. z-index

scss
@each $index in (0, 1, 2) {
  .z-index-#{$index} {
    z-index: #{$index};
  }
}

z-index-*常用的是1,其次是2,不常用的是0

2. 其他,不解释

scss
@each $val in (relative, absolute, fixed, sticky) {
  .#{$val} {
    position: #{$val};
  }
}

@each $dir in (top, right, bottom, left) {
  .#{$dir}-0 {
    #{$dir}: 0;
  }
}

.position-0 {
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
}

.x-0 {
  left: 0;
  right: 0;
}

.y-0 {
  top: 0;
  bottom: 0;
}

Text 文本

1. 文本水平对齐

scss
@each $align in (center, left, right) {
  .text-#{$align} {
    text-align: #{$align};
  }
}

2. 文本垂直对齐

scss
@if ($env != NVUE) {
  .vam {
    vertical-align: middle;
  }
}

文本垂直对齐的一个妙用是让图片下方的间隙消失(如果给图片设block的话会有副作用,应避免使用):

html
<div>图片下方无间隙<img class="vam" src="/....jpg" /></div>
可以看到图片下方有间隙:

可以看到图片下方无间隙:

3. 禁止换行

scss
@if ($env != NVUE) {
  .text-nowrap {
    white-space: nowrap;
  }

  .text-wrap {
    white-space: normal;
  }
}

text-nowrap除了可以让文本禁止换行,还可以阻止inline-block换行,以便形成横向滚动布局。

4. 单行文本两端对齐

scss
@if ($env != NVUE) {
  .text-justify {
    text-align: justify;
    text-align-last: justify;
    &::after {
      display: inline-block;
      width: 100%;
      height: 0;
      content: '\0020';
      overflow: hidden;
    }
  }
}

一般用于让表单左侧 Label 的文字两端对齐。

注意:文本末尾绝对不能有空白字符,否则在较旧版本的浏览器上,最后一个字后面会有空白。如果你看到下方两个示例都是完美的,说明你的浏览器较新,已经对此问题做了改进。

末尾无空白字符
末尾有空白字符

5. 缩进 2 个汉字

scss
@if ($env != NVUE) {
  .text-indent {
    text-indent: 2em;
  }
}

6. 行高

scss
@each $multiple in (14, 16, 18, 20, 22, 24, 26, 28) {
  .line-height-#{$multiple} {
    line-height: #{math.div($multiple, 10)};
  }
}

得到的行高值会是1.62.2这类值。

7. 下划线、删除线

scss
.underline {
  text-decoration: underline;
}

.no-underline {
  text-decoration: none;
}

.del {
  text-decoration: line-through;
}

8. 单行、2 行、3 行段落省略号

scss
@if ($env != NVUE) {
  .one-line {
    text-overflow: ellipsis;
    white-space: nowrap;
    overflow: hidden;
  }

  @each $key, $val in (two: 2, three: 3) {
    .#{$key}-lines {
      display: -webkit-box;
      -webkit-line-clamp: #{$val};
      -webkit-box-orient: vertical;
      text-overflow: ellipsis;
      overflow: hidden;
    }
  }
}

单行的 class 的line是单数,多行的lines是复数。

9. 数字加人民币符号

scss
@if ($env != NVUE) {
  .text-rmb::before {
    content: '¥ ';
    font-size: 80%;
    text-decoration: none;
  }
}

用于商城等,范例:322.22,带删除线范例:322.22

html
<div><span class="text-rmb">322.22</span></div>
<div><span class="text-rmb"></span><span class="del">322.22</span></div>

注意:带删除线的时候,绝对不要合成一个span,也就是不要<span class="del text-rmb">322.22</span>,因为这样人民币符号会被加上删除线,不符合惯例,也不美观。

杨亮的前端解决方案