好家伙,这些写 CSS 的新姿势你还不知道?

马丁路德 等级 633 0 0
标签: 前端

现在大部分搞前端的应该还是这样写 CSS 的:

.mock {  
    margin: auto;  
    font-size: 16px;  
    // ...  
}  
<div class='mock'>mock</div>  

以上代码就是举个例子,大部分情况应该都是写一个类,然后整一堆样式进去。

但是这种方式写多了以后,你应该会感受到一些痛点,比如说:

  • 取名困难,节点结构一多,取名真的是个难事。当然了,我们可以用一些规范或者选择器的方式去规避一些取名问题。

  • 需要用 JS 控制样式的时候又得多写一个类,尤其交互多的场景。

  • 组件复用大家都懂,但是样式复用少之又少,这样就造成了冗余代码变多。

  • 全局污染,这个其实现在挺多工具都能帮我们自动解决了。

  • 死代码问题。JS 我们通过 tree shaking 的方式去除用不到的代码减少文件体积,但是 CSS 该怎么去除?尤其当项目变大以后,无用 CSS 代码总会出现。

  • 样式表的插入顺序影响了 CSS 到底是如何生效的。

  • 等等,不一一说明了。其实对于笔者而言,第一二块在开发中是最难受的两个点,尤其是刚写前端,需要做活动 / 产品页的时候。

当下,社区里有一些 CSS 方案,能够解决以上一些痛点:

  • Atom CSS

  • CSS-in-JS

  • 上述两者的结合体

本文就来聊聊以上三种方案的优缺点以及各自方案的代表作。

Atom CSS

首先来聊聊啥叫做 Atom CSS:意思是一个类只干一件事,比如说:

.m-8 {  
    margin: 8px;  
}  

想象一下你按照这样的思想搞出一大堆类似的类名,就能整出一个践行 Atom CSS 方案的三方库了,tailwindcss 就是这个方案里的佼佼者。其实 Atom CSS 很多人应该早都用过了,栅格系统上就有它的身影,无非不清楚原来它就是 Atom CSS 罢了。

我们先来看看如果用 tailwindcss 的话,写好样式的 HTML 大概长啥样:

好家伙,这些写 CSS 的新姿势你还不知道?

上图是人家官网上的,在这之前还有一段挺炫的动画。看起来好像挺方便的,写上一堆类名就能出左边好看的样式了,省了很多写样式的时间,但是读者们可以来想想这种方式它会有啥好处及弊端?

在说优缺点之前,我们先来聊聊 Atom CSS 的历史。其实它并不是一个新兴产物,这玩意你往前推个十年就能看到它的讨论。正所谓天道好轮回,苍天饶过谁。Atom CSS 以前火过,而且是被喷火的,沉寂了几年之后这几年又被拿出来说了。

接下来我们以 tailwindcss 为例来聊聊 Atom CSS 方案的优劣点。

优劣点

如果你想在团队内部推广这个产品,学习成本会是一个问题,毕竟需要大家都看得懂你这坨东西到底是啥意思,这算一个很明显的缺陷。但是对于语法问题你还真的不用怎么担心,tailwindcss 是有语法补全的工具链的,Webstorm 已经内置了,VSCode 需要大家自行装个插件,所以喷写 tailwindcss 语法麻烦的可以歇一歇。

样式复用,就像写组件一样,这次我们是把样式一个个抽离了出来,这样带来的一大好处是减少了 CSS 代码文件体积。

原本传统的写法是定义一个类,然后写上需要的样式:

.class1 {  
    font-size: 18px;  
    margin: 10px;  
}  
.class2 {  
    font-size: 16px;  
    color: red;  
    margin: 10px;  
}  

这种写法是存在一部分样式重复的,换成 Atom CSS 就能减少一部分代码的冗余。

把 CSS 当成组件来写。大家乍一看 tailwindcss 官网肯定会觉得我在 HTML 里写个样式要敲那么多类是有病吧?

