捍卫者usb管理控制系统_捍卫效用优先CSS

捍卫者usb管理控制系统

by Sarah Dayan

通过莎拉·达扬

捍卫效用优先CSS (In Defense of Utility-First CSS)

“Favor composition over inheritance”.

“偏重于继承的偏爱”

This piece of wisdom from Design Patterns, one of the most influential software engineering books, is the foundation of utility-first CSS. It also shares many principles with functional programming: immutability, composability, predictability, and avoidance of side-effects. The goal behind all those fancy terms is to write code that’s easier to maintain and to scale.

这是最有影响力的软件工程书籍之一, Design Patterns的这一智慧,是实用程序优先CSS的基础。 它还与函数式编程共享许多原理:不变性,可组合性,可预测性和避免副作用。 所有这些花哨的术语背后的目标是编写易于维护和扩展的代码

Despite its growing popularity, utility-first CSS still hasn’t convinced everyone. While some praise it, others have been vividly critical about such a practice. I used to be in the latter group. I was a BEM fan, sold to an approach I adopted for its advantages and ended up rooting for it like we do for a sports team. I rejected utility-first because it implied that my beloved and familiar approach wasn’t good anymore.

尽管实用程序优先CSS越来越受欢迎,但它仍然不能说服所有人。 尽管有些人对此表示赞赏,但其他人却对这种做法持批评态度。 我曾经是后者 。 我曾经是BEM迷,后来被我采用的一种优势所取代,最终像我们为运动队所做的那样扎根。 我拒绝实用程序优先,因为它暗示我心爱的和熟悉的方法不再适用。

Since then, I’ve dived a lot deeper into the topic. I studied design patterns and functional programming. This allowed me to radically revise my judgment.

从那时起,我就对该主题进行更深入的研究。 我研究了设计模式和功能编程。 这使我从根本上修改了自己的判断

CSS Tricks and Adam Wathan have done a brilliant job at taking us on a journey from “regular” CSS to utility-first, and explaining the “why” behind it. Rather than paraphrasing, I’ll focus on the recurring criticism of utility-first and debunk common misconceptions.

CSS Tricks和Adam Wathan在带领我们进行从“常规” CSS到实用程序优先的旅程,并解释了其背后的“原因”方面做得非常出色。 我将重点放在对实用程序优先和错误的常见误解的反复批评上,而不是表述。

“还可以使用内联样式” (“Might as well use inline styles”)

People often compare utility-first CSS to applying CSS rules to HTML nodes through the style attribute. This way of styling is unanimously considered a bad practice, and we have since moved on to separate stylesheets and class abstractions.

人们通常将效用优先CSS与通过style属性将CSS规则应用于HTML节点进行比较。 这种样式方式被一致认为是一种不好的做法,此后,我们开始着手开发单独的样式表和类抽象。

Utility-first CSS is no different. All styles are defined and maintained separately. This allows code reuse, usage of pseudo-classes, pseudo-elements, pre-processors, and browser caching.

实用程序优先CSS也不例外 。 所有样式都是单独定义和维护的。 这允许代码重用,伪类的使用,伪元素,预处理器和浏览器缓存。

Yet, atomic CSS detractors hurriedly associate it to inline styles. Atomic classes are small, they often have only one rule, and they’re named in a functional way instead of being semantic.

但是,原子CSS批评者急忙将其与内联样式相关联。 原子类很小,它们通常只有一个规则,并且它们是以功能方式命名的,而不是语义上的

All that being said, just because it looks the same doesn’t mean it is the same. Understanding how both practices differ is key to grasping the benefits of utility-first.

只是因为它看起来相同并不意味着它相同的。 了解这两种做法之间的差异是掌握效用优先的关键。

Inline styles allow you to do anything you want. You don’t have to follow any pre-existing definition. You’re re-writing everything from the ground-up every time you style a new HTML node. Similar elements end up with duplicate code, which makes the page unnecessarily heavier. If you’re not careful, it’s easy to ignore pre-existing solutions and reinvent the wheel every time.

内联样式允许您做任何您想做的事情 。 您不必遵循任何预先定义。 每次为新HTML节点设置样式时,都需要重新编写所有内容。 相似的元素以重复的代码结尾,这使页面不必要地变重。 如果您不小心,很容易忽略现有的解决方案,并每次都重新发明轮子。

Stranger Things<;/h2>

Stranger Things is an American science fiction-horror web television...

;Game of Thrones

Game of Thrones is an American fantasy drama television...

Unnecessarily verbose, heavier file size, multiple sources of truth for a single design concept.

单个设计概念不必要的冗长,更大的文件大小,多个事实来源。

Three attempts at solving the same problem. This is easily induced by the absence of a single source of truth, and likely to cause visual inconsistencies.

解决相同问题的三种尝试。 由于没有单一的事实来源,很容易导致这种情况,并可能导致视觉上的不一致。

Utility classes expose a well-defined API that you can use to compose more complex components. You’re not re-writing styles; instead, you’re relying on classes that define styles and behaviors once and for all.

实用程序类提供了定义明确的API,您可以使用它们来组成更复杂的组件 。 您不是在重写样式。 相反,您依赖的是一劳永逸地定义样式和行为的类。

// HTML

Stranger Things

Stranger Things is an American science fiction-horror web television...

Game of Thrones

Game of Thrones is an American fantasy drama television...

// CSS
/* Font sizes */
.font-13 { font-size: 13px } .font-16 { font-size: 16px }...
/* Font styles */
.font-bold { font-weight: bold }.font-italic { font-style: italic }...
/* Font colors */
.font-purple { color: purple }...

Using a defined set of existing CSS rules, no matter how atomic, forces you to pick styles from a limited list. You’re not granted total freedom like you are with inline styles. You’re maintaining a consistent catalog of allowed styles, and using them to compose larger components.

使用已定义的一组现有CSS规则,无论原子性如何,都会迫使您从有限的列表中选择样式。 您无法像内联样式一样被授予完全自由。 您要维护允许样式的一致目录,并使用它们来组成更大的组件。

This approach enforces consistency by limiting the ways you can style elements. Instead of having access to 16+ million colors, you only have access the number of colors defined in your theme.

这种方法通过限制样式元素的方式来增强一致性。 您只能访问主题中定义的颜色数量,而不必访问16+百万种颜色。

It also provides a single source of truth. Instead of re-declaring the same color for each element that uses it, you define it once in a class and use that class wherever you need it. In addition, using separate styling (with atomic classes or not) gives you access to pseudo-classes and pseudo-elements, pre-processors, caching… a whole load of benefits that aren’t available with inline styles.

