天天看点

一封写给 CSS 的情书

<b>本文讲的是一封写给 CSS 的情书,</b>

<b></b>

https://user-gold-cdn.xitu.io/2017/6/23/73b12f2b44aa17838547e30dd56f8cab

当我和同事们谈及我对 CSS 的热爱有增无减时,他们一个个盯着我看,好像我做了个不幸的人生决定一样。

“TJ,来坐这,我们来聊聊你小时候做的那个糟糕的选择是如何注定你一生的失败的。”

有时候我觉得开发者们 —— 这星球上最固执己见的一批人 —— 只有一条共识:CSS 是最垃圾的。

嘲讽 CSS 是在技术大会上博众人一笑的最佳手段之一,黑 CSS 的表情包也早已泛滥成灾,我觉得不放两个在这都对不起大家。

但是今天我要给你们洗洗脑了。我要说服你相信 CSS 是你日常所使用的最好的技术之一,CSS设计精美,每次你打开 <code>.css</code> 文件的时候都应该心存感激!

我的论点相当简单明了:为构建复杂的用户界面创建一个全面的样式系统是非常困难的,任何 CSS 的替代方案都只会比 CSS 更糟而已。

为了论证我的观点,我会将 CSS 同其他几种样式系统相比较,首先来看一种比较古老的技术。

大学期间我曾用 Java applets 技术编写过一些应用,这是一种现在几乎已经被淘汰了的技术。Java appltes 基本上就是一些 Java 应用,你可以使用 <code>&lt;applet&gt;</code> 标签随意地将其嵌入浏览器中。运气好的话,可能有一半用户在本地安装了版本正确的 Java,并能成功运行你的应用。

一个简单的 Java applet,带你回到 90 年代末

Java applets 在 1995 年推出,并在随后的几年里逐渐流行了起来。如果你在 90 年代末就已经在出来浪了的话,那你应该记得那场关于 web 技术和 Java applets 的技术论战。

和大多数用于构建用户界面的技术一样,Java applets 允许你改变用户界面上各种控件的外观。而且由于 Java applets 被视为 web 开发的合理替代技术,有时会将在 applets 中进行控件布局的便捷性和用 web 技术实现相同的功能作比较。

Java applets 显然没有使用 CSS,那它究竟是如何进行 UI 布局的呢?并不容易。

首先应该注意的是,Java applets 没有提供将代码逻辑和样式进行分离的方法,就像你可能在网页上使用 HTML 和 CSS 一样。它将作为本文剩余部分的主题。

其次,创建两个按钮并改变其背景颜色需要编写大量代码。此刻你要是在想,“呵呵,这种方法在开发实际应用的时候很快就会变得不可控了”,那么你便开始能理解为什么 web 技术最终战胜了 Java Applets 了。

话虽如此,但我知道你在想什么。

“TJ,你还没有完全说服我 CSS 的样式系统比 Java Applet 的更好呢。你这标准应该设得更高一点嘛。”

没错,Java applet 的可视化 API 并非界面设计的黄金准则,因此让我们将注意力转到当前的开发中来:Android 应用。

在 Android 应用中,界面控件的定义写在 XML 文件中,而与这些控件交互的逻辑则写在单独的 Java 文件中。这点很像 web 应用 —— HTML 文件负责标签结构,独立的 JavaScript 文件负责行为逻辑。

如下代码是一个非常简单的 Android “activity”(基本就是个页面)的标签结构:

这对 web 开发者而言可能会有点晕,但请记住,一个基本的“index.html”文件也有其怪异之处。 你在这里看到的是两个 UI 组件,一个 <code>&lt;android.support.constraint.ConstraintLayout&gt;</code> 和一个 <code>&lt;android.widget.Button&gt;</code>,每个组件又有各种属性。直观起见,上述应用在 Android 手机上的运行效果如下图所示。

让我们回到本文主旨上来,如何为这些组件赋予样式呢?和 web 中的 <code>style</code> 属性类似,基本上 Android 的每个 UI 组件都有各种属性,你可以为这些属性赋值来控制组件的外观。

例如,如果你想改变上例中按钮的背景颜色,你可以使用 <code>android:background</code> 属性。在下面的代码中我便应用了该属性使按钮背景变为红色。

到现在为止还挺好。 Google 推荐的 Android 开发环境 Android Studio 甚至提供了一个强大的可视化编辑器,可以很容易地配置其中的一些常见属性。 下面的图片显示了这个示例应用程序在 Android Studio 中的设计视图。 请注意,你可以使用屏幕右侧的窗格轻松配置诸如“背景”等属性。

通过类似设计试图这样的工具,将一些基础样式应用于 Android 界面控件是非常简单的。不过,Android 的优点也就止于此了。

实际应用开发所需要的可远不止基础样式,根据我个人的经验,处理复杂样式是 Android 代码之冗余而 CSS 代码之简洁的分水岭。举例来说,假设你需要创建一个易于复用的键值对的集合——类似于 CSS 中的 class。在 Android 中也可以做类似的事情,不过很快就会变得一团糟。

Android 应用有一个 <code>styles.xml</code> 文件,可以在其中创建具有层级结构的 XML 代码块。例如,假设你想要应用中所有的按钮都具有红色的背景,那你可以使用如下代码创建一个 “RedTheme” 样式:

