原文: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,它和傳統的 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!
- 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.
你根本就不需要擔心!其他人已經替你做好了這些!已經有許多非常實用的第三方庫了,它們擁有許多你所需要的 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.
Tachyons 的重點不只在於各種類的有用,還在於它背後的基礎設計理念——它的所有尺寸(sizing)、空間(spacing)相關的類(如 margin、padding、font-size)都是考慮了伸縮性的。
更準確的講,Tachyons 在尺寸和空間上使用的是“rem”單位,以此來使得他們可以基於應用根元素的字型大小伸縮。根元素預設字型大小是 16px,所以如果你不去動它的話,就意味著你會獲得“基於 4 的(four-based )”伸縮,所有的空間和尺寸都是 4 的倍數。
蘋果和谷歌畢竟是懂設計的,而他們在自己產品中使用的就是 “four-based” 伸縮!
“採用一致性的空間佔比對於佈局來說會更容易預測、更容易適配和佈置,進而提升可維護性。” -- Jina Anne, DesignBetter.Co
這一點很重要,因為它給出了關於設計和佈局的規則和平衡點。
Using scales also helps you avoid magic numbers. Those constant numbers that hang around in your CSS and make things "work".
採用這種伸縮層次還可以避免“魔術數(magic number)”問題。
檢視原文
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 後,功能的編寫、模板的構建以及樣式的設定都可以在一個檔案中就完成!正如前面我展示的那樣,這可以顯著地減少構建一個元件的耗時,且不影響產出的質量。
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 mineThis 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 庫——然後開始簡化你樣式的設定吧!