放松一下,看看CSS切图规范和技巧

872 阅读8分钟

前言

记得 2016 年刚参加工作那会,进的第一家公司的前端分组是有细分切图和 JS 两个方向。前端界面一般是由 UI 设计师出图后,由切图组来还原页面,完成后再交给 JS 人员进行功能开发。

要想尽可能的还原设计图,中间的细节还是很多的。当时切图组有着自己的规定和技巧,能够快速产出高还原度的页面和高质量的 HTML、CSS 代码。

最初 CSS 写法野生的我代码会存在下面问题:

  • Modal, Popup, Tip 的 z-index 混乱
  • important 滥用
  • 布局自适应差
  • ...

经过切图组的历练,代码规范和质量都提升不少,同时也能粗略看出别人 CSS 编写的水平。

本文中 CSS 前预处理器使用的 Less。

代码规范

定义变量

定义若干 Less 变量,提高代码的维护性,规范和统一样式。

  1. 主题色调。主色调:@primary,辅助色:@sub,警告色:@warn
  2. 其他色调。如边框,背景,字体颜色
  3. 尺寸类型。圆角,字号,通用高度(按钮,输入框)
  4. 统一样式。阴影 box-shadow
  5. 规范性数值。z-index

一般情况下我们都是使用第三方组件库进行开发,组件库已经完成了这些变量的定义,所以我们只需定义一些自己项目的通用变量即可。

使用指令化繁为简

通过 Less 可以定义通用指令,解决一些重复性工作,化繁为简,规范写法,便于后期维护。

  1. 文本超出显示省略号