如此,你便可以将 <code>android:theme="@style/RedTheme"</code> 属性应用到对应的顶层 UI 组件中。如下代码所示,我将该属性应用到了上文示例中的顶层布局组件中。

这可以实现所需效果,在此布局组件中的所有按钮确实变成了红色,不过我们可以回过头想一下。在 CSS 中一行 <code>button { background: red; }</code> 就可以搞定的事情,竟然要用那么多 XML 代码。而且随着应用越来越大,这种方式也只会变得越来越复杂。

一般来说,Android 中稍微复杂点的样式往往需要涉及到嵌套的 XML 配置文件或是一大堆用于创建可扩展组件的 Java 代码——无论哪种方式都不能令我满意。

再来看看媒体查询(media queries)。Android 允许你实现类似于 CSS 媒体查询的属性并将其用于 UI 组件中,但这完全是耦合在标签结构中的,根本无法在页面或视图间复用。

我们本可以将 CSS 的特性都过一遍,但通过上述几个例子便可得出一个结论:在 Android 中确实可以实现各种样式效果,但其实现方法总是要比在 web 上实现复杂很多。

讨论 Android XML 的冗余性很简单,但要真地想出一种清晰简洁而且能在大规模应用上运行良好的 UI 组件样式机制却是非常难的。主观上你肯定可以举出和上述 Android 例子一样糟糕的 CSS 的例子,但使用这两种技术工作过后,我会毫不犹豫地选择 CSS。

为保证论述完整性,让我们再来讨论另外一种可以渲染 UI 组件的平台:iOS。

为了你能更好地理解我在说些什么,下图展示了在 iOS 应用中如何为视图添加两个按钮。

值得注意的是,开发 iOS 应用并非一定要用 Storyboard,但其替代方法需要用 Objective-C 或 Swift 代码开发大部分用户界面,因此苹果官方推荐 iOS 开发使用 storyboards。

让我们回到本文主旨上来,如何为 iOS 中的 UI 组件赋予样式呢?你可能已经猜到了,在可视化编辑器中配置 UI 控件各自的属性是很容易的一件事情。例如,如果想改变一个按钮的背景颜色,使用屏幕右侧的菜单就可以轻易地实现。

和 Android 很像,为构件配置各种属性是很简单的。但同样和 Android 类似,当需求变得复杂时事情也就更棘手了。例如,在 iOS 应用中如何使多个按钮的看起来完全一样呢?这就不简单了。

此处的关键点不在于具体细节,因此我不会详细说明每一行 Swift 代码的作用。关键在于为多个控件赋予样式不可避免地会涉及到 Objective-C 或 Swift 代码,而这在 CSS 中只需要定义一个简单的类名即可搞定。

公平地说,原生开发者也能指出 CSS 中一些诡异的特性,而且在某种程度上他们也没错。毕竟,无论是 Web 还是诸如 iOS 和 Android 这样的原生平台,界面组件的定位、样式、动画以及处理各种设备的兼容性都不是什么简单的事情。任何全面的样式系统都不可避免地作出一些取舍,但是,在各种软件行业都工作后,我觉得 CSS 凭借诸多优势脱颖而出了。

话虽如此,如果您愿意的话,CSS 的灵活性也允许你忽略关注点分离原则,而通过应用代码来处理所有样式。 诸如 React 这样的框架便采取了这种方法,而不需要对 CSS 语言或架构作任何改动。

在如何为界面控件赋予样式方面,Android 和 iOS 的机制都比较严格,而 web 则有多种选择,你可以选择最满足你实际需求的那一种。

CSS 是一种相对简单的语言。从上层来看,CSS 不过是定义了一系列键值对的选择器的集合。这种简单性使得很多事情都可能实现。

CSS 的简单性带来的不仅仅是转译器。你在 web 上看到的每一个主题构建器(theme builder)或拖拽构建工具(drag &amp; drop building tool)都有可能源自 CSS 的简单性。iOS 和 Android 的世界里甚至根本没有主题构建器这一概念,因为该工具的输出必须是一个完整的 iOS 或 Android 应用,而一个完整应用并不是那么容易开发的。(不存在 iOS/Android 主题构建器,更多的是类似应用模版或应用启动器这样的东西)

还有一点:你知道浏览器的开发者工具有多棒吗?你可以很容易地调试应用的外观和体验,这又是 CSS 简单性的一个体现。iOS 和 Android 都没有类似 web 上的可视化开发者工具。

最后,说 CSS 很棒还有一个最重要的原因,那就是开发者使用一些简单的选择器和样式规则便能开发出一系列东西。网络上充斥着“10 个仅用 CSS 实现的精彩案例”这样的帖子证明了这一点,在这里也我要放上几个我最喜欢的例子。

以下为精彩案例,点击图片可查看源码:

那 CSS 就没有坑吗?当然有。盒模型就有点怪异,而 flexbox 又不是那么容易上手,另外诸如 CSS 变量这样的特性要再早几年出来就更好了。

每种样式系统都有其不足之处,但是 CSS 的灵活、简单和功能强大让它经受住了时间的考验,也帮助 web 成为了目前非常强大的开发平台。面对 CSS 的攻讦者,我很乐意捍卫 CSS,而且我也鼓励你这样做。

<b>原文发布时间为:2017年6月23日</b>

<b>本文来自云栖社区合作伙伴掘金,了解相关信息可以关注掘金网站。</b>

继续阅读