「译」CSS语义化还是前端架构?

2018-07-14 admin

**特别声明:**此篇文章由Jekst根据Nicolas的英文文章原名《 About HTML semantics and front-end architecture》进行翻译,整个译文带有我们自己的理解与思想,如果译得不好或不对之处还请同行朋友指点。如需转载此译文,需注明英文出处: nicolasgallagher.com/about-html-…以及作者相关信息

——作者:Nicolas

——译者:Jekst

在此,我把我喜欢的思想,经验和主意,还有在过去的一年里,我试验过的想法汇集起来。它们包括HTML语义,前端构架的元素与途径,类命名模式和HTTP压缩。

我们探索的脚步将永无止境,直到回到最初的起点,到那时 我们才会第一次,真正了解 自己出发的地方

T.S. Eliot — “Little Gidding”

关于语义

语义是研究符号和标志,以及他们所代表的事物之间的关系的。在语言学里,主要是研究符号所表达的意思(如单词、短语或声音)。Web前端开发中,语义主要涉及到了约定好的HTML元素、属性(attribute)及属性(attribute)值的意义(包括一些扩展,如微数据)。这些约定好的语义,通常是正式的规范,可以用来更好的理解一个网站的各方面信息。但是,在定义了规范后,元素、属性(attribute)及属性(attribute)值的语义还要受到开发商共同选择和实现的影响,这就导致了后期规范化的约定好的语义要进行修改(这是 HTML设计的一个原则)。

区分不同类型的HTML语义

编写“具有语义的HTML”原则是现代、专业前端开发的一个基础。大多数的语义和自然存在的或预期内容的多方面相关(例如,h1元素、lang属性(attribute)、type属性(attribute)的email值、微数据)。

然而,并非所有的语义需要根据内容衍生出来的。类名不能是“非语义”的。无论使用什么名字,他们都需要有意义、有目的。类名语义跟HTML语义不同。我们可以使用HTML元素,某些HTML属性(attributes)、微数据等约定的“global”语义,他们的目的不会和那些网站、特定的应用程序的“local”语义产生混淆。那些“local”的语义是包含在属性(attribute)值里的,如class属性(attribute)。

尽管HTML5 specification section on classes再次假定“最佳实践”是:

“鼓励作者使用[类属性(attribute)]值来描述实际内容的本质,而不是描述那些所需的内容。”

本身没有理由这样做的。实际上,在开发大型网站或应用程序时,这样经常会是一个阻碍。

  • 内容层语义本来服务于HTML元素和其他属性(attribute)。
  • 类名给机器或者访问者提供很少或没有用的语义信息,除非是商定好的名字(并且是机器可读的)的一小部分——微格式。
  • 使用类名主要的目的是为了使用CSS和javascript。如果你不需要在你的web文档里添加表现和行为,那么在你的HTML里,就可能不需要类名。
  • 类名应该传达有用的信息给开发者。当你在阅读一个DOM代码段的时候,它有助于理解一个特定的类名是做什么的,特别是在多个开发者的团队里,前端工作者并不是唯一开发HTML组件的。

看一个非常小的例子:

<div class="news">
  <h2>News</h2>
  [news content]
</div>	

这里的类名“news”不会告诉你任何信息,从内容上看,它本身就不是很明显。关于这个组件的总体结构没有给你提供信息,它不能够用于非“news”的内容。试着将你的类名语义和实际的内容紧密结合,会降低架构可扩展性的能力和被其他开发者使用的易用性。

内容独立的类名

在一个设计里,另一种方法是根据重复结构和功能模式衍生类名语义。复用性最高的组件是那些内容独立的类名。

我们不应该担心层与层之间的连接是否清晰明确,应该担心那些反映具体内容的类名。这样做并不是意味着类名“无语义”,它仅仅意味着这些类名的语义不是根据内容衍生出来的。如果一些额外的HTML元素有助于创造更强大的、灵活的、可重用的组件,我们就不介意使用额外的HTML元素,这只是意味着你使用了更多的元素来标记内容。

前端架构

