资讯专栏INFORMATION COLUMN

Functional CSS: 从试着改进可重用CSS做起

microelec / 3312人阅读

摘要:从试着改进可重用做起泊学视频回想起每次更新泊学网站,最让我头疼的,就是改写。于是我几乎不假思索的写出了这样的模板它同样包含了一个封面图,一个标题和一个简介。

从试着改进可重用CSS做起

泊学4K视频

回想起每次更新泊学网站,最让我头疼的,就是改写CSS。在不同的阶段,对CSS不断深入的理解,对网站内容的调整,对UI的重用需求,都影响着CSS的编写方式,因此,稍不留神,你的代码理解就会充斥着各种风格和各种作用的CSS,让你什么时候想起这些,都觉得心情不那么愉快。

因此,就和大家分享一些心得,如何理解CSS,以及如何更有效的编写CSS。

从基于语义的CSS说起

首先,我们从一个最简单的例子开始,回想一下你的第一个CSS例子,一定和下面这样是类似的,所谓CSS,表达的就是页面DOM的样式:

  

Hello world!

然后,在text-center里,我们指定文字居中对齐的样式:

.text-center {
    text-align: center;
}

很简单对不对?随着样式越写越多,我们很快就会开始关注到一些编写CSS的建议。例如:应该把HTML和CSS的职责分开,HTML中不应该包含任何和具体样式(例如居中对齐)有关的信息,这些具体的样式都应该放到CSS中处理。

于是,我们就开始尝试着用样式要表达的语意来替换掉它表达的具体样式:

Hello world!

这样看起来就好多了。无论.greeting指定的具体样式是什么,都不影响它在HTML中表示欢迎信息样式的含义。这样,从理论上说,我们就可以用一套HTML模板,实现各种不同风格的UI了。

于是,我们就开始基于这种语义的方式,来编写各种界面了。例如,我们添加一个表示视频作者的信息卡,它的HTML模板是这样的:

Mars

The creator of boxue.io. Bla bla bla...

同样,在这个模板里,creator-info是一个按语义命名的样式,接下来,是这个样式的实现:

.creator-info {
  background-color: white;
  border: 1px solid rgba(0,0,0,0.1);
  border-radius: 4px;
  box-shadow: 0 2px 4px rgba(0,0,0,0.1);
  overflow: hidden;
  > img {
    display: block;
    width: 100%;
    height: auto;
  }
  > div {
    padding: 1rem;
    > h2 {
      font-size: 1.25rem;
      color: rgba(0,0,0,0.8);
    }
    > p {
      font-size: 1rem;
      color: rgba(0,0,0,0.75);
      line-height: 1.5;
    }
  }
}

它看上去的结果是这样的:

这里,我们的重点不是这些样式的具体内容,而是这个CSS的结构,如果我们把所有具体的样式都去掉,你就会发现,这个样式严重依赖于HTML中DOM的层次结构:

.creator-info
  > img
  > div
    > h2
    > p

因此,尽管在HTML中,我们依靠基于语义的样式剥离了CSS,但这种方式却很容易在CSS中暴露过多和HTML相关的细节。因此,这样的做法,实际上并没有完全实现剥离CSS和HTML职责的目的,我们需要更好的做法。

把样式从DOM结构中剥离出来

为了避免样式依赖DOM结构的问题,我们的思路是:让样式的命名方式兼具格式和语义的功能。然后,在DOM里,对不同位置的元素,使用对应的样式。这里,我们借鉴了BEM命名方法,对我们要使用的样式名称,统一使用这样的命名格式:主体-依赖主体的内容__内容的属性

Mars

The creator of boxue.io. Bla bla bla...

这次,我们给DOM中,每一个需要样式的元素绑定了有特定命名规则的样式。这样,在样式表里,所有的样式就可以是扁平结构的了:

.creator-info {
    background-color: white;
    border: 1px solid rgba(0,0,0,0.1);
    border-radius: 4px;
    box-shadow: 0 2px 4px rgba(0,0,0,0.1);
    overflow: hidden;
}

