阅读 354

[译] 如何用函数式 CSS 简化样式工作

原文Simplify Styling with Functional CSS
作者Harry Nicholls 发表时间:October 18, 2018
译者:西楼听雨 发表时间: 2018/11/11 (转载请注明出处)

查看原文 Do you dread styling your apps? Fear that a change might break the styles you crafted through many hours of labour? I'm here to tell you that there's another way. Introducing functional CSS.

In this article I'll explain what functional CSS is, show you how it compares to traditional CSS, and demonstrate how you can simplify styling by using functional CSS!

I used to hate writing CSS. I couldn't make head nor tail of it. How do I structure my CSS file? When should I make a class? How do I vertically centre a div?!

These are just some of the questions that cropped up on a regular basis. I was afraid to make the slightest change to my styles, because it took soooo long to get them into a state I wanted! The whole thing just didn't make sense to me.

I found some relief when I discovered component libraries such as Angular Material, Ionic, and Bootstrap. I was able to focus on developing functionality, rather than worrying about layout, button styles, and aligning divs.

All was rosy for a time, but a feeling began creeping in. I began to find component libraries very restrictive. The developers of the library decide what your app should look like, and you have very little say in it after that.

Plus, the best component libraries end up being the most popular, which results in many apps having the same look and feel. Everything becomes generic.

Don't get me wrong, component libraries are great for building MVPs, because they take care of so much that doesn't really add to your product. But what happens when you've outgrown the MVP? Can you see yourself ripping out Bootstrap and replacing it with custom CSS?

NOPE.

Functional CSS sheds a whole new light on the styling problem: you want your app to look great, but you don't want to spend the next 3 weeks trying to centre a div (am I hung up on div centring?).

你是否害怕给你的应用设置样式?担心一个变动就可能把你经过许多个小时精心制作的样式破坏掉?我在这就是想要告诉你有其他方法解决这些问题。那就是:引入函数式 CSS(functional CSS)。

在这篇文章中,我将解释什么是函数式 CSS,它和传统的 CSS 又有什么区别,以及如何用其简化样式的设置!

我向来都讨厌写 CSS。我捉摸不定它:我该怎样组织我的 CSS 文件呢?什么时候我该使用 class?我要怎么做才能把一个 div 垂直居中。

这些问题都是日常出现的,它们只是所有问题的其中一部分。我不敢对我的样式做出一点轻微的调整,因为这会耗费我很长很长的时间来调整它们以期达到我的预期!所有这一切我都感觉对我没有什么意义。

不过在我了解了一些如 Angular Material、Ionic、Bootstrap 组件库后,我找到了一些宽慰——我可以将精力集中在功能性的开发上,而不需要担心布局、按钮样式、div 的对齐。

一切看起来都那么乐观,但一段时间后,一种新的感觉又开始产生了——我开始发现这些组件库局限太多了,这些库的开发人员决定了你的应用应该长什么样,而对此你没有什么发言权。

而且,因为最优秀的库最后都会变得最流行,导致的结果就是许多应用的样子都长的差不多,变得大众化。

不要误会我的意思,组件库是非常适合于构建 MVP 应用的,因为他们会考虑到许多你考虑不到的东西,但当你的 MVP 应用膨胀过大时会发生什么呢?你有没有发现,你会用把 Bootstrap 抽离出来进行自定义?

函数式 CSS 给这个样式问题带来了一片光明:你希望你的应用长的好看,但又不想耗费 3 周的时间来做“把一个 div 居中”这样的工作(我是不是对 div 居中这个太唠叨了?)。

那么到底什么是函数式 CSS 呢?

查看原文 The definition of "functional" is:

Of or having a special activity, purpose, or task; relating to the way in which something works or operates.

Functions should do one thing, and, given the same input, should produce the same output.

Every.

Single.

Time.

With CSS, your classes should apply one visual effect (e.g. no underline), and apply that every single time. So your CSS becomes made up of many small parts, that can be composed to give a specific visual effect.