一个组件、模版、面向对象的架构的目的是能够开发一些可重用的组件,这些组件包含了一系列不同的内容类型。类名语义在大型应用程序里的重要性在于它是由实用性衍生出来并且很好的服务于这个组件的主要目的-为开发人员提供有意义,灵活,可复用的表现或行为性的接口,以便使用。

可复用、可组合的组件

总的来说,可扩展的HTML或CSS必须依赖HTML里的类来创建可复用的组件。一个灵活的、可复用的组件既不是依赖于存在的DOM树里的某个部分,也不需要使用特定的元素类型。它应该能够适应不同的容器,并且可以容易的加上样式。如果有必要,添加额外的HTML元素(除了那些仅用来标记内容的HTML元素)可以用来创建更强健的组件。一个很好的例子就是Nicole Sullivan所说的的media object.

易于组合的组件得益于使用选择器类型,而避免使用类型选择器。下面的例子降低了btn部分和uilist部分易组合性。问题在于.btn的优先级比.uilist a(会覆盖重复的属性样式)的优先级低,并且uilist需要a作为子结点。

.btn { /* styles */ }
.uilist { /* styles */ }
.uilist a { /* styles */ }	

<nav class="uilist">
  <a href="#">Home</a>
  <a href="#">About</a>
  <a class="btn" href="#">Login</a>
</nav>	

提高一个组件部分和uilist部分的易组合性的一个方法是使用类给子DOM元素添加样式。这样可以减少样式规则的特性,但是最大的好处就是允许你将结构上的样式应用到任何类型的子节点上。

.btn { /* styles */ }
.uilist { /* styles */ }
.uilist-item { /* styles */ }	

<nav class="uilist">
  <a class="uilist-item" href="#">Home</a>
  <a class="uilist-item" href="#">About</a>
  <span class="uilist-item">
    <a class="btn" href="#">Login</a>
  </span>
</nav>	

Javascript特定类

使用javascript特定类有助于降低因组件主题样式或结构改变而导致原来应用在上面的javascript不起作用的风险。我发现一个方法是使用某些只给javascript使用的类——js-*——不给这些特殊类添加任何样式呈现。

<a href="/login" class="btn btn-primary js-login"></a>	

改变组件的结构或主题将无意中影响任何所需的JavaScript行为和复杂的功能,使用这种方法,你可以减少这种无意中的情况发生。

组件修饰符

组件经常会有些变化,和基组件的呈现有稍微的不同,如不同颜色背景或者边框。有两种模式可以使用来达到这些变化。我把这两种模式称为“单类”模式和“多类”模式。

“单类”模式

.btn, .btn-primary { /* button template styles */ }
.btn-primary { /* styles specific to save button */ }

<button class="btn">Default</button>
<button class="btn-primary">Login</button>	

“多类”模式

.btn { /* button template styles */ }
.btn-primary { /* styles specific to primary button */ }

<button class="btn">Default</button>
<button class="btn btn-primary">Login</button>	

在使用“单类”模式时,如果你使用了预处理器,你可能使用Sass的@extend功能减少一些维护的工作。然而,即使有预处理器的帮助,我优先选择的是使用“多类”模式,在HTML里添加类修饰符。

我发现“多类”模式是一个更具有扩展性的模式。例如,使用基于btn的组件,进一步添加了5种按钮类型和3种按钮尺寸。使用“多类”模式,最终你需要9个类,通过混合匹配达到效果。但是使用“单类”模式你需要24个类。

如果需要,使用组件修饰符也比较容易根据上下文调整一个组件。比如你可能在另一个组件里对btn的外观要做些细微的调整,可以这么做:

/* "multi-class" adjustment */
.thing .btn { /* adjustments */ }

/* "single-class" adjustment */
.thing .btn,
.thing .btn-primary,
.thing .btn-danger,
.thing .btn-etc { /* adjustments */ }	

“多类”模式意味着你只需要一个单独的内部组件选择器去匹配任意类型的btn——在这个组件里被应用了btn的样式元素。“单类”模式意味着你需要写出任何可能的按钮类型,并且在任何时候改变了一个按钮的外观,你都需要调整这个选择器。

结构化类名