它还提供了唯一的真理来源。 不必为使用它的每个元素重新声明相同的color ,而是在类中定义一次,然后在需要的地方使用该类。 此外,使用单独的样式(是否带有原子类)使您可以访问伪类和伪元素,预处理器,缓存……内联样式无法提供的全部好处。

You may argue that it doesn’t matter if atomic styles are limited: carelessly mixing them may result in inconsistent layouts like with inline styles. But that’s a human issue, not a technical one. You get the exact same problem with any approach, and any language for that matter, whether you’re able to scope or not. If you don’t follow the rules, style guides, and best practices that your team put in place, you’re the one to blame. Not the program, not the language, and not the architecture.

您可能会争辩说,原子样式是否受限制并不重要:粗心地混合原子样式可能会导致布局与内联样式不一致。 但这是人的问题,而不是技术的问题 。 无论采用何种方法,无论采用哪种方法,都将遇到完全相同的问题。 如果您不遵守团队制定的规则,样式指南和最佳实践,那您就应该对此负责。 不是程序,不是语言,也不是体系结构。

“它违反了关注点分离” (“It violates separation of concerns”)

One of the biggest arguments against functional CSS is that it goes against separation of concerns. That CSS should strictly be in charge of the styling, and HTML should semantically structure the page. That by using atomic classes and composing components in the HTML, you’re somewhat delegating styling to the HTML instead of doing it in CSS.

反对功能CSS的最大论据之一是,它反对关注点分离。 CSS应该严格负责样式,HTML应该在语义上构造页面。 通过使用原子类和在HTML中组成组件,您可以将样式委托给HTML,而不是在CSS中进行。

This is an extreme, and ultimately warped, vision of what “separation of concerns” means.

对于“关注分离”意味着什么,这是一种极端的,最终是扭曲的愿景。

A few years ago, I was on a job interview with a front-end developer who told me about his sheer disdain for Bootstrap. According to him, using extra markup to create a grid was a heresy: that’s a job for CSS, and CSS only. HTML should be 100% oblivious to how it’s rendered.

几年前,我正在接受一个前端开发人员的工作面试,他告诉我他对Bootstrap的轻蔑。 根据他的说法,使用额外的标记来创建网格是一个异端:这是CSS和CSS的工作。 HTML应该100%忽略其呈现方式。

The problem with that kind of thinking is that it’s deeply impractical. It raises design principles to a dogmatic level, ignoring concrete use-cases and context. It pushes you to be more concerned about checking all the “good practice” checkboxes than solving actual problems.

这种想法的问题在于它是非常不切实际的 。 它将设计原则提高到教条式的水平,而忽略了具体的用例和上下文。 它促使您比解决实际问题更关心检查所有“良好实践”复选框。

Adam Wathan explains it well (see: “Separation of concerns” is a straw man): when it comes to HTML and CSS, you can’t look at it from a strict “separation of concerns” perspective. It’s a “which depends on which” relationship.

Adam Wathan对此进行了很好的解释(请参阅:“关注点分离”是个草率的人) :当涉及HTML和CSS时,您不能从严格的“关注点分离”的角度看待它。 这是“取决于哪个”关系

Make no mistake: just because style composition is performed in the HTML document doesn’t mean it’s done in HTML. We’re not using style or align attributes on HTML nodes. We’re assembling pieces that we defined in a proper stylesheet, in CSS. Our HTML becomes a consumer of our CSS “API.” As Vue.js explains it in their documentation, separation of concerns doesn’t equal separation of file types. Your styles can be composed on HTML nodes, it’s still a CSS job.

没错:仅在HTML 文档中执行样式构成并不意味着它在HTML中完成。 我们不在HTML节点上使用样式对齐属性。 我们正在用CSS组装在适当的样式表中定义的片段。 HTML成为CSS“ API”的使用者 。 正如Vue.js在其文档中所解释的那样,关注点的分离并不等于文件类型的分离。 您的样式可以在HTML节点上组成, 但这仍然是CSS工作

“它使HTML膨胀” (“It bloats the HTML”)

When people mention code bloat, they usually mean one of two things (or both): code that’s hard to read, and a heavier codebase.

当人们提到代码膨胀时,它们通常是指以下两件事之一(或两者兼而有之): 难以阅读代码较重的代码库

The complexity of your layout has to exist somewhere. A component-first approach doesn’t remove “bloat,” it only deports it to the stylesheet. Even so, because your larger components reuse the same atomic styles as others, you inevitably end up with duplicate code.

布局的复杂性必须存在于某处 。 组件优先的方法不会消除“膨胀”,而只是驱逐到样式表。 即便如此,由于较大的组件会重复使用与其他组件相同的原子样式,因此不可避免地会产生重复的代码

$green: #74b759;
.component {  &-title {    color: $green;    font-weight: bold;  }}
.widget {  &-title {    color: $green;    font-style: italic;  }}
.footer {  &-links {   color: $green;   text-decoration: underline;  }}

Even with Sass, you get duplicate rules in the source code. @mixin can help, but you still get duplicates in the compiled CSS.

即使使用Sass,您在源代码中也会得到重复的规则。 @mixin可以提供帮助,但是您仍然可以在已编译CSS中获得重复项。

Now I know what you’re thinking. We got @extend. That’s an ideal use case for it, right?

现在我知道你在想什么。 我们得到了@extend 。 这是一个理想的用例,对吗?

Not so fast.

没那么快。

@extend may avoid ruleset duplication in the compiled CSS, but the mega comma-separated selector it will generate could end up being a lot heavier than if you had duplicated the rule. So much for avoiding bloat.

@extend可以避免规则集在已编译CSS中重复,但是它将生成的大型逗号分隔的选择器可能比复制规则时要重得多 。 避免膨胀非常重要。

You’re also concatenating unrelated classes and moving them all to the top, where the first @extend takes place. This can quickly result in specificity issues and odd overrides. Not to mention that you can’t @extend an outer class or placeholder from within a media query. So yeah, definitely not a silver bullet.

您还需要串联不相关的类,并将它们全部移到发生第一个@extend 的顶部 。 这会很快导致特异性问题和奇异的覆盖。 更不用说您不能从媒体查询中@extend外部类或占位符。 是的,绝对不是万能的。

From a file size standpoint, you shouldn’t worry about repeated class names in the HTML. That’s what Gzip is for. The deflate algorithm was specifically made to handle duplicate strings, so there’s no point in trimming away characters in your HTML. The resulting file size will make little to no difference whether you use a few or a lot of classes.