.creator-info__image {
    display: block;
    width: 100%;
    height: auto;
}

.creator-info__content {
    padding: 1rem;
}

.creator-info__name {
    font-size: 1.25rem;
    color: rgba(0,0,0,0.8);
}

.creator-info__description {
    font-size: 1rem;
    color: rgba(0,0,0,0.75);
    line-height: 1.5;
}

还记得当时自己把泊学网站样式修改成这样之后,着实兴奋了一阵子,因为这样的方式似乎彻底解决了HTML模板和CSS之间相互依赖的问题。

处理重复的界面布局

但是没过多久,我就发现了新的问题。当我编写首页上每个视频系列的UI组件时,结构上,它和之前的作者信息卡几乎是一样的。于是我几乎不假思索的写出了这样的HTML模板:

Machine Learning from Scratch

Let"s create a real-world machine learning demo from scratch.

它同样包含了一个封面图,一个标题和一个简介。只不过,我们把样式名称中的主体从creator换成了series。但是,当我要给这些新的样式设置值的时候,就有点儿纠结了。该如何设置这些series-***的样式呢?你可能想到了两种选择。

第一种,最直接的方法,就是把series-***按照creator-***复制一遍。这肯定可以工作,但是估计没多少人会认同这种做法,因为它违反了Don"t Repeat Yourself的原则;

第二种,如果你使用了SCSS,就可以实现从某个样式继承这样的用法:

.series-info {
    @extend .creator-info;
}

.series-info__image {
    @extend .creator-info__image;
}

.series-info__content {
    @extend .creator-info__content;
}

.series-info__name {
    @extend .creator-info__name;
}

.series-info__description {
    @extend .creator-info__description;
}

但这样做也有它自己的问题,@extend应该只在彼此有关联的样式之间使用,而不仅仅是为了避免重复编写相同的样式。并且,如果稍后我们还要视频信息卡呢?真的需要这些使用了相同样式的selector么?显然,目前的这种解决方案仍旧不够理想。

去除掉过于细致的语义

实际上,造成样式难以重用的原因,是因为selector表达的语义过于细致了。语义越细致,重用就越困难。因此,我们只要把这种绑定类似界面布局UI的selector,起个名字替代掉类似creatorseries这样的名字就好了:

.media-card {
  background-color: white;
  border: 1px solid rgba(0,0,0,0.1);
  border-radius: 4px;
  box-shadow: 0 2px 4px rgba(0,0,0,0.1);
  overflow: hidden;
}

.media-card__image {
    display: block;
    width: 100%;
    height: auto;
}

.media-card__content {
    padding: 1rem;
}

.media-card__name {
      font-size: 1.25rem;
      color: rgba(0,0,0,0.8);
}

.media-card__description {
      font-size: 1rem;
      color: rgba(0,0,0,0.75);
      line-height: 1.5;
}

这样,无论是作者信息还是视频系列信息,就都可以用同一套样式来表示了:

Machine Learning from Scratch

Let"s create a real-world machine learning demo from scratch.

甚至,只要UI布局和media-card描述的体系相同,这套样式就可以直接重用。

但是情到此结束了么?显然没有,现在,你可能又会想了:假设我们需要修改作者信息卡的样式,但仍保存视频系列信息卡的样式该怎么办呢?

如果像之前一样,它们的样式是独立的,只修改对应的样式就好了。现在,它们共享样式了,我不仅要创建新的样式,还要连同对应的HTML一起修改,这样做真的好么?

实际上根本没有绝对的职责分离

为了回答这个问题,我们得回到这一节开始提出的目的:分离HTML和CSS的职责。面对这个话题,我们直觉上就会认为,只有彻底剥离了才算完成达成目标。但实际的情况则是,它们两者根本无法做到完全分离。我们只能根据自己项目的实际情况,选择一种适合自己的方式。