To demonstrate functional CSS, I've built a Trello clone, Frello (original, I know…), and created one branch with traditional CSS styles and another branch with functional CSS styling.

(If you want to jump ahead, check out Frello, and get the source code here)

Here's a the card presentational component from the app, styled with both types of CSS. Take a look at the different CSS files and you'll quickly notice the difference:

所谓“函数式”,其含义为:

属于或者拥有某种特定活动、目的、或者任务;relating to the way in which something works or operates.

函数应该只专做一件事,且,在每一次给定相同的输入的情况下,应该产出相同的输出。

在 CSS 中就是指,你的 class 应该只产生一种视觉效果(例如,禁用下划线),并且每次需要的时候都应该单独应用一次。这样,你的 CSS 就会变为由许多小部分所组成,以便可以用来编织特定的整体视觉效果。

为了演示函数式 CSS,我构建了一个 Trello 副本—— Frello,并分别创建了一个传统 CSS 样式分支和函数式 CSS 样式分支。

(如果你想更一步了解,可以检出一份 Frello 代码,代源码地址在这

下面就是这个应用采用了这两种 CSS 类型的一个卡片组件展示。观察这两个不同 CSS 文件,你很快就会发现他们的不同:

演示地址:codesandbox.io/s/4jpvpk3l2…

查看原文 The first thing I want to point out is that the functional-styles file contains a lot more classes than the traditional-styles CSS file. And that probably seems overkill right now. Bear with me.

Say we now want to create a second component:

首先我想指出的是,functional-styles.css 文件相比 traditional-styles.css 文件里面包含了许多 class,初看起来有点不可思议,但请相信我接着往下看。

我们现在来创建另外一个组件:

演示地址:codesandbox.io/s/qry5zmyq6…

查看原文 You can see that the traditional CSS from both of these components has some duplication, but the functional CSS reuses some of the classes:
  • flex
  • items -center
  • dark-gray
  • helvetica
  • w5
  • ph2
  • bn
  • bg-transparent

That's not an exhaustive list. There's a lot of reuse going on here, and that's only with two components. Imagine how much reuse would be going on with a whole apps worth of components!

在这个例子中,你可以看到,传统的 CSS 开始出现了一些冗余,而函数式 CSS 对一些 class 有了一些复用,如:
  • flex
  • items-center
  • dark-gray
  • helvetica
  • w5
  • ph2
  • bn
  • bg-transparent

这个列表很长,就不一一举例了。这里发生了许多的复用,而且这还只是有两个组件的情况下。想象一下,如果这是在整个应用中的话,将可以进行多少的复用?!

Tachyons 框架

查看原文 You might be thinking, how do I write all of these functional css blocks?! How do I know which ones I need???

The great news is, YOU DON'T HAVE TO! Someone else has done it for you! There are a handful of libraries that contain most of the classes you'll ever need. Yeah, sure, they're not exhaustive, they don't cover every possible style that you might want to apply, but the large majority of useful effects are there.

Tachyons is one such library. I've used it in a few projects, and found it to be incredibly useful.

To demonstrate how effective Tachyons is at speeding up your workflow, I timed how long I spent working on each aspect of the Frello app:

  • Functionality
  • Styling:
    • Traditional CSS
    • Functional CSS using Tachyons

Here are the results:

  • Functionality -  3h 10m
  • Traditional CSS -  3h 44m
  • Functional CSS using Tachyon -  1h 59m

By far, traditional CSS took the longest time to do. It even took more time than building the functionality of the app! Maybe this says more about my ability to write plain CSS than anything else, but it's clear that styling Frello with functional CSS was a much quicker process.

I spent almost twice as much time writing traditional CSS compared to adding Tachyons classes to components. The glaring difference here is that I didn't actually have to write much CSS when using Tachyons. If I'd written all the functional CSS classes from scratch, I expect it would've taken a lot longer.

你也许会想,我要怎么写这些函数式 CSS 样式?!我又如何知道我需要哪些函数式 CSS ???

你根本就不需要担心!其他人已经替你做好了这些!已经有许多非常实用的第三方库了,它们拥有许多你所需要的 class。当然,它们肯定不全面,不能覆盖所有你可能需要的样式,但是绝大部分有用的样式是已经有了的。

Tachyons 是如此一个库!我在好几个项目中都使用了它,并发现它确实是非常好用。

为了演示 Tachyons 在对我们的工作流速度方面的提升有多有效,我对开发 Frello 应用的各方面做了耗时测试,包括:

  • 功能性
  • 样式
    • 传统样式
    • 使用 Tachyons 的函数式 CSS

下面是他们的结果:

  • 功能性 - 3h 10m
  • 传统 CSS - 3h 44m
  • 使用基于 Tachyons 的函数式 CSS - 1h 59m

可以看到,目前,传统 CSS 这块的耗时是最长的,甚至超过了功能性开发的耗时!也许这跟我写纯 CSS 的能力有关,但这还是表明了使用函数式 CSS 来设置样式会快的多。

我花在编写传统 CSS 上的时间几乎是通过添加 Tachyons 的各种类来设置组件样式所耗时间的两倍。当使用 Tychyons 时,最大的不同就是我不需要编写许多实际的 CSS。如果所有函数式 CSS 我都自己从零开始来写,可以预想到,其所耗时间会很长。

为什么应该关注?

查看原文 So what I'm trying to advocate here is taking advantage of the work that others have done in building functional CSS libraries. They're built on solid foundations in design, people have spent many hours thinking about how these libraries should be built, and what the most useful classes will be.

And it's not just the classes that are useful, but the fundamental design principles behind Tachyons. All of Tachyons spacing and sizing classes (think margin, padding, and font-size) are based on scales.

To be precise, Tachyons use 'rem' for all sizes and spaces making them relative to your apps root font-size. The default root font-size is 16px, so if you don't change this you'll have a four-based scale, meaning all spaces and sizes are multiples of four.

Apple and Google use a four-based scale in their products, and they know a thing or two about design!

"Using a consistent spacing scale also promotes maintainability through ratios by making layouts more predictable and more likely to "fit" and align well." -- Jina Anne, DesignBetter.Co

This is important because it gives rhythm and balance to your design and layout.

所以,在此我想倡导的是:要善于利用其他人在构建函数式 CSS 库中已经积累的成果。这些 CSS 库构建在强健的设计基础之上,“这些库该如何建构“以及“最有用的类是那些”都是人们经过许多个小时思考的结果。

Tachyons 的重点不只在于各种类的有用,还在于它背后的基础设计理念——它的所有尺寸(sizing)、空间(spacing)相关的类(如 margin、padding、font-size)都是考虑了伸缩性的。

更准确的讲,Tachyons 在尺寸和空间上使用的是“rem”单位,以此来使得他们可以基于应用根元素的字体大小伸缩。根元素默认字体大小是 16px,所以如果你不去动它的话,就意味着你会获得“基于 4 的(four-based )”伸缩,所有的空间和尺寸都是 4 的倍数。

苹果和谷歌毕竟是懂设计的,而他们在自己产品中使用的就是 “four-based” 伸缩!

“采用一致性的空间占比对于布局来说会更容易预测、更容易适配和布置,进而提升可维护性。” -- Jina Anne, DesignBetter.Co

这一点很重要,因为它给出了关于设计和布局的规则和平衡点。

img

Using scales also helps you avoid magic numbers. Those constant numbers that hang around in your CSS and make things "work".

采用这种伸缩层次还可以避免“魔术数(magic number)”问题。

img

查看原文 Another key advantage of using a functional CSS is library is that it can speed up your development workflow by reducing tab-switching. This is particularly noticeable when using a framework such as React, where your templates are inside your JS files.

With functional CSS, you can write the functionality, build the template, and style your component in a single file! As I demonstrated above, this can significantly reduce the time you spend building a component, while maintaining high quality output.

另一个使用函数式 CSS 的重要优势是,第三方库可以减少标签的切换,进而提升你的开发流程速度。这种情况在使用 React 这类框架的时候特别明显,因为模板都在 JS 文件中。

借助函数式 CSS 后,功能的编写、模板的构建以及样式的设置都可以在一个文件中就完成!正如前面我展示的那样,这可以显著地减少构建一个组件的耗时,且不影响产出的质量。

Tachyons Schmachyons

查看原文 > "But functional CSS doesn't scale… If you need to update a button that's used all over your app, you'll have the change the class on every single instance of that button!" -- Developer friend of mine

This is a very valid concern. But I'd say to this, review the way you're building the app. If you have the same button throughout your app, then make it a component. Insert the component everywhere you need it, and when you want to update its styles, change the classes on the component!

There are a lot of classes in Tachyons, and it can be difficult to know which one you need to apply at first. And it can be difficult to know what the class even does.

What does "bn" do? Or is "fw7" for that matter?

Tachyons documentation is useful, but can be difficult to navigate, especially if you're trying to find out what a particular class does.

Luckily, there's a very useful tool, Tachyons TLDR, that can help you get to grips with many aspects of Tachyons, including the class names and the scale system. Personally, I found it very useful.

Another common complaint about functional CSS libraries is that they're very opinionated, and only offer you a limited selection of classes.

If you've struggled with this, I have good news! You can customize Tachyons, and generate a stylesheet based on your own config using tachyons-generator!

There are other functional CSS libraries available, some of which are highly customizable:

There are options available for you to get the functional CSS library that suits your needs.

“但其实函数式 CSS 并不是可伸缩的……假如你需要更新一个按钮,那么你需要把这个按钮的所有实例的 class 都改一遍!”——来自我的一个开发者朋友

这种顾虑是非常正常的,但我想说的是,请先回顾一下你构建一个应用的方式:如果在你的应用中分布着相同的按钮,那么把它制作成一个组件,在需要的地方将其插入,然后当你需要更新它的样式时,修改这个组件的 class 就可以了!

Tachyons 中有许多的 class,在使用前很难知道需要使用哪一个,也很难知道每一个 class 具体做的是什么,如 “bn” 是干什么用的?又或者“fw7”有什么作用?

虽然可以查阅 Tachyons 文档 ,但它比较难以使用,特别是在你想找出某个 class 是干什么的的时候。

幸运的是有一个非常有用的工具可用,Tachyons TLDR,它可以帮助我们理解关于 Tachyons 的许多方面,包括 class 的命名和它的伸缩层次体系。反正从我的角度来讲,我是认为它是非常有用的。

如果你对 Tachyons 的这种设计难以认同,没关系,你可以对 Tachyons 进行自定义,你可以通过使用 tachyons-generator 生成器来基于你自己的配置生成样式。

另外还有一些其他的函数式 CSS 库可用,其中一些还支持高度的定制:

以上总有一款满足你的需求。

接纳函数式 CSS

查看原文 So why do it yourself if you don't have to? Spend your energy building functionality in your apps, not writing CSS that's probably a near duplicate of another CSS class you wrote in some other project.

Save time in your workflow by reducing tab-switching, and apply solid design principles to your work without spending the next 4-years getting a degree in design.

Bring Tachyons with you, or any other functional CSS library for that matter, and simplify styling!

如果不需要,那干嘛还要自己动手呢!把精力放在应用的功能建设上,而不是编写那些可能会与其他项目中的 class 高度相近的重复的 CSS 类上。

减少标签的来回切换并采用稳固的设计原则,可以节省你工作流中的时间,也不用再另外花费一个“4年”来获得设计的能力的提升。

把 Tachyons 带上——或者其他任何相关的函数式 CSS 库——然后开始简化你样式的设置吧!

相关资源

关注下面的标签,发现更多相似文章
评论