资讯专栏INFORMATION COLUMN

CSS语义思维

hqman / 2614人阅读

摘要:除了其本身的语法规则,我们必须自我约束,引入语义规则,不仅仅是为了提高可读性这样的理由,而是拉近人与机器的距离,让我们在思维上更加和代码契合,这样才能写出优秀的程序。

前一阵子在项目组中讲了一个关于CSS的Session,在讲之前我曾收到了许多意见,大部分是希望能讲讲CSS实用性的技术,比如盒模型,CSS3之类的。干货人人都喜欢,因为看得见摸得着,拿来就有用,但我最后还是决定讲一些”湿货“。因为在Code Diff的时候我发现了许多样式的问题不是由于不会写CSS导致的,而是由于在错误的地方使用了写在错误地方的样式。

其实CSS很简单,没有计算没有流程,只是一直描述,无论什么复杂的效果,你只要Google一下就知道怎么写了,甚至可以直接copy。但CSS又很复杂,一个元素的表现会受到它旁边的兄弟元素,也会受到内部的子元素影响,还会受到父元素影响,在这种多重影响下,一个元素的显示逻辑会变得错综复杂。有没有面对塌陷的块级元素而束手无策?无论怎么改它的属性就是得不到自己想要的,但看看似乎一模一样的示例程序却安然无恙,是不是恨得咬牙切齿?我想这就是本文所要解决的主要问题,让你学会如何优雅的写CSS。

泾渭分明 - 明确书写意图和表现语义

其实我们只要稍微接触过CSS,一定都学过盒模型,我假设你已经对margin、padding和border已经很熟悉。好了,我们经常会遇到一种情况,想让父元素和子元素之间有一些空间,比如布局的时候,container和content之间的留白。一般来说有两种方式,一种是给父元素加padding内边距,另一种是给子元素加margin外边距。现在想想,你是否慎重考虑过用哪一种方式?你是否明白两者的区别?如果你从未考虑过这些,现在考虑也不迟,这真的很重要,如果你真的想优雅的运用CSS,而不是被它耍的团团转,如果你真的想把CSS写出规模,那你就要认真的思考这里面的逻辑。

先说说父元素的container加上padding的方式,子元素的背景将不会延伸到空白区域,另一种给子元素加margin的方式则反之。但我想先抛下这个表象,看看此时加上padding的父元素的逻辑。它意味着,我创建了一个容器,并且该容器的内部有一些区域是被看不见的东西填充的,无论放入什么都不应该占据这个区域。在你的脑海中想象一个厚厚的玻璃瓶,它就好像是在说“虽然我是透明的,但是在这厚厚的玻璃之内才是你应该呆的地方,无论是什么只要你想放在瓶子里”。现在来看看子元素,是的,其背景也应该并且确实在内部,而不该占据那段空白的区域。如果是为子元素加上margin,这意味着我在容器中创建了某个东西,而这个东西有一个自己的地盘,容器内的其他东西都不能进入这里。

所以他们的本质区别在于其所表达的意义,也就是语义,一个是容器上的语义,另一个是容器内元素的语义,主语也不同,谓语意义也不同。那么这能说明什么呢,不得不提一下高级语言中的高级,这代表某个语言将机器语言封装的更好,接口更接近自然语言,其强大不言而喻。其实编程语言的发展轨迹就是不断把机器语言往自然语言翻译,让人们可以更容易的跟机器沟通,终极目标自然是人工智能,和机器用自然语言自由沟通。所以虽然代码或者说CSS的语法并没有什么变化,但我们应该在思维上清楚的区分代码片段的意图和语义来写CSS。

语言学家乔姆斯基曾构造过一句符合语法的话:

  

“Colorless green ideas sleep furiously”

意思是无色的绿色想法愤怒的睡觉。想法睡觉是违反常识的,无色的绿色是矛盾的,愤怒的睡觉是不合常理的。仅仅符合语法是不够的,仅仅不报错也是不够的,尤其是CSS这种描述性的语言很少会报错,所以我想说的是,其描述性质让我们有更多选择来实现我们所期望的效果,但我们却应该慎重,要让语义分明,而不是在有限的语法规则下任意妄为,那样写不出好的CSS代码。除了其本身的语法规则,我们必须自我约束,引入语义规则,不仅仅是为了提高可读性这样的理由,而是拉近人与机器的距离,让我们在思维上更加和代码契合,这样才能写出优秀的程序。

言归正传,究竟如何语义化CSS呢。之前有讲过OOCSS,其实面向对象的思想就是一种语义化,将虚拟的元素看作实际的对象,用常识来构造代码,就像是用户体验中的用户习惯一样,这是一种遍及全人类的用户习惯,让代码更友好,即所谓的优雅。

比如最常见的布局,我们一般都会有header、body和footer,这样无需任何说明和规则,谁都会理解,header在前,footer在后,中间是body。有趣的是table中的thead、tbody和tfoot,由于加载优化,我们即使把tfoot放在tbody前面,让其先加载,但显示的时候tfoot仍然会在tbody下面,由此可见语义化的重要,否则你一定会以为不是W3C的人弄错了标准,就是浏览器厂商搞出了Bug。虽然这是HTML标签不是CSS,但我觉得这个例子很恰当的说明了一点,显示逻辑是独立的,不应该和其他逻辑混为一谈,它应该只关心如何显示。

