我喜欢 Jonathan Snook 在 Twitter 上提出的这一点,我一直在不停地思考它,因为它描述了编写 CSS 时真正困难的事情
我觉得那条推文听起来要么很肤浅,要么很深刻,这取决于你的看法,但实际上,我认为没有任何系统、框架或库真正考虑过这一点——尤其是在可维护性的背景下。
— Snook (@snookca) 2019年2月26日
事实上,我认为这是在大型代码库中编写可维护 CSS 最困难的事情。 这是我日常工作中一个巨大的问题,我认为大多数 CSS 中的技术债务 最终都会归结为这一点。
例如,让我们假设我们正在为复选框设置样式——该复选框可能在页面上有一个位置、一些边距,以及可能的其他定位样式。 并且该复选框可能是绿色的,但当您单击它时会变成蓝色。
我认为我们可以将这两种类型的样式区分开来,即布局和外观。
但是,编写良好的 CSS 需要将这两种类型的样式分开。 这样,复选框样式就可以一次又一次地重复使用,而不必担心这些定位样式(如边距、填充或宽度)可能会反过来困扰您。
在 Gusto,我们使用 Bootstrap 的网格系统,这很棒,因为我们可以像这样编写 HTML,明确地将这些问题分开,如下所示
<div class="row">
<div class="col-6">
<!-- Checkbox goes here -->
</div>
<div class="col-6">
<!-- Another element can be placed here -->
</div>
</div>
否则,您可能会最终编写如下样式,如果将来在其他地方重复使用这些复选框样式,则会导致大量问题
.checkbox {
width: 40%;
margin-bottom: 60px;
/* Other checkbox styles */
}
当我看到这样的代码时,我的第一个想法是,“为什么宽度是 40%
——以及 40% 的什么?” 突然之间,我可以看到这个复选框类现在依赖于我不理解的其他一些代码。
因此,我开始将所有 CSS 视为适合这两个类别之一:外观和布局。 这一点很重要,因为我相信这两种类型的样式几乎不应该烘焙到一组样式或一个类中。 页面上的布局应该是一组样式,而外观(例如复选框的实际外观)应该在另一组样式中。 以及您是使用 HTML 还是单独的 CSS 类来实现这一点,尚有待商榷。
出现此问题的原因是,人们将不断尝试覆盖布局样式,而这正是我们最终得到一个类似于意大利面条怪物的代码库的原因。 我认为这种区别对于编写能够正确扩展的优秀 CSS 至关重要。 你怎么看? 在下面添加评论!
非常棒的观察。 我认为解决此问题的最简单(也是最好?)的方法是利用 CSS 内置的继承系统。 我的 CTA 按钮类告诉我的按钮如何显示,并且所有作为我的 #hero 部分子元素的 CTA 将具有 3rem 的右边距(例如)。 这样,您就可以将布局样式限定在按钮使用一次的位置,但按钮的外观样式可以在任何地方重复使用。
不过,我倾向于建议不要为此使用额外的 HTML。 特别是在当今的 CSS 网格和 flexbox 等技术中,我们可以清理我们的标记以使其保持超级简单和语义化。 Bootstrap 之类的东西最大的缺点之一是需要多少个容器。 我无法想象在所有 Bootstrap 容器之上使用额外的 HTML 进行布局样式。
CSS 的原生继承是天赐之物,我认为没有充分利用它。 可能来自整个“高特异性选择器很糟糕”的教条; 人们认为高特异性总体上是不好的,而没有理解它可以被用于坏处的方式。 分离外观和布局样式不是这些原因之一。
完全同意你的观点,特别是当你提到人们避免嵌套选择器仅仅是因为常识说这是一个坏主意时。 这也是我无法坚持使用 BEM 的原因之一。
我完全同意。 在我上一份工作中,我继承了一个经过 3 位不同设计师之手的代码库。 那真是乱七八糟。 CSS 文件中有一些已注释的部分,分别对应于上面提到的每个人,每个人都使用 !important 覆盖其他人的样式。 我最终放弃了整个东西并从头开始。
我认为 snook 的 smacss 书(这很难说!)可能是我见过的关于 css 最重要的著作。
关于你对宽度的具体说明,我喜欢 Nicole Sullivan 的一句名言:“永远不要在网格之外使用 ccss 宽度属性”。
在过去的一年中,我一直在思考这个问题。 不过,我当时称它们为布局和美学样式。
我在一个名为 Moose 的概念框架中记录了一些初步的想法。 它旨在涵盖前端的所有领域。 我很乐意听取任何关于它的意见。
https://oose.blueflag.codes/docs/moose/introduction
我再同意你不过了
您好,
一个好的方法是采用原子设计方法
http://atomicdesign.bradfrost.com/chapter-2/
我想这就是 BEM 有助于的地方,那个宽度为 40% 的复选框可以有一个名为“form__checkbox”的类,虽然不一定引用其父元素,但至少表明它旨在用于“form”块中。
我同意你的观点。
我不知道前端开发者如果没有这种“基本”知识该如何保持理智
但是 bootstrap? 该换换了,拥抱网格! :)
我同意! 这是一个我遇到的问题,然后感觉我在每个新项目中都解决了它。 我最大的代码膨胀问题。
我见过的最接近真正概述的解决方案的是 SMACSS 样式指南。 我建议任何感兴趣的人只需搜索 SMACSS 这个词即可。 它有一定的学习曲线,但它或多或少地解决了这个问题——在您能够做到的程度上。 不过,我必须承认,将其整合到每个项目中可能很困难,因为它有时会过犹不及。
样式可维护性方面最大的问题似乎集中在信息架构上——围绕样式的分类以及这些类别在特定 HTML 结构上组合时的交互方式。 不仅仅是元素需要样式,还必须了解为什么以及样式对于元素的功能是否至关重要,或者样式是否协调元素与另一个元素的关系。 这本身看起来会有所不同,具体取决于元素是组件的后代部分还是组件的根。 当然,这就是为什么许多 CSS in JS 方法让我感到厌烦的原因,在一个致力于发布 CSS 自定义属性、Shadow DOM 和命名部分的平台上,它似乎落后了十年。 不过,我们仍然需要某种 CSS 模块来实现此目的。
是的,我认为这一点至关重要。
我总是在 body 标签上添加一个用于不同布局的类名,然后定位该布局内的各个组件以添加其大小和位置属性。
我还创建了一些可用于特定布局的 section 元素,我甚至可以通过编写类似以下内容使其“与组件无关”
我喜欢这个!
我非常同意这一点。 我经常看到内联样式执行 row 和 col 本可以完成的事情。
我喜欢这种方法! 不过,它并没有解决在基于组件的方法中拆分 CSS 的问题。 从维护的角度来看,理想情况下,我希望单个文件组件包含样式。 这样,当组件被移除时,我不必去寻找应该与之一起移除的具有布局样式的祖先组件。
我还没有确定哪种更好,在以下位置定义布局
1. 最近的祖先
2. 单个布局文件
3. 每个布局一个布局文件
项目的规模可能决定了 2 和 3 之间的选择,但不确定 1 是否是最可预测的。
我认为 Harry Roberts 为此做了一个非常棒的类比。
我相信他说过类似这样的话
把你的组件看作是书籍。你可以把它们放在书架上,书架提供了一个强大而美观的结构来承载你的书籍。不要试图在没有书架的情况下摆放你的书籍,因为这最终会导致一堆大小不一的书籍不稳定地堆叠在一起,如果你试图从中取出或更改任何东西,它就会倒塌。
书架是用于布局的 CSS,书籍是你的组件。
说得好。我尽力做到这一点。读完之后,我会更加注意。谢谢 :)