当创建组件时——并添加了“主题“——一些类用于区分不同的组件,一些类用于组件修饰符,一些类和DOM结点关联,他们被包含在一个较大的抽象呈现组件里。

很难判断btn(组件)、btn-primary(修饰符)、btn-group(组件)和btn-group-item(组件子对象)之间的关系,因为这些名字不能清楚的使人明白这些类的用途。没有一致的模式。

在过去的一年里我一直在尝试命名模式,这种模式能够帮助我更快的理解DOM片段里结点间的关系,而不是试着来回的在HTML、CSS和JS文件之间查看, 拼凑出网站的架构。这种模式主要受BEM系统方法命名的影响,但是,被我改编成一种更容易阅读的形式。

t-template-name
t-template-name--modifier-name
t-template-name__sub-object
t-template-name__sub-object--modifier-name

component-name
component-name--modifier-name
component-name__sub-object
component-name__sub-object--modifier-name

is-state-type

js-action-name
js-component-type	

我把一些结构当做抽象的“模板”,其它则当作更清晰的组件(通常建立在“模板”上)。但是这种区分并非总是必要的。

这只不过是我目前发现的一个命名模式而已。它可以采取任何形式。但是这种模式的好处在于它消除了那些只依赖(单)连接符,或者下划线,或者是驼峰格式的模糊的类名。

原始文件大小和HTTP压缩

任何关于模块化与可扩展的CSS的讨论关心的是文件大小和“膨胀“。Nicole Sullivan的言论中经常会提到文件大小存储(以及维护改进),并提到了像Facebook这样的公司采用这种方法的经历。进一步的,我想我会分享我在预处理输出时的HTTP压缩效果,以及大量使用HTML类的一些事情。

当Twitter 的Bootstrap刚面世时,我重写了编译好的CSS,以便更好地与手动操作的文件比较大小。在最小化两个文件之后,手动操作的CSS文件比预处理程序输出的小10%。但是当两个文件都通过gzip压缩后,预处理程序输出的CSS文件比手动操作的小了5%。

这强调了比较HTTP压缩后文件大小的重要性,因为减小文件大小并不能说明一切。它暗示了有经验的CSS开发者在用预处理程序时不必太过关心编译后的CSS中有一定程度的重复,因为经过HTTP压缩后,文件将变得更小。通过预处理程序处理更易于维护的CSS代码所带来的好处,要胜过关注原始CSS和压缩后输出的CSS的美观或文件大小。

在另一个实验中,我从网站上弄了一个60KB的HTML文件(由很多可重用的组件组成),删除了它的每一个class属性(attribute)。这样处理之后,文件减小到25KB。当原始文件与修改过的文件都通过gzip压缩后,它们的大小分别变为7.6KB和6KB——只相差1.6KB。自由使用class所导致的实际文件大小的结果已经不值得再去强调了。

我如何学会停止担忧的…

多年来,许多技术熟练的开发人员的经验,已经改变了大型网站和应用程序的开发方式。尽管如此,对于个人来说,放弃“语义化的HTML”的观念,意味着将由内容来决定类名(即使非要这么做,也只能作为最后的手段来使用),这通常需要你开发完一个大型的应用程序后,才能够强烈地意识到这种做法不靠谱的一面。你必须准备好抛弃老观念,寻找替代方案,甚至重新审视以前已被你摒弃的方法。

一旦你开始写大型的网站和应用,你和其他人不仅必须去维护它,而且还得积极地迭代改进。你很快会意识到即使你尽了最大的努力,你的代码仍然开始变得越来越难以维护。已经有一些人提出了他们自己的方法来解决这些问题:Nicole的博客和面向对象的CSS项目,Jonathan Snook的可扩展的模块化结构CSS,以及Yandex开发的 BEM方法。这些方法值得我们花时间去探索。

当你选择了以减少编写和编辑CSS的时间为目的的方式来编写HTML和CSS时,那么如果你想改变它们的样式,你就必须接受花更多的时间去改变HTML元素的class。无论是前端还是后端开发者 —— 任何人都可以重新排列预建的“乐高积木”,这将是相当实用的;事实证明,没有人会CSS魔法。