从文件大小的角度来看, 您不必担心HTML中重复的​​类名 。 那就是Gzip的目的。 deflate算法专门用于处理重复的字符串,因此修剪HTML中的字符毫无意义。 无论您使用的是几类还是很多类,生成的文件大小都几乎没有差别

On the other hand, the more a selector is repeated in a stylesheet, the more work your browser has to do to resolve all styles. If you have a single .title-green class for a given style, it simply matches all .title-green in the page. But if you have many classes doing the same thing (using @mixin) or similar selectors doing different things (using @extend), the more expensive it will be for the browser to match.

另一方面,样式表中重复选择器 的次数越多,浏览器解决所有样式所要做的工作就越多 。 如果给定样式只有一个.title-green类,则它仅与页面中的所有.title-green匹配。 但是,如果您有许多类在做相同的事情(使用@mixin )或类似的选择器在做不同的事情(使用@extend ),则匹配浏览器的代价将更高。

HTML “bloat” doesn’t matter, but CSS does. The network and engine don’t care how many classes you have in your HTML, but the way you write your CSS counts. If your decision-making process revolves around performances, make sure you focus your attention on the right things.

HTML的“膨胀”无关紧要, 而CSS的膨胀。 网络和引擎并不在乎HTML中有多少类,而是在乎CSS的编写方式。 如果您的决策过程围绕绩效而定,请确保将注意力集中在正确的事情上。

“ BEM就足够了” (“BEM is enough”)

OOCSS and all derived methods (SMACSS, BEM, etc.) drastically improved how we handle CSS. Utility-first CSS is an heir of this approach: it, too, defines reusable objects.

OOCSS和所有派生方法(SMACSS,BEM等)极大地改善了我们处理CSS的方式。 实用程序优先CSS是这种方法的继承者:它也定义了可重用的对象

The problem with BEM is that it focuses on building components first. Instead of looking for the smallest, unsplittable patterns, you’re building blocks and their child elements. BEM does an excellent job at namespacing and preventing style leaks, but its component-first nature inevitably leads to premature abstraction. You make a component for a certain use-case and end up never reusing it (a navbar component, for example).

BEM的问题在于它首先关注于构建组件。 您不是在寻找最小的,不可分割的模式,而是在构建模块及其子元素 。 BEM在命名间隔和防止样式泄漏方面做得非常出色,但是其组件优先的特性不可避免地导致过早的抽象 。 您为某个用例创建了一个组件,并且最终永远都不会重复使用它(例如,导航栏组件)。

BEM encourages you to use modifiers to handle component variations. This may seem smart at first, but unfortunately leads up to other problems. You end up creating tons of modifiers you only use once for a specific use-case. Worse: from one component to another, you might end up with similar modifiers, further breaking the DRY principle.

BEM鼓励您使用修饰符来处理组件变化。 乍一看这似乎很聪明,但是不幸的是导致了其他问题。 您最终会创建大量的修饰符,对于特定用例只能使用一次。 更糟糕的是:从一个组件到另一个组件,您可能最终会得到类似的修饰符,从而进一步打破了DRY原理。

.card {  background: white;  border: 1px solid grey;  text-align: justify;}
.card--left {  text-align: left;}
.card--right {  text-align: right;}
.tooltip {  background: black;  color: white;  text-align: center;}
/* Oops, looks like duplicate rules down there! */
.tooltip--left {  text-align: left;}
.tooltip--right {  text-align: right;}

At scale, components can become hard to change without breaking instances throughout a project. Premature abstraction keeps components from evolving and splitting into independent entities if they need to. Modifiers multiply as an attempt to fix it, resulting in non-reusable variations for unicorn use-cases, and undo band-aids when we realize our component does too much.

从规模上讲,在不破坏整个项目实例的情况下,组件很难更改。 过早的抽象可以防止组件演化和分裂成独立的实体(如果需要)。 修饰符会作为修复它的尝试而繁殖,从而导致独角兽用例的不可重用变化,并且当我们意识到我们的组件做得太多时,撤消创可贴。

BEM is a great attempt at fixing inherent CSS problems, but making it the core CSS approach of your project brings all the problems you meet when favoring inheritance over composition.

BEM是解决固有CSS问题的伟大尝试,但是使其成为项目的核心CSS方法会带来在继承优先于合成时遇到的所有问题。

“这是在CSS之上学习的另一种语言” (“It’s a whole other language to learn on top of CSS”)

This statement can be said of any naming system for any specific project, whatever methodology you pick. Your CSS class names ecosystem is a layer of abstraction on top of pure CSS. Whether you’re using semantic names like .card or functional ones like .bg, new contributors will need to familiarize themselves with what does what and when to use it.

对于任何特定项目的任何命名系统,无论您选择哪种方法,都可以说这一说法。 您CSS类名称生态系统是纯CSS之上的抽象层。 无论您使用的是诸如.card类的语义名称,还是诸如.bg类的功能性名称,新的贡献者都需要熟悉如何使用以及何时使用它。

You can’t escape having to use a naming interface between your HTML and CSS, unless you’re willing to describe your exact markup in CSS or write inline styles. Ultimately, functional class names are easier to understand because they describe the style. You know what they do without having to lookup the actual styles, while semantic names force you to either look at the rendering or browse code.

除非您愿意用CSS描述确切的标记或编写内联样式,否则就无法避免在HTML和CSS之间使用命名接口。 最终,函数类名称更易于理解,因为它们描述了样式。 您无需知道实际样式即可知道它们的作用,而语义名称则迫使您查看呈现或浏览代码。

“这是无法维持的” (“It’s unmaintainable”)

When people say utility-first CSS is unmaintainable, they often mention that when something changes in the design, you have to change it everywhere. You have buttons with regular corners and you decide to make them rounded, so you need to add the .rounded-corners utility class on every button in the code. Yet, the whole point of utility-first is that you start composing with utility classes, and then create components when you start identifying repetitive patterns.

当人们说实用程序优先CSS难以维护时,他们经常提到当设计中的某些内容发生变化时,您必须在任何地方进行更改。 您有带有规则角的按钮,并且决定对其进行圆角处理,因此需要在代码中的每个按钮上添加.rounded-corners实用工具类。 然而,实用程序-整点一个是你开始与实用工具类组成,然后创建组件当你开始确定重复模式。