再比如,一个导航条一般分为左右两边,里面各有若干链接。你会如何命名?navbar-left和navbar-right是Bootstrap所使用的class,但当宽度减少,Responsive响应式的Bootstrap会让这些链接都收进下拉菜单中,左和右又从何谈起呢?同样是Bootstrap中的颜色命名就做的十分成熟,不是green、blue、red这些词汇,而是success、primary、warning这些词,它们的区别是表现化与语义化的区别,我喜欢把这个叫做显示逻辑。也就是说在class层面我们应该只关注元素(或者说对象)是用来做什么的(意图)以及它应该表示什么(语义)。这里三种颜色代表成功、重要和警告,至于我们是用绿、蓝和红来表示还是通过其他什么颜色甚至形状,应该在style层面写CSS属性表示。如此我们使用class时无需迷茫于表示成功应该用绿色还是红色,意图明确无误。回到导航栏的例子,我们应该使用main和sub之类的词语标识导航栏中重要的和次要的链接,即使在某些实现下,主要和次要没有区别也不用担心,那是该实现的显示逻辑,我们不应该横加干涉。

狡兔三窟 - 善用class与style多对多的复杂关系

说到class和style(样式属性),这又是一段混乱不清的关系。其实每当我们要实现一个样式,自觉或不自觉的都会考虑,是将元素和class一一对应,然后为元素上的class写style,还是用class和几条style对应之后在元素上搭配组合。前者的好处是每个class中的style不会影响其他class,但可用性十分的低,极端点说这已经不算是在编程了,而是在画页面;后者的好处可以灵活使用不同的样式搭配给元素使用,组合出元素需要的效果,但很难维护,牵一发动全身,样式很难测试,无法保证在你动了一条style之后,没有影响其他的地方。甚至最要命的是大部分CSS代码都是无意识的游走在这两种情况之间,所以我们要做的不是选择一种极端,而是找到一个平衡点,并使用一些方法使得我们的CSS既能灵活复用在各种元素上,又能易于维护,不致修了这破坏那的情况。

分组

首先,对于一个或一套元素的样式,我们应该有自己的创建原则,而不是想到哪写到哪。比如,我一般使用这样的步骤来创建元素:

1. 结构

首先仅关注结构布局,以站点整体为基准,将元素抽象为一个或多个结构。

比如制作一个按钮,你也许会发现它的尺寸和导航上的链接一致,而内外边距以及display和overflow之类的属性又和页面容器一样,这时你就可以把按钮的结构拆成两个结构,一个是尺寸,一个是边界逻辑,这种情况时常发生,所以有的CSS理论认为应该把width和height这对尺寸属性和padding以及margin这对边距属性彻底的分开也是这个道理。其实并不是说它们4个放一起就决定不行,只是一般它们都有各自复用的价值,所以常常被拆开使用,归根揭底这是由显示逻辑决定的。

2. 皮肤

一般由于设计统一性,我们可以借助设计指导,轻松的制作出标准皮肤。但要注意的是,皮肤指的不仅仅甚至不一定是颜色之类的。继续用Bootstrap举例,有5种基础颜色,但这并不是皮肤,5种颜色的语义不同,它们只是默认用了5种颜色,勉强可以看作默认皮肤,而真正的皮肤是theme,让按钮变得有立体感。还有一个误区就是认为哪几种属性是皮肤,哪几种不是。就像前面所说的,我们要在语义上进行划分。一个属性在某些意图下可能是结构,在另外的意图中可能是皮肤。

举个极端的例子,在一个Workshop中我用CSS和HTML制作了左边这样的Logo,Logo本身应该完全算是皮肤,因为一般来说就是一张图片,所以制作它的所有CSS属性都应该算作皮肤。下面的CSS代码中,无论是定位还是文字的处理,以及尺寸等,都是为了构造Logo,所以这些属性都是皮肤。

css#logo i, #logo b {
  position: relative;
}
#logo i {
  left: -30px;
  transform: rotate(-30deg);
  font-size: 60px;
  letter-spacing: -11px;
  opacity: 0.3;
}
#logo b {
  top: -43px;
  left: 40px;
  font-size: 68px;
  word-break: break-all;
  width: 3px;
  line-height: 10px;
  text-indent: 6px;
}
3. 状态

除了结构和皮肤,其实还有一类很容易被人忽视的样式,即使是设计人员也经常忘了它,那就是状态。最常见的是hover,鼠标触碰元素与否的状态,以及active,当前选中的标签,当前所在的分页等等。通常人们会把它划分到皮肤中,但你要明白我们划分的依据是意图,很显然,状态不是皮肤,仅仅是通常为表达某些状态时会使用一些颜色,毕竟颜色是最好的表示方法。它还与各种逻辑有着千丝万缕的联系,经常会使用JavaScript来加以控制,所以将状态多带带分出来是极有必要的,JavaScript只需要更改一个class就可以实现状态的切换,而不是在执行的时候才想起来应该把哪里隐藏把哪里显示,或者是变个颜色出个动画之类的。