对于哪些具备详细语义(.creator-info.series-info)的样式而言,此时,HTML是独立的,它完全不关心这些DOM会长成什么样子。它只暴露了一个接口,允许我们定制其中的样式。因此,这种选择下的CSS不是独立的,它依赖于样式绑定的HTML,需要以HTML为参考,定义样式的内容。

对于那些具备中立语义(.media-card)的样式而言,此时,CSS是独立的,它完全不关心自己会被用在什么元素上。此时,HTML就不是独立的了,它需要知道样式表提供了哪些内容,并基于这些内容,来编排DOM。

实际上,这两种方法,没有绝对的谁优谁劣的问题。只是你要想清楚,哪种方式更适合自己的项目。

What"s next?

看到这里,如果你和我之前有过类似的困惑,现在,你应该跃跃欲试地要调整下自己的CSS了。先别着急,在下一节里,我们将继续讨论,如何通过合理的命名,最大化实现样式的可重用目标。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/115552.html

相关文章

  • 2017-10-23 前端日报

    摘要:前端日报精选桌面通知精读前端性能优化备忘录聊聊组件间通信的几种姿势到底该如何配置深入理解高阶组件中文第期体系调研报告前端面试总结掘金技术周刊期知乎专栏从试着改进可重用做起掘金式数学作者众成翻译为什么企业进行数码变革要用平台众成 2017-10-23 前端日报 精选 HTML5 桌面通知:Notification API精读《2017前端性能优化备忘录》聊聊Vue.js组件间通信的几种姿...

    mengbo 评论0 收藏0
  • 成为一个PHP专家:缺失的环节

    摘要:为了成为一个专家,他必须先成为中级者。它非常适合于急于求成或者没有太多技术的人,但掌握绝对无法使你成为一个专业的开发者它使用意大利面条式的编码,教你的是不合适的设计原则。 这一篇文章是Becoming a PHP Professional系列 4 篇博文中的第 1 篇。 当浏览各类与PHP相关的博客时,比如Quora上的问题,谷歌群组,简讯和杂志,我经常注意到技能的等级分化。问题都类...

    cooxer 评论0 收藏0
  • jQuery最佳实践

    摘要:链式操作使用链式操作代替变量缓存和多次操作每当链长超过个链接或得到,因为活动任务的复杂,使用适当的换行和缩进使代码的可读性。对于较长的链式操作可以把对象缓存到一个变量里。 原文地址:http://lab.abhinayrathore.com/jquery-standards/ 第一次翻译,有不对不妥的地方请拍砖。showImg(http://segmentfault.com/img/b...

    wizChen 评论0 收藏0
  • 切图崽的自我修养-合理组织CSS结构

    摘要:前言不要再叫我切图崽,我很生气,这样很不礼貌,请叫我前端工程师从方面来说,前端工程师和切图崽的区别,并不是指写单条技巧的高低,甚至很多工程师在一些的奇技淫巧都比不上切图崽那切图崽到底和工程师之间的差别是什么呢差别是年工作经验视野,是格局,是 前言 不要再叫我切图崽,我很生气,这样很不礼貌,请叫我前!端!工!程!师! 从css方面来说,前端工程师和切图崽的区别,并不是指写单条css技巧的...

    cangck_X 评论0 收藏0
  • Web前端开发入门不得不看

      引  如今,各种互联网的Web应用程序层出不穷,那么如何快速入门,成长为一个优秀的Web开发工作者呢?  这个问题不容易回答,几乎所有的培训机构都不能清晰地解答。  所以对于Web开发刚刚入门的菜鸟们,我觉得只有通过去做,去实验,学会Web开发,可能是学着学着,实验着实验着就会了。  没有人告诉你如何去做。我学习的时候,我的导师只是给了我一堆视频,一堆文档。我们从明确一个目标开始:哦,这个阶段...

    Nekron 评论0 收藏0

发表评论

0条评论

microelec

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<