**译者手语:**整个翻译依照原文线路进行,并在翻译过程略加了个人对技术的理解。如果翻译有不对之处,还烦请同行朋友指点。谢谢!

关于Jekst

常用昵称jekst,目前就职于北京一家信息技术公司,主要从事。net系列的开发,热爱前端,对css、jQuery有浓厚兴趣,喜欢参加技术交流活动。欢迎交流共勉:新浪微博

如需转载烦请注明出处:

英文原文:nicolasgallagher.com/about-html-…

中文译文:www.w3cplus.com/css/about-h…

原文链接:http://www.w3cplus.com/css/about-html-semantics-front-end-architecture.html

本站文章除注明转载外,均为本站原创或编译。欢迎任何形式的转载,但请务必注明出处。

转载请注明:文章转载自 JavaScript中文网 [https://www.javascriptcn.com]

本文地址:https://www.javascriptcn.com/read-35949.html

文章标题:「译」CSS语义化还是前端架构?

相关文章
必须记住的 30 类 CSS 选择器
开篇 有 30 个 CSS 选择器你必须烂熟于心,它们适应于当今各大主流浏览器。 1.* * { margin: 0; padding: 0; } *选择器选择的是每一个单一元素。很多程序员用上面的 CSS 将所有元素的 ma...
2015-11-16
CSS2.0帮助文档(参考手册)chm下载
下载地址:CSS2.0帮助文档(参考手册)chm下载 友情提示:如果打开空白,在手册上右键属性解除锁定即可。 ...
2015-11-12
可以从CSS框架中借鉴到什么
现在很多人会使用 CSS 框架进行快速建站。   那 CSS 框架是什么呢,它通常是一些 CSS 文件的集合,这些文件包括基本布局、表单样式、网格、简单组件、以及样式重置。使用 CSS 框架大大降低工作成本进行快速建站。   当然对于一些大...
2016-03-11
如何为高负载网络优化Nginx 和 Node.js?
译者:AlfredCheung 在搭建高吞吐量web应用这个议题上,NginX和Node.js可谓是天生一对。他们都是基于事件驱动模型而设计,可以轻易突破Apache等传统web服务器的C10K瓶颈。预设的配置已经可以获得很高的并发,不过,...
2015-11-12
Web前端开发与iOS终端开发的异同
毕业之前一直在做前端开发,毕业后就转成做iOS开发,这两者有很多挺有意思的对比,尝试写下我能想到的它们的一些相同点和不同点。 语言 前端和终端作为面向用户端的程序,有个共同特点:需要依赖用户机器的运行环境,所以开发语言基本上是没有选择的,...
2016-01-13
如何编写干净高效的CSS代码
其实CSS的学习并不困难,但在一些较为大型的项目中就显得杂乱无章,变得很难管理,尤其是不同的人编写CSS的风格总会略有不同,从团队合作的层面上来说,就更加难以沟通,所以,我们为此总结了一些如何实现高效整洁的CSS代码原则: 使用Reset但...
2015-11-12
前端MV*框架的意义
经常有人质疑,在前端搞MV有什么意义?也有人提出这样的疑问:以AngularJS,Knockout,BackBone为代表的MV框架,它跟jQuery这样的框架有什么区别?我jQuery用得好好的,有什么必要再引入这种框架? 回答这些问题之...
2016-03-11
前端问答社区成立了
由雷锋网友提供的给大家相互交流的前端问答社区正式上线了,欢迎大家来此相互交流相互学习 ...
2016-03-30
2015 Web 2.0和AJAX如何做好优化
2015如何让做好web2.0和ajax的优化?JavaScript中文网总结当下提出以下四大优化意见,旨在帮助W前端开发人员有效利用APM解决上述问题。 随着Web应用程序速度与效率快速增长,网站已经成为企业与其客户进行交互的第一途径——...
2015-11-12
javascript教程:关于if简写语句优化的方法
UglifyJS是一个对javascript进行压缩和美化的工具,在它的文档说明中,我看到了几种关于if语句优化的方法。尽管我还没使用它去做一些尝试性的测试,但从这里可以看到它的确对js作了美化的工作。也许有人认为if语句就那么简单,能优化...
2015-11-12
回到顶部