使用

接着,无论我们是已经把各种写好的CSS属性分好了组,还是正准备以这种方式开始写CSS,我先引入一个语言学的术语 语块(Lexical chunk),创造这一术语的 Michael Lewis 认为语言并非由传统语法和词汇组成,而是由多个词汇的预制语块组成。我们现在分好的组其实就是一个个CSS的语块,CSS本身就是这种预制功能,我们要做的就是把style语块化,然后在HTML中写上代表它的class名称,当HTML元素上的多个class组合在一起时就组成完整的语义。

比如表示步骤的元素,这是一个形状类似标签,一个挨一个的排列的元素。我将它的尺寸等属性抽出来命名为label,然后把布局的属性组命名为float-left,如果我的设计风格是扁平化的,我可以把相关的皮肤属性命名为flat,你知道虽然扁平化一般用不着特别的属性,但我也可以写一些强制去掉圆角和渐变背景的属性。作为步骤,会分为当前的步骤,之前的步骤,以及还没到的步骤,当前的步骤可以命名为current,或者is—active,后面的步骤不能点所以可以命名为is-disable,这些都是状态。而现在我们来看看当前步骤元素是什么样的

    

总结成一句话就是“The flat label which float left is active”。这就是语义化的CSS。把组织好的语块像说话一样作用于元素上,对元素发出指令,让其变成想要的样式。而且你应该会发现,一组该元素所独有的属性,或者是尺寸之类的一般是主语,布局是动宾短语,而皮肤多是一些形容词,最后状态可以用表语。

总之,CSS作为一个描述性的语言,有很多人觉得不能算一种语言,但我反而觉得这是一种高级语言,因为更接近自然语言。当然其主要作用是在视觉渲染上,所以应该是一种受限的语言,可以看作是接近自然语言的子集。所以它的性质觉得了其重语义轻语法的特点,写CSS不能仅靠语法规则,一定要用上语义规则,最好是能和项目中所有人达成共识,CSS框架其实就是一种通用共识。


  

原文

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

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

相关文章

  • CSS语义思维

    摘要:除了其本身的语法规则,我们必须自我约束,引入语义规则,不仅仅是为了提高可读性这样的理由,而是拉近人与机器的距离,让我们在思维上更加和代码契合,这样才能写出优秀的程序。 前一阵子在项目组中讲了一个关于CSS的Session,在讲之前我曾收到了许多意见,大部分是希望能讲讲CSS实用性的技术,比如盒模型,CSS3之类的。干货人人都喜欢,因为看得见摸得着,拿来就有用,但我最后还是决定讲一些湿货...

    icattlecoder 评论0 收藏0
  • HTML,CSS,JavaScript的思维导图

    摘要:一个思维导图是把抽象的事物具体化,以一个东西为思想核心内容,映射出一系列的组成及作用影响的内容。的思维导图是层叠样式表语言,是对的语言进行样式化。我设计的思维导图如下简介,对象,编程语言基础,客户端,参考,创建与调试等等内容。 一个思维导图是把抽象的事物具体化,以一个东西为思想核心内容,映射出一系列的组成及作用 影响的内容。 HTML的思维导图 HTML是一种超文本标记语言。我认为要学...

    n7then 评论0 收藏0
  • HTML,CSS,JavaScript的思维导图

    摘要:一个思维导图是把抽象的事物具体化,以一个东西为思想核心内容,映射出一系列的组成及作用影响的内容。的思维导图是层叠样式表语言,是对的语言进行样式化。我设计的思维导图如下简介,对象,编程语言基础,客户端,参考,创建与调试等等内容。 一个思维导图是把抽象的事物具体化,以一个东西为思想核心内容,映射出一系列的组成及作用 影响的内容。 HTML的思维导图 HTML是一种超文本标记语言。我认为要学...

    chanjarster 评论0 收藏0
  • HTML,CSS,JavaScript的思维导图

    摘要:一个思维导图是把抽象的事物具体化,以一个东西为思想核心内容,映射出一系列的组成及作用影响的内容。的思维导图是层叠样式表语言,是对的语言进行样式化。我设计的思维导图如下简介,对象,编程语言基础,客户端,参考,创建与调试等等内容。 一个思维导图是把抽象的事物具体化,以一个东西为思想核心内容,映射出一系列的组成及作用 影响的内容。 HTML的思维导图 HTML是一种超文本标记语言。我认为要学...

    defcon 评论0 收藏0
  • 前端知识归纳

    摘要:继承性子标签会继承父标签样式优先级行内样式选择器类选择器标签选择器通配符继承机制创建了的元素中,在垂直方向上的会发生重叠。 技能考察: 一、关于Html 1、html语义化标签的理解; 结构化的理解; 能否写出简洁的html结构; SEO优化 a、理解:根据内容的结构化(内容语义化),选择合适的标签(代码语义化)便于开发者阅读和写出更优雅的代码的同时 让浏览器的爬虫和...

    sixleaves 评论0 收藏0

发表评论

0条评论

hqman

|高级讲师

TA的文章

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