A button is an ideal and most obvious candidate for being abstracted into its own component. You might not even need to go through the “utility-first, then component” phase for this case. When it comes to larger components, favoring composition first is the best choice for maintainability. Why? Because it’s safer to add or remove classes on a specific HTML node than to add or remove styles in a class that applies on many elements.

按钮是抽象成其自身组件的理想且最明显的候选者。 在这种情况下,您甚至不需要经过“实用程序优先,然后是组件”阶段。 当涉及到较大的部件时, 优先考虑成分是可维护性的最佳选择。 为什么? 因为在特定HTML节点上添加或删除类比在适用于许多元素的类中添加或删除样式更安全

Too many times have I been subjected to changing designs, and had to duplicate existing components to make them behave differently because I had no other choice. Even when a designer supplies all designs at the beginning of a project, and even if you do a great job at identifying components before you code, you can’t predict the future.

我经历了太多次更改设计的经历,并且不得不复制现有组件以使它们的行为有所不同,因为我别无选择。 即使设计师在项目开始时就提供了所有设计,即使您在编写代码之前在识别组件方面做得很出色, 也无法预测未来

Let’s say initial designs have white cards with an inset box shadow and a little ribbon in the corner.

假设最初的设计有白色卡片,卡片上有一个暗盒阴影,在角落处有一条小丝带。

// CSS
.card {  position: relative;  background: white;  padding: 22px;  border: 1px solid lightgrey;  text-align: justify;  border-radius: 5px;  box-shadow: 0 0 5px 0 rgba(0, 0, 0, .2);  overflow: hidden;}
.card::after {  position: absolute;  top: -11px;  right: 9px;  display: block;  width: 10px;  height: 50px;  background: red;  transform: rotateZ(-45deg);  content: '';}
// HTML
...

This solution is simple, semantic, and reusable. You handle everything in CSS and have minimal HTML to write. But suddenly you get new designs for new pages, and they use the card without the ribbon. Now you have to find a way to remove the ribbon for these new cards.

此解决方案简单,语义且可重用。 您可以处理CSS中的所有内容,并且编写HTML最少。 但是突然之间,您得到了用于新页面的新设计,并且他们使用不带功能区的卡片。 现在,您必须找到一种方法来删除这些新卡的功能区。

.card-no-ribbon::after {  display: none;}

Problem is, this class is undoing something that was previously designed. Having to add a class to remove a feature is an anti-pattern: it’s counter-intuitive and hard to maintain. When you decide to change how the base class behaves, you need to keep an eye on the undo modifier to make sure it still works.

问题是,此类正在撤销以前设计的内容。 必须添加类来删除功能是一种反模式: 它违反直觉并且难以维护 。 当您决定更改基类的行为时,需要注意undo修饰符以确保其仍然有效。

We now need to add another ribbon to the bottom left.

现在,我们需要在左下方添加另一个功能区。

.card::before,.card::after {  /* shared code */}
.card::before {  top: -11px;  right: 9px;}
.card::after {  bottom: -11px;  left: 9px;}

But now we need to update .card-no-ribbon!

但是现在我们需要更新.card-no-ribbon

.card-no-ribbon::before,.card-no-ribbon::after {  display: none;}

This, right here, is the fragile base class anti-pattern in action. Because your base class was abstracted too soon, is doing too much, and now needs to evolve, you can’t edit it without worrying about possible side-effects. If new people start contributing to the project, those risks multiply by ten.

就是正在起作用的脆弱的基类反模式 。 因为您的基类过早地被抽象,正在做太多的事情并且现在需要发展,所以您不能在不担心可能的副作用的情况下对其进行编辑。 如果新人开始为该项目做贡献,那么这些风险将增加十倍。

The only option you have left this stage is to do a refactor: have a nude .card as the base class, and add the ribbons with .card--top-ribbon and .card--bottom-ribbon modifiers. But now you have to edit all the existing .cards in your code that do need to have a ribbon.

您在此阶段剩下的唯一选择是进行重构:将裸.card作为基类,并使用.card--top-ribbon.card--bottom-ribbon修饰符添加.card--bottom-ribbon 。 但现在你必须编辑现有的所有.card在你的代码, 确实需要有一个色带。

Early refactors are a pretty good indicator of unmaintainability.

早期的重构是不可维护性的很好指示

You could argue that a smart developer could have seen it coming. That they should have made a naked .card base class and a .card--ribbon modifier, right from the start.

您可能会说一个聪明的开发人员可能已经看到了它的来临。 他们应该从一开始就制作一个裸露的.card基类和.card--ribbon修饰符。

That’s actually making a case in favor of utility-first and composition.

实际上,这为支持 Utility-first和composition提供了理由

You’re taking the decision to break down a given design element that you deemed too monolithic, so it’s easier to scale. That’s a good call. The more you go, the more you’ll realize this leads to utility-first.

您正在决定分解您认为过于单一的给定设计元素,因此更易于扩展。 真是个好电话。 您走得越多,您就越会意识到以实用程序为先。

You might think it doesn’t, and that your job is to foresee what is the bare minimum for a given component. But unless you own a crystal bowl, this is a risky assessment. This is also short-sighted. What if parts of your component need to be extended to other components? For example, what if you now need buttons with ribbons? If you duplicate the .card--ribbon class, your code isn’t DRY anymore, which makes it even more unmaintainable. So? Make a mixin and import it into both modifiers? Again, that’s extra work and “wet” code.

您可能会认为并非如此,而您的工作是预见给定组件的最低要求。 但是,除非您拥有水晶碗,否则这是一个冒险的评估。 这也是短视的。 如果组件的某些部分需要扩展到其他组件怎么办? 例如,如果您现在需要带有功能区的按钮怎么办? 如果您复制.card--ribbon类,则您的代码不再是DRY了,这使得它变得更加难以维护。 所以? 制作一个mixin并将其导入两个修改器中? 同样,这是额外的工作和“湿”代码。

The best solution for this use-case is to write a single utility class for the ribbon, and modifiers for sizes and colors if necessary. This allows you to have a single source of truth and use the ribbon anywhere you want to. If you need to put ribbons on avatars, panels, unordered lists, modals, you can do it without having to write a single extra line of CSS.

此用例的最佳解决方案是为功能区编写单个实用程序类,并在必要时编写尺寸和颜色的修饰符。 这样,您就可以拥有一个真实的来源,并且可以在任何需要的地方使用功能区。 如果您需要在头像,面板,无序列表,模态上放置功能区,则无需编写任何额外CSS行即可完成。

This is the definition of scalability and maintainability. All you have to do is reuse the available code you wrote proactively, instead of having to tweak existing code reactively.