.tof() {
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

.tof2(@line) {
  overflow: hidden;
  text-overflow: ellipsis;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: @line;
}
  1. 多倍图使用
.bg-image(@url) {
  background-image: url("@{url}@2x.png");
  background-size: 100%;
  background-repeat: no-repeat;
  @media (-webkit-min-device-pixel-ratio: 3), (min-device-pixel-ratio: 3) {
    background-image: url("@{url}@3x.png");
  }
}

代码风格

代码规范各个团队会有所不同,定义出自己的风格就行。

  • 为了保证一致性和可扩展性,每个声明应该用分号结束(包括最后一条声明),每个声明换行
  • 声明块的右花括号应当单独成行
  • 当一个规则包含多个选择器时,每个选择器声明必须独占一行
  • 在文件结尾添加一个空白行
  • 缩进:使用 2 个空格做为一个缩进层级
// bad
.exa2, .exa3:focus, .exa4 {
    display: inline-block; width: 24px; color: gray;}

// good
.exa2,
.exa3:focus,
.exa4 {
    display: inline-block;
    width: 24px; color: gray;
}

虽然最后样式都被压缩成无空格无换行的紧凑型,但代码的规范性直接影响着美观、团队协作效率。可以将规则加入 stylelint

属性顺序

团队内有统一的属性顺序规范会让你在编写或调试 CSS 时感到愉悦。统一的属性顺序好处也很明显:提高代码的可读性,便于查找。

根据属性的重要性按顺序书写,先写定位布局类属性,后写盒模型等自身属性,最后是文本类及修饰类属性

定位布局自身属性文本类及修饰类
displaywidthfont
positionheighttext-align
floatmarginwhite-space
toppaddingbackground
.........
// bad
.box {
   font-family: 'Arial', sans-serif;
   border: 3px solid #ddd;
   left: 30%;
   position: absolute;
   background-color: #eee;
   right: 30%;
   display: block;
   font-size: 24px;
   overflow: hidden;
   padding: 1rem;
}

// good
.box {
    display: block; // 定位布局
    position: absolute;
    left: 30%;
    right: 30%;
    overflow: hidden;
    padding: 1rem; // 自身属性
    border: 3px solid #ddd;
    background-color: #eee;
    font-size: 24px; // 文本类及修饰类
    font-family: 'Arial', sans-serif;
}

当然,实际编写中不可能完全按定义好的顺序来写,不过大概是按上面三类来书写,最后可以使用 stylelint、stylelint-order 来格式化一下

嵌套层级

选择器的嵌套层级应不大于 3 级,位置靠后的限定条件应尽可能精确。

除了模块名和作用对象之外,中间的用于控制作用范围的选择器可以尽可能的少,只要能与其它的定义区分开即可,并不一定非得把所有的层级都写进去。这样可以更好的减少权值的大小 ,有利于后继的重定义。

这个早期我在切图组开发的时候,使用的是 BEM 规范。

// 普通
<div class="news">
    <div class="news_listwrap">
        <ol class="news_list">
            <li class="news_item">
                <span class="title"></span>
                <span class="time"></span>
            <li>
        <ol>
    <div>
<div>

.news .news_list .time {}

// BEM 
<div class="news">
    <div class="news__listwrap">
        <ol class="news__list">
            <li class="news__item">
                <span class="news__title"></span>
                <span class="news__time"></span>
            <li>
        <ol>
    <div>
<div>

.news__time {}

现在开发一般都使用 CSS Modules,CSS Modules 能有效的避免样式冲突,所以一般情况我们都不会嵌套超过三层。

正确使用标签

想起我早期的切图作品,里面的 html 标签就是 div 一把写。正确的使用 html 标签也是让你的代码阅读性提高很多,也有助于 SEO。

tag.png

一些常见的注意点:

  • div 无任何语义,最好只用于页面的布局和容器。
  • 尽量不在行内元素里套块级元素,如:<span><p></p></span>
  • 一个页面只能使用一个 <h1> 标签
  • 尽量不要为了样式写空标签,可以用 :before 和 :after 来控制,图片按钮之类除外。
  • ul 和 li 之间不能有其他标签,虽然不会报错,但他们是配对的呀,不能有第三者

减少使用标签选择器

减少使用标签选择器,使用具有语义的 class 类名。从分离的角度考虑,在表现层中不应该分配 html 标记/语义。

有时我们会把一个有序列表需要被改成一个无序列表,或者一个 div 将被转换成 article。使用标签选择器的话到时 html 和 css 都要修改,增加工作量。

// bad
div.exa1 header.exa2 > h2 {
 font-size: 28px;  
}

//good
.exa1 .exa2 > .exa3 {
    font-size: 28px; 
}

合理使用 z-index 值

将 z-index 进行分层,对文档流外绝对定位元素的视觉层级关系进行管理。z-index 值不易设置过高。 同层的多个元素,如多个由用户输入触发 的Dialog,在该层级内使用相同的 z-index 或递增 z-index。 建议每层包含100个 z-index 来容纳足够的元素,如果每层元素较多,可以调整这个数值。

@zindex-fix: 100; // fixed, topbar, backtotop
@zindex-dd: 500; // dropdown
@zindex-modal: 1000 // pop

使用第三方组件开发的话,组件库一般已经设置好合理的 z-index 数值,直接使用就行。

处理样式自适应能力

如果你直接复制设计稿的相关属性,那你的样式自适应能力有时就比较差。比如设计稿一个宽度为 120px 的按钮,你没有自适应相关的意识的话,直接写死了 120px, 要是按钮文字比设计稿多,这时样式就出问题了.

// bad
.btn {
    width: 120px;
}

// good
.btn {
    min-width: 120px;
}

媒体查询

Media Query 不要单独编排,需要与相关的规则一起定义

// bad
.header {}
.content {}
@media (...) {
    .header {}
    .content {}
}

// good
.header {
    @media (...) {}
}
.content {
    @media (...) {}
}

布局的正确姿势

页面级布局 —— 顶、底部固定

layout.png

/** 常规布局 */
.ui-layout {
    position: relative;
    padding-top: 64px;
    padding-bottom: 64px;
    overflow: hidden;
    box-sizing: border-box;
    
    .ui-layout__header {
        position: absolute;
        left: 0;
        top: 0;
        right: 0;
        height: 64px;
    }
    
    .ui-layout__body {
        height: 100%;
        overflow-y: auto;
        overflow-x: hidden;
    }
    
    .ui-layout__footer {
        position: absolute;
        left: 0;
        bottom: 0;
        right: 0;
        height: 64px;
    }
}

/** flex 布局 */
.ui-layout {
    display: flex;
    flex-direction: column;
    
    .ui-layout__header {
        height: 64px;
    }
    
    .ui-layout__body {
        flex: 1;
        overflow-y: auto;
        overflow-x: hidden;
    }
    
    .ui-layout__footer {
        height: 64px;
    }
}

页面级布局 —— 底部固定

内容少时,底部固定在最下方;内容多时,底部跟随内容滚动

layout2.png

.ui-layout {
    position: relative;
    min-height: 100%;
    padding-bottom: 64px;
    box-sizing: border-box;
    
    .ui-layout__footer {
        position: absolute;
        left: 0;
        bottom: 0;
        right: 0;
        height: 64px;
    }
}

常见效果的写法

水平列表出现滚动条

skill.png

<div class="wrap">
    <ul class="box">
        <li>1</li>
        <li>2</li>
    </ul>
<div>
.wrap {
    overflow-x: auto;
    overflow-y: hidden;
}

.box {
    white-space: nowrap;
    
    li {
        display: inline-block;
        width: 50px;
        height: 50px;
    }
}

长宽等比

需求1:实现一个长宽必须要等比(如16:9)的容器

需求2:一个元素宽度为屏幕宽度的50%,高度等于宽度,宽高比为1:1(一个正方形)

skill2.png

实现方式:基于容器 width 给 padding 一个百分比。如实现正方形的容器,设置 padding-top: 100%

实现原理:元素的 padding-top 或 padding-bottom 的百分比值是根据父元素的 width 进行计算的。

条件:元素 height: 0,且 box-sizing: border-box;

举例:实现 16:9 的容器:9 / 16 * 100% = 56.25%

.wrap {
  width: 200px;
}

.box {
    position: relative;
    width: 100%;
    padding-top: 100%;
    overflow: hidden;
    .content {
        position :absolute;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        width: 100%;
    }
}

你也可以直接使用 aspect-ratio 来实现,不过需要处理兼容性问题,可以引入 postcss-aspect-ratio-polyfill 处理

.box {
  width: 200px;
  aspect-ratio: 1/1;
}

总结

早期的 css 很多布局和兼容性都要花很多时间和耐心去处理。不过随着现代浏览器快速迭代,css 新特性的直接使用让我们可以快速写出页面,比如 flex 布局。flex 布局出现后,大部分页面上的页面结构都可以使用 flex 布局来完成。不过旧的方式也需要去了解,在了解的过程中会对 css 各个属性有更深理解,也会学到像 BFC 这样的概念。

总之,CSS 编写规范还是很重要的,有利于团队协作和代码维护。

本文正在参加「金石计划」