绘制与修饰

写在前面

本文是对 resume.jade & resume.scss 源码中 『经历』部分 的补充说明,请在 FirstWeb.app 中对照源码、并尝试修改。

HTML+CSS 有点像 油画,可以一层、一层的画上去,以至完善。
在浏览器中浏览 resume.jade 的时候,同时修改 resume.scss 139 行附近,将 .timelines 随意改成 .timelines_tmp 类似的,令其样式不生效,看效果如何;然后再重新修改回 .timelines 以备后用。大抵就能明白 一层一层 的意思了。

HTML+CSS 是实用主义偏向的,能达到效果,在代码结构、层次并不糟糕的前提下,怎么来都可以。

HTML 源码

div.timelines
    div.timeline.left_timeline.current_timeline
        p.title Z.R.E.Y Co., LTD.
        span.summary Dec 2012 to Now  Product Leader
    div.timeline.right_timeline
        p.title Funny Co., LTD.
        span.summary Nov 2011 to Dec 2012 Chief Architecture
    div.timeline.left_timeline
        p.title BAE
        span.summary Jul 2007 to Nov 2011 UED Leader
    div.timeline.right_timeline
        p.title No.1 School of the Earth
        span.summary Dec 2003 to Jun 2007 MBA
    .clear

如上,是 timeline 相关原始的 HTML (Jade) 源码,它代表了页面的骨架。

左右分栏

我们要先将下面这种原始的状态,分成左右两栏:

这里的左右两栏,仅仅是视觉上的,内容都还在同一个父 DOM 元素里,或者说,HTML 并未改变过。

实现这个布局,CSS 的逻辑代码很简单:

.timeline { width: 47%; }
.left_timeline { float: left; clear: left; }
.right_timeline { float: right; clear: right; }

绘制中间线条

下面 SCSS 代码中地 &:before ,也就相当于 CSS 的 .timelines:before,术语叫 伪元素。同理还有 :after,也就是在当前元素的 before 或者 after 再插入一个 (『伪造的』) DOM 元素。

绘制中线的 SCSS 代码如下所示:

.timelines {
    position: relative;
    display: block;
    &:before {
        display: block;
        position: absolute;
        width: 2px;
        height: 100%;
        left: 50%;
        content: "";
        background: #dddddd;
    }
}

一个 伪元素,一般需要设定 content,即使 content 是空字符,不然这个 伪元素 可能并不会被创建出来。之后,就将其作为一个普通的元素,设定尺寸(宽高)、位置以及其它属性即可。

你可以尝试将 :before 改成 :after,但是需要增加额外的属性: top: 0; z-index: -1;。这个尝试后,会对 beforeafter 的逻辑有更好的理解,当然对于绝对位置的坐标也会有更好的理解。
如果后面在查看『继续理解』之『理解布局』时候,反过来再看本段的内容,也可以加深理解。

于是,我们未在修改 HTML 元素的前提下,实现了一条中间的分割线:

绘制线条上的圆点

线条上的圆点,也使用 伪元素 的方式实现,一个元素,在其 width == height == border-radius 三者等同的情况下,实质上就是一个 了。

再结合元素的 backgroundborder 的属性,就能对这个 进行修饰了:

  1. 只有 border,那么相当于一个 圆边
  2. 只有 background,那么相当于一个 实心圆
  3. 如果圆的半径很小,border 很粗,就相当于一个 空心圆
  4. 像 Demo 中的,是 border 的颜色跟页面背景一样都是 #fff,且有 background,则构建了线条上圆点的空白间隙;
  5. 还有比如外部再裹一层甚至多层父元素,也是同样手法的圆,就可以产生 圆环 了;
  6. etc

resume.jade 实际的 CSS 样式代码:

.timeline:before{
    content: "";
    position: absolute;

    width: 6px;
    height: 6px;
    border-radius: 6px;
    background: #bbbbbb;
    border: 2px solid #ffffff;

    left: 50%;
    margin-left: -4px;
    margin-top: 6px;
}

线条上的圆点也绘制成功了:

产生参差感

我们最终要实现如下图的参差感:

实现的逻辑很简单,就是每个 .timeline 块,给一个 margin-top,而唯独第一个的 margin-top0,就可以了。

实际的SCSS 代码:

.timeline{
    margin-top: 45px;
    &:first-child {
        margin-top: 0;
    }
}

其最终编译为 CSS 的源码为:

.timeline {margin-top: 45px;}
.timeline:first-child {margin-top: 0;}

其中 .timeline:first-childCSS 选择器 的一种,在这里表示 第一个 .timeline。具体可以使用关键词 CSS 选择器 从搜索引擎中获得知识。
另一方面,如果认为 CSS 选择器 用起来也不是很好理解,或者容易用错,那么也没有关系,我们完全可以换一个思路:

  1. 仍然所有的 .timeline 给一个 margin-top
  2. 创建一个新的类,比如叫 .timeline_without_margin_top,并设定 margin-top:0
  3. 在 Jade 中,给第一个 .timeline 元素,新增一个 .timeline_without_margin_top 的 class。

简而言之,就是手工实现对第一个元素的属性设定,那么就用不到 first-child 这个选择器了。

绘制箭头

这里一笔带过,因为后面一文《边框构建的箭头》中有详细的说明。

思考

后续在『继续理解』中有一篇是『理解布局』,里面介绍了一种应对绝大数场景的布局方法,到时候再回过头来看,你可能会感觉到就本文内容而言,有一点不适用性 (这其实是错觉)。
为什么呢?因为这次 timeline 的布局是 Z 字型的。

假设我们面对的是如下的内容:

1-1    |     2-1
1-2    |     2-2
1-3    |     2-3

那么很容易左右分栏,然后左边管左边的布局,右边管右边的,各自为政,互不干扰。

而我们此次实际面对的虽然是视觉左右分布,但内容仍然上下关联:

1   |     2
3   |     4
5   |     6

说起来,也是非常常见的 float 布局,看起来左右分栏了,也只是视觉上的,而实际的内容、代码上都没有因为分栏而产生分裂。