这就是可伸缩性和可维护性的定义 。 您要做的就是重用您主动编写的可用代码,而不必被动地调整现有代码。

.ribbon {  position: relative;  overflow: hidden;}
.ribbon::after {  position: absolute;  display: block;  top: -11px;  right: 9px;  width: 10px;  height: 50px;  background: red;  transform: rotateZ(-45deg);  content: '';}

By breaking down designs into small elements, we write much more reusable code.

通过将设计分解为小元素,我们编写了更多可重用的代码。

Calling utility-first CSS “unmaintainable” is absolutely inaccurate. In fact, it may be the most maintainable and scalable CSS methodology to this day.

将实用程序优先CSS称为“不可维护”是绝对不正确的。 实际上, 它可能是迄今为止最易维护和可扩展CSS方法。

You can’t predict the future. This is why you should always favor composition over inheritance. A good sign of a healthy and scalable codebase is how things go when you need to change it.

您无法预测未来。 这就是为什么您应该始终偏重于继承而不是继承。 健康且可扩展的代码库的一个好兆头是,当您需要更改代码库时,一切将如何进行。

If a new change makes you anxious because you might break something, it’s a sign of poor design. But I would go a step further and say that if you need to write new CSS to make an existing component do something that another component already does, your code isn’t as scalable as you think it is.

如果新的更改使您担心,因为您可能会破坏某些东西,则表明设计不佳。 但是我要进一步说,如果您需要编写新CSS来使现有组件执行其他组件已经做过的事情,那么您的代码将无法像您想象的那样可伸缩。

If you need to reuse behavior that exists somewhere, you shouldn’t have to write new code. You should be able to trust and use what you already wrote and go from there. You have one source of truth on which you can rely, instead of two or more slight variations that you must not forget to keep up to date. This is the definition of maintainability.

如果您需要重用某处存在的行为, 则不必编写新代码 。 您应该能够信任和使用您已经写过的内容,然后从那里开始。 您有一个可以依靠的真理来源,而不是两个或更多个微小的变化,您一定不要忘记这些变化以保持最新。 这就是可维护性的定义。

“这很难看而且很难读” (“It’s ugly and hard to read”)

Do you remember the uproar when BEM started to become popular? I do. I remember many people who rejected the whole thing because of its syntax. Praising the model, but disgusted with the idea of chaining two underscores or two hyphens.

您还记得BEM开始流行时的骚动吗? 我做。 我记得许多人因为语法而拒绝了整个事情。 称赞该模型,但对链接两个下划线或两个连字符的想法感到厌恶。

As humans, it’s in our nature to be easily put off by what we’re not familiar with. Yet, letting subjective cosmetic considerations come in the way of a potentially useful technique is where developers should draw the line. Our job is to solve problems. Our main concern should be the end user.

作为人类,被我们不熟悉的事物轻易拖延是我们的本性。 但是,让主观化妆品考虑成为一种潜在有用的技术是开发人员应该划清界限的地方。 我们的工作是解决问题 。 我们主要关心的应该是最终用户

Look at the source code of many big projects: most of them have ended up adopting BEM. Chances are not all their front-end developers were sold at the beginning.

看一下许多大型项目的源代码:其中大多数最终都采用了BEM。 并非一开始就出售他们的所有前端开发人员。

Overcoming initial feelings, especially if driven by personal preference, isn’t that hard when you’re putting the success of a project first.

当您将项目的成功放在首位时 ,克服最初的感觉并不容易,尤其是在个人喜好驱动下。

Now on the topic of legibility, I get that long strings of classes can be “scary” when you open a file for the first time. This is not an insurmountable task though. More verbose code is a trade-off of composition, but it’s a much lesser inconvenience than unscalability.

现在,关于易读性的话题,我发现当您第一次打开文件时,长长的类字符串可能会“吓人”。 但是,这并不是一项不可克服的任务。 较冗长的代码是结构的折衷,但是与不可扩展性相比 ,它带来的不便要少得多

I don’t use shorthands like .pt-8 or .bb-lemon in my own code. I favor full-length class names like .padding-top-8 and .border-bottom-lemon, which are much easier to read. Autocomplete solves the problem of having to type long class names, and there are tools you can use to re-hash class names into smaller ones for production. I doubt this will make any significant change to your performances but hey, if it makes you feel good to shave bytes away, knock yourself out ?

我在自己的代码中不使用.pt-8.bb-lemon类的速记。 我喜欢全长类名,例如.padding-top-8.border-bottom-lemon ,它们更容易阅读。 自动完成解决了必须输入长类名的问题,并且可以使用一些工具将类名重新散列为较小的类名以进行生产。 我怀疑这会不会对您的演奏产生重大影响,但是,嘿,如果让您感觉好一点,那么就把自己淘汰吧?

Ultimately, the nature of functional class names might actually be more expressive. It’s easy for your brain to make a connection between such a class and what’s happening on screen. Even if you don’t get to see how it renders, you can get a pretty good idea of what .hidden or .opacity-6 are supposed to do.

最终,功能类名称的性质实际上可能更具表达性 。 您的大脑很容易在此类课程和屏幕上发生的事情之间建立联系。 即使你不明白,看看它是如何呈现,你可以得到什么心中有数.hidden.opacity-6所应该做的。

You know how they call a Quarter Pounder with Cheese in Paris?

Stylistically speaking, it’s pretty easy to know what’s going on here.

从风格上讲,很容易知道这里发生了什么。

Semantic class names don’t convey the same thing. It works for small components like buttons or alerts, which are common enough to be easily recognized. Yet, the bigger and the more complex a component gets, the less obvious it is to know what class name maps to what element on the screen, or what it looks like.

语义类名称不能传达相同的含义。 它适用于按钮或警报之类的小型组件,这些组件很常见,很容易识别。 但是,组件变得越大越复杂,那么就不知道什么类名映射到屏幕上的什么元素或它看起来像什么。

The Shining

His breath stopped in a gasp. An almost drowsy terror stole through his veins...

Stephen King

Stephen Edwin King (born September 21, 1947) is an American author of horror, supernatural fiction, suspense, science fiction, and fantasy...

Harder to know what class does what without going through the stylesheet.

不通过样式表就很难知道哪个类在做什么。

In that way, functional classes are a lot easier to understand than semantic class names. They demand less catching up time and less file-switching. Ultimately, they give you the very bit of information you’re looking for anyways.

这样,功能类比语义类名称更容易理解。 他们要求更少的追赶时间和更少的文件切换。 最终,它们为您提供了您一直在寻找的大量信息。