<figure class="md:flex bg-gray-100 rounded-xl p-8 md:p-0">  
  <img class="w-32 h-32 md:w-48 md:h-auto md:rounded-none rounded-full mx-auto" src="/sarah-dayan.jpg" alt="" width="384" height="512">  
  <div class="pt-6 md:p-8 text-center md:text-left space-y-4">  
    <blockquote>  
      <p class="text-lg font-semibold">  
        “Tailwind CSS is the only framework that I've seen scale  
        on large teams. It’s easy to customize, adapts to any design,  
        and the build size is tiny.”  
      </p>  
    </blockquote>  
    <figcaption class="font-medium">  
      <div class="text-cyan-600">  
        Sarah Dayan  
      </div>  
      <div class="text-gray-500">  
        Staff Engineer, Algolia  
      </div>  
    </figcaption>  
  </div>  
</figure>  

其实我们是可以利用 Atom CSS 一次只干一件事的特性,将这些类随意组装成我们想要的类,这样就可以提供出来一个更上层的通用样式来复用。

比如说项目中的按钮都是存在通用的圆角、内边距、字体等,这样我们就可以封装出这样一个类:

.btn {  
    @apply p-8 rounded-xl font-semibold  
}  

效率工具。tailwindcss 用的好肯定是能提高写布局的效率的,尤其对于需要做响应式的页面而言。当然这东西其实也算是甲之蜜糖乙之砒霜,评价两极分化很严重,有人认为提高了效率,也有人认为反而是增加了成本,或者说是脱裤子放屁。

提供了一整套规范化的设计模式,直接点说就是 tailwindcss 给你内置好一套优秀的设计主题了。但是这玩意对于规范的视觉团队来说是个不小的福音,不规范的话就可能是火葬场了。下面我给大家举个例子:

// tailwind.config.js  
const colors = require('tailwindcss/colors')  

module.exports = {  
  theme: {  
    screens: {  
      sm: '480px',  
      md: '768px',  
      lg: '976px',  
      xl: '1440px',  
    },  
    colors: {  
      gray: colors.coolGray,  
      blue: colors.lightBlue,  
      red: colors.rose,  
      pink: colors.fuchsia,  
    },  
    fontFamily: {  
      sans: ['Graphik', 'sans-serif'],  
      serif: ['Merriweather', 'serif'],  
    },  
    extend: {  
      spacing: {  
        '128': '32rem',  
        '144': '36rem',  
      },  
      borderRadius: {  
        '4xl': '2rem',  
      }  
    }  
  }  
}  

以上是 tailwindcss 的主题配置文件,大家可以按照视觉的要求来做调整。比如说今天视觉觉得屏幕的 lg 尺寸应该是 976px,过段时间又觉得需要改成 1000px。对于开发者而言我们只需要修改一行代码就能全局生效了,很舒服。

但是假如说视觉原本定义的边距规则如下:

// tailwind.config.js  
module.exports = {  
  theme: {  
    spacing: {  
      px: '1px',  
      0: '0',  
      0.5: '0.125rem',  
      1: '0.25rem',  
      1.5: '0.375rem',  
      2: '0.5rem',  
      2.5: '0.625rem',  
      3: '0.75rem',  
      3.5: '0.875rem',  
      4: '1rem',  
      5: '1.25rem',  
      6: '1.5rem',  
      7: '1.75rem',  
      8: '2rem',  
      // ...  
    },  
  }  
}  

现在需要我们把 6 换成 1.6rem,但是这个规则只需要作用在某些组件上,此时我们需要如何修改样式?新增一个 spacing 然后一个个去替换需要的地方么?

上述场景笔者认为还是不少见的,最起码在我们公司内部是存在这样的问题。已经定义了视觉规范并体现在内部的组件库上,但是在业务中还是有不少视觉会去动组件的基本样式,这里改个边距,那里改个颜色等等。原本组件库是为了帮助开发者提效的,但是在这种场景下开发者反而会抱怨改动样式极大提高了他们的成本,并且大部分情况下还不得不这样做。

再说回传统 CSS 的问题,其实 tailwindcss 也解决了一部分,但是仍旧存在没解决的点,比如说:

  • 死代码问题没解决

  • 样式表的插入顺序依旧有影响

以上说了那么多,其实对于我们使用 tailwindcss 而言,有利也有弊。它肯定是存在很好用的场景的,比如说写个人的产品页,或者说业务中样式变化不频繁的场景中,但是如果说需要业务中全量切换到 tailwindcss 的话,笔者肯定是持保留态度的。