“这不是您编写CSS的方式” (“It’s not how you write CSS”)

CSS specificity is a feature, not a bug. Use it correctly, and it will give you amazing control.

CSS专用性是功能 ,而不是错误。 正确使用它,它将为您提供出色的控制。

That’s what CSS veterans say when yet another article about the dangers of specificity pops up. And technically they’re right: the CSS priority system isn’t an accident. It usually bothers people who don’t master CSS because of the lack of scope. But a language isn’t broken because it doesn’t behave like what you’re used to. Nested CSS rules are like !important: they’re handy, but have been so poorly used for years that we now see it as something to avoid.

那是CSS资深人士所说的,当时又出现了一篇关于特异性危险的文章。 从技术上讲, 它们是正确的 :CSS优先级系统并非偶然。 通常由于缺乏范围而困扰那些不精通CSS的人。 但是一种语言并没有被打破,因为它的行为不像您惯常的那样。 嵌套CSS规则就像!important :很方便:但是使用了很多年,以至于我们现在将其视为可以避免的东西。

Specificity should be used proactively, not reactively. They should be design decisions, not a quick fix when your styles don’t apply. Harry Roberts explains it well in CSS Guidelines:

应主动使用特异性,而不应被动使用。 它们应该是设计决策 ,而不是您的样式不适用时的快速解决方案。 Harry Roberts在CSS准则中对此进行了很好的解释:

“The problem with specificity isn’t necessarily that it’s high or low; it’s the fact it is so variant and that it cannot be opted out of: the only way to deal with it is to get progressively more specific”.
“特异性的问题并不一定是高还是低; 这是事实,它是如此的多样化,因此不能退出:处理它的唯一方法是逐步变得更加具体。”

Specificity is a powerful tool, but it needs to be used with uppermost caution and a good long-term vision of the project. Use them wrong, and you’ll feel the pain of having to go back. Keeping specificity low avoids problems altogether: it relies solely on source order, which is a lot easier to manage. With atomic CSS, if a style doesn’t apply, fixing it is as simple as adding or removing a class on an HTML node. You don’t have to call your stylesheet’s structure into question, which is a lot easier and safer to manage.

专门性是一个强大的工具,但在使用时要格外谨慎,并对项目有良好的长期愿景。 错误地使用它们,您将不得不回头。 保持低的特异性可以完全避免问题:它完全依赖于源代码顺序,这很容易管理 。 对于原子CSS,如果不应用样式,则对其进行修复就像在HTML节点上添加或删除类一样简单。 您不必质疑样式表的结构,这更容易管理,也更安全。

// CSS
.color-navy {  color: navy;}
.color-red {  color: red;}
// HTML

- Whose motorcycle is this?

- It's a chopper baby.

- Whose chopper is this?

- It's Zed's.

- Who's Zed?

- Zed's dead baby, Zed's dead.

Want the text to be navy? No need to touch the CSS. Simply remove the .color-red class from the encompassing iv>. If you need one of the children to be red, then move the .color-red on it.

希望文字是海军的? 无需触摸CSS。 只需从包含的 iv>中删除.color-red类。 如果您需要其中一个孩子是红色的,请在其上移动e the .cole the .col

“If a feature is sometimes dangerous, and there is a better option, then always use the better option.” — Douglas Crockford
“如果某个功能有时很危险,并且有更好的选择,那么请始终使用更好的选择。” —道格拉斯·克罗克福德

Using specificity or not isn’t about showing how well you master CSS and how you, unlike others, can keep it under control. It’s about understanding the advantages and flaws of the features at your disposal, and making choices in the best interest of the project.

是否使用特定性并不是要显示您对CSS的掌握程度,以及与其他人不同, 如何能够控制CSS。 它是要了解您可以使用的功能的优点和缺点 ,并根据项目的最大利益进行选择。

“您最终会得到大量未使用CSS” (“You end up with plenty of unused CSS”)

Let’s say you’re using Sass maps to generate your utility classes. Colors, font sizes, backgrounds, everything is automatically compiled into proper, ready-to-use CSS. Problem is, if you don’t use everything, you’re left with useless extra bytes in production. This can easily be fixed with UnCSS.

假设您正在使用Sass映射来生成实用程序类 。 颜色,字体大小,背景以及所有内容都将自动编译为适当的随时可用CSS。 问题是,如果您不使用所有内容,那么生产中将剩下无用的额外字节。 这可以通过UnCSS轻松解决。

UnCSS is great at dusting off your stylesheets, but it comes with two caveats: it only works on HTML files (so, no PHP and no template files) and it only takes into account the JavaScript that’s executed on page load (not classes added on user interactions, for example). If you’re using a language like PHP to render your pages, you can add a job in your deployment workflow that compiles pages into temporary HTML and runs UnCSS on them. For the second issue, you can use the ignore option to list out that are classes added on user interaction.

UnCSS擅长清理样式表,但有两个警告 :它仅适用于HTML文件(因此,没有PHP也没有模板文件),并且仅考虑了页面加载时执行JavaScript(未添加类)。例如用户互动)。 如果使用的是PHP之类的语言来呈现页面,则可以在部署工作流中添加一个作业,将页面编译为临时HTML并在其上运行UnCSS。 对于第二个问题,可以使用ignore选项列出在用户交互中添加的类。

Now it’s also important to ponder this issue. The cost of unused classes is heavier stylesheets (longer to download) and longer parse time. If you have a lot, and by that I mean a large percentage of your total styles, of unused classes, this can hurt performances. If you only have a few here and there, the impact will be negligible.

现在,考虑此问题也很重要。 未使用类的代价是样式表(下载时间更长)和解析时间更长。 如果您有很多东西,并且我的意思是说,您的总样式中有很大一部分是未使用的类,那么这可能会损害性能 。 如果到处只有几个, 那么影响可以忽略不计

Maintaining your CSS codebase is your job as a developer. No matter what methodology you choose, you have to keep an eye on the project and make sure to remove dead code when things change.

维护CSS代码库是您作为开发人员的工作。 无论选择哪种方法,都必须时刻关注项目,并确保在事情发生变化时删除无效代码。

Being careless with that is how you end up with plenty of unused classes, not because you’re generating some of them.

粗心大意就是最终会导致大量未使用的类,而不是因为您正在生成其中一些类

Need a text color class only for the main color? Make a class for this one only. Need backgrounds for most colors in the theme, yet unsure you’ll use them all right away? Generate the damn classes. They’ll be ready when you need them, you won’t have to maintain them when you add new colors, and the extra code will cost nothing. This is not where your app’s bottlenecks are. If you’re having performances issues, there are a million other things to consider before even looking into your CSS.

需要仅用于主色的文本颜色类吗? 仅为此一个课程。 需要主题中大多数颜色的背景,但是不确定是否可以立即使用它们吗? 生成该死的类。 当您需要它们时,它们将准备就绪,添加新颜色时无需维护它们,并且额外的代码将不花费任何费用。 这不是您应用程序的瓶颈所在 。 如果您遇到性能问题,那么甚至在研究CSS之前,还需要考虑一百万个其他因素。

“很难知道可以使用什么” (“It makes it hard to know what’s available to use”)

When your CSS codebase is a large collection of small utility classes, reading the source code won’t help you get a good overview of the available styles. But is it the role of the source code anyway?

当CSS代码库包含大量小型实用程序类时,阅读源代码将无法帮助您全面了解可用样式。 但这是源代码的作用吗?

It certainly isn’t. That’s what style guides are for.

当然不是。 这就是样式指南的用途。

Exploring source code is far from being enough to get a good understanding of how a full API is designed. This isn’t limited to atomic CSS: OOCSS or BEM projects, even small ones, can reach a level of sophistication which requires at least a README.

探索的源代码是远远不足以让一个完整的API是如何设计一个很好的理解。 这不仅限于原子CSS:OOCSS或BEM项目,即使是小型项目,也可以达到要求至少README的复杂程度。

Can you imagine having to crawl back in an unminifed version of the master Bootstrap stylesheet every time you don’t remember if this is .col-md-offset-6 or .col-offset-md-6? Would anyone new to Bootstrap understand what such a class means without a little literature on how the grid works? Documentation, style guides, and API references are designed to help us make sense of complex systems. Sure, it doesn’t mean documentation should justify poor design and unclear naming conventions, but thinking you should be able to understand an entire project only by reading the source code is pure fantasy.

您是否可以想象每次不记得是.col-md-offset-6还是.col-offset-md-6时,都必须在主Bootstrap样式表的未精简版本中进行爬网? 没有任何有关网格如何工作的文献,Bootstrap的任何新手都会了解此类的含义吗? 文档,样式指南和API参考旨在帮助我们理解复杂的系统。 当然,这并不意味着文档应该证明不良的设计和不清楚的命名约定,而是认为您仅通过阅读源代码就应该能够理解整个项目是纯粹的幻想。

There are plenty of tools out there to help you generate documentation right from your code. I use KSS for most of my projects, but CSS-Tricks shares a list of alternatives. Give it a try!

有很多工具可以帮助您直接从代码中生成文档。 我在大多数项目中都使用KSS ,但是CSS-Tricks共享了一系列替代方案 。 试试看!

“实用程序类应与组件一起使用” (“Utility classes should be used along with components”)

Yes. Absolutely. That’s precisely why it’s called utility-first and not utility-only.

是。 绝对。 这就是为什么它被称为Utility- first而不是Utility- only的原因

Utility-first isn’t about ditching components altogether. It means you should start off with utility classes, make the most of them, and only abstract when you see repeating patterns. You’re allowing your project to grow while remaining flexible, and identifying actual components over time, when patterns start to emerge.

效用优先不是要完全放弃组件。 这意味着您应该从实用程序类开始,充分利用它们,并且只有在看到重复的模式时才抽象。 您可以在保持灵活性的同时使项目不断发展,并在模式开始出现时确定随时间推移的实际组件。

It is crucial to understand that a component isn’t just a similar-looking “block” that you can reuse. It’s a pattern that is strongly tied to your specific project. Sure, you’re probably going to use tons of .btn and .modal, so it makes sense to abstract them early on. But are you positive you’re going to ever reuse .testimonial? Or at least reuse it enough to make it worth being a new component? Will it always look like this in every context, or is it specific to the homepage? Keep your options open. It’s a lot easier to later abstract a composite style into a component than to try and undo one.

至关重要的是要了解,组件不仅仅是 可以重用的外观相似的“块”。 这种模式与您的特定项目密切相关。 当然,您可能会使用大量的.btn.modal ,因此尽早对其进行抽象是有意义的。 但是您是否肯定会重复使用.testimonial ? 或者至少重用它足以令它值得成为一个新的组件? 它会在每种情况下始终看起来像这样,还是特定于首页? 保持选择不变。 以后将复合样式抽象到组件中要比尝试撤消一个样式容易得多。

“它使重新设计/主题化成为一场噩梦” (“It makes redesigning/theming a nightmare”)

Because atomic CSS is strongly tied to your design, this can make things more difficult when you have to do a redesign or develop an alternate theme. It’s far from impossible though, and there are a few things you can do to make your utility-first CSS more suited to these kinds of needs.

由于原子CSS与您的设计紧密相关,因此当您必须重新设计或开发替代主题时,这会使事情变得更加困难。 但是,这绝非不可能,并且您可以做一些事情来使实用程序优先CSS更适合这些需求。

You can start by keeping class names not too specific. Instead of .margin-bottom-8, you can use a more abstract name like .margin-bottom-xxs. This way you can change the value without making the names invalid.

您可以先保持类名不太具体。 除了.margin-bottom-8 ,您可以使用更抽象的名称,例如.margin-bottom-xxs 。 这样,您可以更改值而不会使名称无效。

Another approach would be to create aliases. Imagine you’re building an app that has light and dark mode: some colors would change, some others wouldn’t. We don’t want to make all our color utilities contextual: .background-primary and .background-secondary don’t tell us what color is behind the class. You don’t want an entire color system like that. Yet, you could still have color utilities with proper color names (.background-lime or .background-red), and generate aliases for those which might need to change for theming purposes.

另一种方法是创建别名 。 想象一下,您正在构建一个具有明暗模式的应用程序:某些颜色会改变,而其他颜色则不会。 我们不想让所有颜色实用程序都与上下文相关: .background-primary.background-secondary不会告诉我们类背后是什么颜色。 您不需要像这样的整个色彩系统。 但是,您仍然可以使用具有适当颜色名称( .background-lime.background-red )的颜色实用程序,并为可能需要更改主题名称的.background-lime生成别名。