对于 Atom CSS 来说,大家应该是不能否认它的优点的,但是我们是否有办法在尽可能避免它的缺点的情况下又获得它的优点呢?答案是有的,但是在讲答案之前我想先来聊聊 CSS-in-JS。

CSS-in-JS

CSS-in-JS(下文以 CIJ 缩写表示)核心就是在用 JS 写 CSS,这同样也是一个颇具争议的技术方案。

在这个领域下有两个库比较流行,分别为:styled-components(下文以 sc 缩写表示) 以及 Emotion。笔者目前已经用了一年多的 sc 了,来粗略谈谈它的优缺点。

我们先来了解下 sc 是怎么使用的。首先说下 sc 和 Emotion 的语法是趋于一致的,应该是为了 API 层面的统一吧,甚至前者还依赖了后者的一些包,以下是 sc 的常用写法:

`const Button = styled.a`  
  display: inline-block;  

  ${props => props.primary && css` background: white;  
    color: black;  
  `}  
`  
render(  
  <div>  
    <Button  
      href="https://github.com/styled-components/styled-components"  
      target="_blank"  
      rel="noopener"  
      primary  
    >  
      GitHub  
    </Button>  

    <Button as={Link} href="/docs">  
      Documentation  
    </Button>  
  </div>  
)  

用法我们不多展开,有兴趣的可以去官方看看,基本没有学习成本的,主要是一些样式组件上的使用。

另外 sc 并不是最终生成了内联样式,而是帮我们插入了 style 标签。

优劣点

笔者用了一年多的 sc,感觉这种方案对于 React 来说是很香的。并且解决了我很讨厌的传统写 CSS 的一些点,所以关于优劣点这段的讲述会有点主观。

首先 CSS-in-JS 这种方案不仅能让我们完整使用到 CSS 的功能,而且还扩充了一些用法。比如说选择器这块,在 sc 中我们能通过选择组件的方式来编写样式,如下代码:

`const Button = styled.a`  
  ${Icon} {  
    color: green;  
  }  
`  

另外既然我们通过 JS 来管理 CSS 了,那么我们就可以充分享受 JS 带来的工具链好处了。一旦项目中出现没有使用到的样式组件,那么 ESLint 就可以帮助我们找到那些死代码并清除,这个功能对于大型项目来说还是能减少一部分代码体积的。

除此之外,样式污染、取名问题、自动添加前缀这些问题也很好的解决了。

除了以上这些,再来聊两点不容易注意到的。

首先是动态切换主题。因为我们是通过 JS 来写 CSS 了,那么我们就可以动态地控制样式。如果你的项目有切换主题这种类似的大量动态 CSS 的需求,那么这个方案会是一个不错的选择。

还有个点是按需加载。因为我们是通过 JS 写的 CSS,现阶段打包基本都走的 code split,那么就可以实现 CSS 文件的按需加载,而不是传统方式的一次性全部加载进来(当然也是可以优化的,只是没那么方便)。

聊完了优点我们再来说说缺点。

第一个缺点很明显,有学习成本,当然笔者觉得这个学习曲线还是平缓的。

运行时成本,sc 本身就有文件体积,加上还需要动态生成 CSS,那么这其中必定有性能上的损耗。项目越大影响的也会越大,如果你的项目对于性能有很高的要求,那么需要谨慎考虑使用。另外因为 CSS 动态生成,所以不能像传统 CSS 一样缓存 CSS 文件了。

代码复用性和传统写 CSS 的方式没啥两样。

最后点是代码耦合问题。会有人觉得在大型项目中将 CSS 及 JS 写在一起会增加维护成本,并且也不符合 CSS 需要分离开来想法。

Atom CSS 加上 CSS-in-JS 的缝合怪

看了上文,如果你觉得两种方案都挺好的话,可以了解下 twin.macro,这个库(还有别的竞品)把这两种方案融合了起来。

`import 'twin.macro'  

const Input = () => <input tw="border hover:border-black" />  
const Input = tw.input`border hover:border-black`  

这种方案之上其实还有更好玩的方式,能帮助我们尽量取其精华而去其糟粕。

自动生成 Atom CSS 的 CSS-in-JS 方案

假如说我不仅想用 CSS-in-JS,还想把 Atom CSS 也给整上,但是又不想记 / 写一大堆类名,我这个想法能实现么?

答案是有的。利用运行时的方式把单个样式抽离出来,最后实现虽然我们写的是 CSS-in-JS,但是最终呈现的是 Atom CSS 的样子。

以 styletron 举个例子,开发时候的代码长这样:

import { styled } from "styletron-react";  

export default () => {  
  // Create a styled component by passing  
  // an element name and a style object  
  const Anchor = styled("a", {  
    fontSize: "20px",  
    color: "red"  
  });  
  return <Anchor href="/getting-started">Start!</Anchor>;  
};  

实际编译出来的时候长这样:

<html>  
  <head>  
    <style> .foo {  
        font-size: 20px;  
      }  
      .bar {  
        color: red;  
      } </style>  
  </head>  
  <body>  
    <a href="/getting-started" class="foo bar">Start!</a>  
  </body>  
</html>  

这样的方式就能很好地享受到两种方案带来的好处了。但是这类方案笔者找了些竞品,觉得还没有前两者方案来的流行,大家了解一下即可。另外这种方式带来的运行时成本应该会更大,也许可以配套打包工具在本地先做一次预编译(一个不成熟的想法,说错勿喷)?

总结

说了那么多方案,可能读者会有疑问,那么我到底该用啥?这里笔者说下自己的想法。

首先对于 sc 来说,笔者觉得很香,在项目中大范围用起来未尝不可,当然我们还可以搭配着 Atom CSS 一起来写通用样式。

对于 Atom CSS,笔者个人认为不适合项目中大规模使用,起码在我们公司内部不会是一个好方案,毕竟视觉真的会来动某些通用样式。

大家也可以来说说各自的看法。

本文转自 https://mp.weixin.qq.com/s/2J19KpvBjsM-Y4S1ylHsrg,如有侵权,请联系删除。

收藏
评论区

相关推荐

好家伙,这些写 CSS 的新姿势你还不知道?
现在大部分搞前端的应该还是这样写 CSS 的: .mock {     margin: auto;     fontsize: 16px;     // ... } <div class'mock'mock</div 以上代码就是举个例子,大部分情况应该都是写一个类,然后整一堆样式进去。 但是这种方式写多了以后,你应该
你可能不知道的10个CSS新功能(2021版)
多年来,CSS已经超越了背景颜色、边框、文本样式、边距和盒模型。现代CSS能够提供一系列的功能,而在过去,您需要JavaScript或变通方法来实现这些功能。 为了庆祝它在2021年取得的成就,在这篇文章中,我们想看看一些你可能不知道的令人惊叹的CSS新特性。我们将强调web设计人员和开发人员可以用现代CSS做的很酷的事情,讨论用例,浏览器支持,并给你一个
Fower: 一个可在 Vue 和 React 方便使用的 CSS in JS 库
一年多没写过文章了,今天给大家介绍一个我断断续续花了半年开发的 CSS 项目: . Fower 是什么?Fower 是一个让你高效开发 UI 的样式工具库,目标是让你写 CSS 不再痛苦。Fower 的核心特点是原子化(Atomic/utilityfirst)、类型安全(Type Safe)、CSS in JS,它非常注重开发体验,让你快速且开心的开发界面。
几个有点意思的 CSS 技巧
如果你是一名前端开发人员或者想成为一名开发人员,那么,我今天与你分享的9个CSS技巧,你需要知道一下。现在,我们开始吧。1、学习盒子模型你在学习 CSS 时,应该避免使用Bootstrap或TailwindCSS等框架,这些工具非常适合构建漂亮的网站,但如果你还不能正确的了解 CSS,则建议不要使用这些框架中的任何一个。因为如果你使用了这些工具,你将无法学习
2020 全球 CSS 报告,大家都在用什么样的技术?
本文来源与公众号「秋风的笔记」 介绍 -- CSS 从 1994 年 10 月首次被提出,到目前为止已经20余年,但是 CSS 早已发生了天翻地覆的变化,2020 的CSS  又是如何的呢? 我们现在可以使用 CSS Grid 轻松制作动态或响应式的布局,以更少的代码来进行自适应布局。CSS-in-JS 无需依赖全局样式表,我们可以将样式与组件写在一起
CSS 样式书写规范
编码设置 ---- 采用 `UTF-8` 编码,在 CSS 代码头部使用: @charset "utf-8"; > 注意,必须要定义在 CSS 文件所有字符的前面(包括编码注释),`@charset` 才会生效。 例如,下面的例子都会使得 `@charset` 失效: /* 字符编码 */ @charset "utf-8";
CSS3的基础知识学习(二)
**前言:** CSS主要是用来修饰标签的样式、使得网页更加美观,其实css的引用有三种方式,但主要是使用链接引用,意思就是我们写一个.css的文件,将样式修饰的控制代码写在这里面,这样控制起来方便快捷。对于CSS的学习,知识点中最重要的部分就是属性和选择器,其次还有页面布局和盒子模型,下面进行学习以及代码效果演示。 * * * 一、CSS的三种引入
CSS常用浮出层的写法
浮出层是web页面中经常用到的功能,带有小小尖角的浮出层则更为生动,所以今天带给大家的是有角的浮出层,一起看看吧! ![](http://static.oschina.net/uploads/img/201308/02140120_gpm9.png "poptip") 是的,我们即将实现的就是以上功能,是不是很生动? 贴上HTML: -------
CSS扩展语言
CSS没有变量?不要诬蔑我们大CSS好不?就像ES一样,你说JS没有模块,ES6给你整一个出来,而在这之前就已经有相关的库出来了。CSS也一样,你说CSS没有变量,CSS3就给你一个var(),变量你值得拥有! // 语法 // <custom-preperty-name> 自定义属性名 // <declaration-value>
Java web之JSP的CSS样式不起作用
在编写静态页面时,CSS解析没问题;换成jsp之后样式完全丢失。造成这个的原因是,CSS写的相对路, <link href="../css/notification.css" rel="stylesheet" type="text/css" /> 而这个相对路径是按照jsp文件的当前位置写的。但是,在转换成JSP之后,实际上是使用GET
SASS入门教程及用法指南
作为前端开发人员,你肯定对css很熟悉,但是你知道css可以自定义吗?大家都知道,js中可以自定义变量,css仅仅是一个标记语言,不是编程语言,因此不可以自定义变量,不可以引用等等。面对这些问题,我们现在来引进一个[SASS](https://www.oschina.net/action/GoToLink?url=http%3A%2F%2Fwww.haoro
HTML小游戏
开发工具:Visual Studio Code 游戏介绍:已知有3个方块,前面的2个方块涂有相近的两种颜色,你需要根据这两种颜色序列的递减情况猜测第三个方块的颜色是什么,并从下面的方块中选择你觉得最接近的颜色。 程序设计步骤: 1.编写html代码 2.编写js代码 html代码编写 设置css文件 import url('[https://fon
43个实例xHTML+CSS(DIV+CSS)网页及导航布局教程
在中国,很多前端开发初学者都会把xHTML+CSS页面制作说成DIV+CSS,甚至很多人都还不知道xHTML+CSS是什么意思,只知道盲目的追求DIV+CSS,但在国外,是没有DIV+CSS这个概念的,很明显如果单从字面上去理解,DIV+CSS的网页就要全都是div,很明显是无法达到语义化标准的。请把”DIV+CSS”这个词从脑子中删除,用”xHTML+CS
CSS兼容性(IE和Firefox)技巧大全
CSS对浏览器的兼容性有时让人很头疼,或许当你了解当中的技巧跟原理,就会觉得也不是难事,从网上收集了IE7,6与Fireofx的兼容性处理技巧并整理了一下。对于web2.0的过度,请尽量用xhtml格式写代码,而且DOCTYPE 影响 CSS 处理,作为W3C的标准,一定要加 DOCTYPE声明。 CSS技巧 1.div的垂直居中问题 verti
Sass用法指南
学过CSS的人都知道,它不是一种编程语言。 你可以用它开发网页样式,但是没法用它编程。也就是说,CSS基本上是设计师的工具,不是程序员的工具。在程序员眼里,CSS是一件很麻烦的东西。它没有变量,也没有条件语句,只是一行行单纯的描述,写起来相当费事。 很自然地,有人就开始为CSS加入编程元素,这被叫做"CSS预处理器"(css preproces