// CSS
/* Backgrounds */
.background-lime {  background: #cdf2b0;}
.background-off-white, .background-light {  background: #ebefe8;}
.background-dark-grey, .background-dark {  background: #494a4f;}
/* Colors */
.color-lime {  color: #cdf2b0;}
.color-off-white, .color-light {  color: #ebefe8;}
.color-dark-grey, .color-dark {  color: #494a4f;}
// HTML

Ezekiel 25:17

The path of the righteous man is beset on all sides by the inequities of the selfish and the tyranny of evil men...

From here, all you have to do is write a JavaScript function that toggles all .*-light and .*-dark classes. And for elements that don’t need to change, you can use the original color classes.

从这里开始,您要做的就是编写一个JavaScript函数,该函数可以切换所有.*-light.*-dark类。 对于不需要更改的元素,可以使用原始颜色类。

This method works well, but if you have a lot of classes to switch it may end up hurting performances. DOM manipulations are expensive. You want to reduce them as much as possible if you can. Luckily, there’s a nifty technique involving CSS variables (thanks to Adam Wathan for coming up with it) which makes everything simpler.

此方法效果很好,但是如果要切换的类很多,则可能会损害性能。 DOM操作很昂贵。 您希望尽可能减少它们。 幸运的是,有一种精巧的技术涉及CSS变量(感谢Adam Wathan提出),这使一切变得更加简单。

// CSS
:root {  --green: #42f49b;  --off-white: #ebefe8;  --dark-grey: #494a4f;}
.theme-dark {  --background: var(--dark-grey);  --text: var(--off-white);}
.theme-light {  --background: var(--off-white);  --text: var(--dark-grey);}
.color-lime {  color: var(--green);}
.color-theme {  color: var(--text);}
.background-theme {  background: var(--background);}
// HTML

Ezekiel 25:17

The path of the righteous man is beset on all sides by the inequities of the selfish and the tyranny of evil men...

We defined colors with CSS variables and assigned different values for each context. Depending on the encompassing class, all colors will change thanks to ancestor inheritance. If you were to allow theme switching, all you’d have to do is change .theme-light into .theme-dark on the parent iv>, and all colors would adapt.

我们使用CSS变量定义了颜色,并为每个上下文分配了不同的值。 根据所包含的类, 所有颜色都将由于祖先的继承而改变 。 如果允许主题切换,则只需在父 iv>上将.theme-light更改为.theme-dark ,所有颜色就会适应。

This technique only works if you don’t have to support Internet Explorer and Edge below version 15. Otherwise, go for the first technique and use CSS ancestor inheritance system to avoid having to toggle too many variables. If you have to assign a text color to an entire block, set it on the parent instead of the children.

仅当您不必支持版本15以下的Internet Explorer和Edge时,此技术才有效。否则,请采用第一种技术,并使用CSS祖先继承系统来避免切换过多的变量。 如果您必须为整个块分配文本颜色,请在父级而不是子级上进行设置

/* Nope */

Ezekiel 25:17

The path of the righteous man is beset on all sides by the inequities of the selfish and the tyranny of evil men.

Blessed is he, who in the name of charity and good will, shepherds the weak through the valley of darkness, for he is truly his brother's keeper and the finder of lost children.

And I will strike down upon thee with great vengeance and furious anger those who would attempt to poison and destroy my brothers.

And you will know my name is the Lord when I lay my vengeance upon thee.

/* Yes */

Ezekiel 25:17

The path of the righteous man is beset on all sides by the inequities of the selfish and the tyranny of evil men.

Blessed is he, who in the name of charity and good will, shepherds the weak through the valley of darkness, for he is truly his brother's keeper and the finder of lost children.

And I will strike down upon thee with great vengeance and furious anger those who would attempt to poison and destroy my brothers.

And you will know my name is the Lord when I lay my vengeance upon thee.

在合理范围内拥抱变化 (Embracing change, within reason)

Having strong opinions is great. Not everything has to be settled by finding a middle ground. But there’s a clear line to draw between being opinionated and being reluctant to change.

有强烈的意见是很棒的。 并非必须通过找到中间立场来解决所有问题。 但是, 在自以为是不愿意改变之间有明确的界限。

We, as developers, must be the first to embrace change. Looking back at my first reaction towards utility-first CSS, I realize how important it is we keep an open mind instead of rushing to pick a side. It doesn’t matter how experienced we think we are. Experience is great, but it can also make us believe we already have all we need to make judgment calls and don’t need to dive deeper to understand new concepts.

作为开发人员,我们必须率先拥抱变化 。 回顾我对以实用程序为先CSS的第一React,我意识到我们保持开放态度而不是急于选择一方是多么重要。 我们认为我们有多么经验都没关系 。 经验是伟大的,但它也可以使我们相信,我们已经具备了做出判断电话所需的一切,而无需深入了解新概念。

Software development changes every day. Our industry is still young, and we’re figuring things out as we go. It doesn’t mean we should throw away the past, and continuously refactor all our projects to keep up with the latest trends. Past knowledge is the foundation of today’s discoveries. But just because something is tried and true, doesn’t mean it’s set in stone. It’s important we approach novelty with critical thinking.

软件开发每天都在变化 。 我们的行业还很年轻,我们正在寻找解决方案。 这并不意味着我们应该抛弃过去,并继续重构所有项目以跟上最新趋势。 过去的知识是当今发现的基础。 但是,仅仅因为某些事情是经过尝试并且是真实的,并不意味着它是一成不变的。 重要的是,我们要用批判性思维来对待新颖性。

We’ll probably move on from utility-first CSS at some point, like how we got past many things we used to consider the pinnacle of front-end development. In the meantime, let’s try to stay as open-minded as possible, and do what’s best for the industry, the projects, and the users.

在某些时候,我们可能会从实用程序优先CSS继续前进,例如我们如何摆脱过去曾被视为前端开发巅峰的许多东西。 同时,让我们尝试保持开放的态度,并为行业,项目和用户做最好的事情

Want to learn more about utility-first CSS and how to use it in your projects? Go read On the Growing Popularity of Atomic CSS on CSS Tricks and CSS Utility Classes and “Separation of Concerns” on Adam Wathan’s blog. You can also check out utility-first libraries on this curated list by CSS Tricks.

想更多地了解实用程序优先CSS以及如何在项目中使用它? 在Adam Wathan的博客上阅读关于CSS技巧和CSS实用工具类上原子CSS的日益流行的知识 和“关注的分离” 。 您还可以通过CSS Tricks在此精选列表中检出实用程序优先的库。

Originally published at frontstuff.io.

最初发布在frontstuff.io上 。

翻译自: https://www.freecodecamp.org/news/in-defense-of-utility-first-css-4f406acee6fb/

捍卫者usb管理控制系统

你可能感兴趣的:(编程语言,html,java,css,python)