CSS 最佳实践和初学者建议
CSS/SCSS 最佳实践
欢迎回到另一篇样式帖子,这次我假设您对 CSS 或 SCSS 有所了解,并且能够构建一个网站,无论更漂亮或更丑陋,更好或更差,但最终能够完成工作。
如果您正在学习,并且能够构建结构和样式,那么这篇文章适合您。如果您熟悉 CSS 和/或 SCSS 开发,无论是在您的项目中还是在日常工作中,这篇文章都适合您。
如果您处于学习曲线的早期阶段,那么我建议您全面阅读,如果您没有掌握概念,请花点时间更好地理解以下帖子,然后再回来:
我将尝试一种“边做边学”的方法,以便您轻松掌握。让我们为代码创建一个用例。
用例演示
想象一下,我们在一家初创公司找到一份工作,我们需要为一个新的电子商务构建一个主题(基于 prestashop、magento、定制电子商务……这在这一点上根本不重要)。
我们必须得到以下两样东西之一:
- 我们可以检查或读取 CSS 属性和值(例如颜色、填充、边距、字体系列、字体大小等)的一系列设计。
- 与第 1 点相同,但附加在设计系统上,这是首选。
如果我们没有收到可以检查的设计(来自设计师,最好是网页设计师),这是公司或设计团队的不良做法,除了抱怨之外我们无能为力,但第一天抱怨我们的工作似乎有点适得其反,所以让我们继续假设我们有一个设计。
在这个设计中,我们将能够辨别出其中显示的 HTML 标签。如果我们让图形设计师负责这项工作,我们不能指望他在导出为开发格式(例如从草图导出为摘要)时能够正确设置 HTML 标签,所以我们需要这些 HTML 基础知识。
然后我们需要决定如何构建我们的结构,这是在添加颜色、字体、边框半径、框阴影等之前所需要的。
但是我从某处读到,构建小组件更有利于提高生产力和可维护性,这是真的吗?
是的,但你得先从头开始。最好先编写组件的所有结构(添加一些基本的 CSS 来正确定位和调整结构大小),然后再开始添加更多 CSS。
结构方法
您可以使用不同方法的音调来构建结构,但我们可以将其归结为 3 个类别:
- 弹性框布局。
- 网格布局。
- 仅使用媒体查询。
在响应式布局兴起之初,也就是 Foundation 和 Bootstrap 的早期版本出现的时候,许多框架和自定义网站都只使用了媒体查询,因为如今 Flex 和 Grid 的支持已经很差了。现在,我们会发现在现代框架中,Flex 和 Grid 或两者结合使用的情况越来越多。
框架
我们需要一个框架吗?
当然不是,我对此有些担心,让我们列出它的优点和缺点:
优点
- 提高生产力(因为如果不使用 FW,我们就需要从头开始构建我们需要的东西)。
- 详尽的文档。
- 社区支持(例如在 SO 上提问)
缺点
- 重量会更高,装载时间也会更长。
- 使用框架会增加大量我们绝对不需要的选择器、属性和浏览器默认覆盖(或者更糟糕的是,自我覆盖),而且我们迟早需要覆盖它们。
- 我们不是在学习 CSS 或 SCSS,也不是在学习使用这种“原样”框架的 JS,因为我们只是转到文档并使用它来实现我们需要的东西。
我可以把这个列表写得更长,但就目的而言,已经足够了。显然,为结构创建自己的 CSS 的利弊列表应该与这个列表相同,只是顺序颠倒了。
最近,我使用 flexbox 和 CSS 组件创建了一个框架(尚未发布),组件化后能够仅导入我们在项目中需要的部分,并且该结构(又称“网格系统”)只花了我几个小时就在我们的设计上动态构建了所有可能的结构,因此它不需要整个敏捷冲刺才能达到(至少作为高级人员)。
我建议您构建自己的,因为这样做您会学到很多东西,但让我们继续下一步,因为这毕竟是最佳实践帖子,所以我将添加我自己的代码作为示例,而不是来自框架的代码。
CSS/SCSS 最佳实践
我们最终到达了这样的境界:最佳实践可以将未来的“我”从过去的“我”中拯救出来。
最佳实践 - 第 1 章:浏览器默认设置
本章内容简短。主题是“了解 HTML 标签及其默认属性,让你的代码更优秀”。
让我们举个例子:
跨度文本{ 显示:块; 边距:1em 0; }
乍一看似乎不错,但我们只是把 a 变成 <span>
了一个默认 <p>
标签。这样我们就可以用 a <p>
标签代替 a 了 <span class="text">
,这样可以避免 a 标签的误用,避免执行时额外的渲染或重新渲染,以及 CSS 代码的冗余。而且,省去了这些无用的 CSS 声明,也更易于维护。
每个浏览器可能在 html 标签上呈现不同的默认属性和值,您有责任检查是否需要隐式定义具有某些值的某些属性或让其“保持原样”。
请记住,您可以使用供应商前缀来建立一些不会被其他浏览器呈现的属性值关系。
现在的问题是网站是否需要在每个浏览器中看起来都完全一样?答案是否定的!我们每个人都习惯使用一种浏览器,如果他们觉得某个浏览器不舒服,人们就会换用另一种。浏览器默认设置是导致 *全球超过 80% 的人使用 Chrome或更准确的统计网站上超过 70% 的人使用 Chrome 的原因之一,而 Safari 的使用率更高,这是不好的。这很糟糕,因为 Safari 是新的 IE,它们不遵循标准并且没有正确维护 Safari,导致某些属性出现故障、渲染不自然以及应用时出现错误。还要提到,覆盖所有浏览器默认设置会导致网页过热(大多是不必要的)。
*此统计数据可能与您公司客户的不同,因此请确保您使用分析来了解您的客户或潜在客户正在使用哪些浏览器和设备。最佳实践 - 第 2 章:范围
例如,在主页的设计上,我们会看到重复,就像所有 <p> 标签都具有几乎相同的属性和几乎相同的值,因此将这个公共标签隔离到 CSS 中是合乎逻辑的,如下所示:
p { 字体系列:“Roboto”,无衬线字体; 字体大小:18px; 字体粗细:400; 下边距:1em; 行高:16px; }
不是吗?
当然是,但是这个代码有好有坏,让我们看看为什么。
没关系,因为:
- 我们为标签设置基本样式。
- 我们不需要在 html 中添加样板,避免使用类或 id,从而提高生产力,同时避免记录另一个特定类的需要。
这是不行的,因为:
- 我们没有范围,因此我们需要在 ap 标签看起来不同的地方用新值覆盖此属性。
- 目前我们可能没有足够的信息来确保这适合我们项目中的大多数 <p> 标签。
- 如果将来的重新设计增加了一些 <p> 标签之间的差异,那么重新编码将会很困难。
- 我们用完全相同的值覆盖了浏览器的默认值
margin-bottom: 1em;
那么我们可以做些什么来修复这个“不合格”名单呢?
CSS版本:
div#main p { 字体系列:“Roboto”,无衬线字体; 字体大小:18px; 字体粗细:400; 行高:16px; }
SCSS 版本:
div#main { p { 字体系列:“Roboto”,无衬线字体; 字体大小:18px; 字体粗细:400; 行高:16px; } }
现在我们有了作用域;它只会在作为子级(<div id="main">
在本例中是主包装器或主页包装器)时应用此段落属性。 <div id="products-page">
例如,在产品页面上,我们必须有一个作为主包装器的子级,这样我们才能为电商或 Web 应用程序中的每个布局设置特定的样式。
如果 margin-bottom 与浏览器默认设置相同,我们也会避免使用它,这样可以避免不必要的重新渲染(因此更高效、快速、干净)。
现在,我们可以通过添加类来修改或覆盖此属性。
CSS 版本
div#main p { 字体系列:“Roboto”,无衬线字体; 字体大小:18px; 字体粗细:400; 行高:16px; } div#main p.大文本{ 字体系列:“Roboto”,无衬线字体; 字体大小:24px; 字体粗细:粗体; 行高:26px; }
SCSS 版本
div#main { p { 字体系列:“Roboto”,无衬线字体; 字体大小:18px; 字体粗细:400; 行高:16px; &.大文本{ 字体系列:“Roboto”,无衬线字体; 字体大小:24px; 字体粗细:粗体; 行高:26px; } } }
我们正在覆盖 font-size、font-weight 和 line-height 属性。最好定义一个通用标签,仅包含这些属性和值,这些属性和值对于同一作用域内的所有同类标签都是通用的,但我们也可以为此设置否定选择器。
CSS 版本
div#main p { 字体系列:“Roboto”,无衬线字体; } div#main p:not(.big-text) { 字体大小:18px; 字体粗细:400; 行高:16px; } div#main p.大文本{ 字体大小:24px; 字体粗细:粗体; 行高:26px; }
SCSS 版本
div#main { p { 字体系列:“Roboto”,无衬线字体; &:不(.大文本){ 字体大小:18px; 字体粗细:400; 行高:16px; } &.大文本{ 字体大小:24px; 字体粗细:粗体; 行高:26px; } } }
*只要我们深入研究属性,我们就能看到 SCSS 在可维护性和可读性方面的好处,不是吗?
现在,我们为 #main div 子标签 p 上的 font-family 属性设置了通用值,并根据特定类(或不存在特定类)更改了属性值。无需覆盖,易于阅读,执行高效,一切顺利,我们成功了!
最佳实践 - 第 3 章:类名
使用语义正确的语言作为类名。这意味着以下代码是垃圾:
div.div-1 { 背景:浅蓝色; } div.div-2 { 背景:黄花; }
您可能现在知道 div-1 的含义,但是当您在三四个月后回到这个项目来开发一个进化项目时,您需要检查每个项目才能知道在 div 中添加 class="div-1" 时到底发生了什么。
此外,这可能导致您创建一个新类来执行与 div-1 和 div-2 相同的操作,因为您不记得 div-1 和 div-2 声明,并且 IDE 的智能感知没有给您任何有关设置浅蓝色或金黄色背景颜色的提示。
这不需要进一步解释,请自行阅读以下清理后的代码:
.lightblue背景{ 背景:浅蓝色; } .goldenrod 背景 { 背景:黄花; }
这同样适用于抽象类名,如class="brown-sugar"
或class="pretty-text"
,如果几个月后你还能记得这些类的内容,那么恭喜你,但有些同事可能会说你的坏话(你不能因此责怪他们)。
最佳实践——第四章:包装器
不要无缘无故地包装一切。我多次看到类似的事情
<div class="header-wrapper"> <h1>主页 </h1> </div>
这里的问题是,你为什么要这么做?你只需在 h1 标签中添加一个类即可。如果你需要包装某些内容,因为布局类型(flex 或 grid)需要一些带有特定属性的包装器才能达到预期的设计,这没问题,但像生活方式这样的包装会在你的 HTML 结构中添加节点元素,这会使它变得更重,更难维护,甚至会引发页面速度警告(降低你的 SEO)。
最佳实践 - 第 5 章:重置
除非非常必要,否则不要使用它们
如果您不知道“重置”在 CSS 上下文中的含义,它是指将一个或多个元素的 N 个属性设置为 0 或“none”。例如:
* { 边距:0; 填充:0; }
这将避免使用浏览器默认值呈现项目(如果有),以便您可以为每个元素设置自己的边距和填充(在此示例中)。
它还可以用于重置框架给出的值(通常框架具有内置重置)。
如果您知道浏览器如何渲染(并重新渲染)CSS,那么您可以预料到这会造成开销。您说得对,这就是为什么我告诉您除非必要,否则不要使用它们,尤其是在您想要良好的页面速度性能的情况下。
我建议使用的唯一“重置”是:
* { 盒子尺寸:边框; }
这将阻止浏览器计算不同对象与其他对象不同的大小,这很有帮助,有时也是需要的。
作为更好的做法,您可以box-sizing: border-box;
仅添加到相关元素,或者在不同的浏览器上测试时看到元素上的异常行为时使用它。
最佳实践——第六章:选择器特异性
避免额外的选择器
如果你已经读过我的博文《CSS 初学者及进阶指南》,你就会知道如何正确地覆盖属性(添加优先级)。所以,如果你默认添加了额外的优先级,以后覆盖这些属性就会很困难。
当然,更好的情况可能是一片绿地,不需要覆盖,但在现实世界中,事物会不断发展,覆盖的必要性就像沙漠中的水一样显现出来。事实上,如果你的项目不需要覆盖,那你为什么还要添加额外的特异性呢?
主体 > div#main > .container p.bold { 字体粗细:粗体; }
这些额外的选择器赋予了它独有的特异性,这对两件事都不利,一是上面解释过的(你必须添加更多特异性来覆盖它,这在目前来说有点困难),二是渲染。渲染会搜索一个,然后转到 CSSOM(CSS 对象模型)上的下一个,所以最好的解决方案是:
。大胆的 { 字体粗细:粗体; }
现在您甚至可以在 span 或 h 标签上使用它,而不仅仅是在 p 标签上。
最佳实践 - 第七章:连接类
是的!有些做法很简单,只需添加一些只应用一小部分样式的类,而不是在一个类上设置一堆东西。
<div class="d-flex justify-center align-items-center lightgray-background"> <p class="primary-color bold">你好,世界</p> </div>
看看这段代码解释起来有多简单,就像读一本书一样。你不觉得吗?
CSS 代码如下所示
.d-flex { 显示:flex; } .justify-center { justify-content: center; } .align-items-center { align-items:center; } .lightgray-background { 背景:lightgray; } .primary-color { 颜色:#4570DE; } .bold{ 字体粗细:粗体; }
对于所有参与该项目的人来说(包括参与该项目未来迭代的您自己),这都是毫无疑问的。
最佳实践 - 第 8 章:使用 SCSS
如果可能的话,当然可以。
为什么?
SCSS 的可读性更强,允许你创建混合宏、选择器树和 @use 语句来替代 @import,并且在转译成 CSS 时始终会被压缩/最小化(如果没有,请使用其他转译器/编译器 :D)。如果这还不够,一些打包器(例如 Parcel.js)会自动添加开箱即用的编译器,因此你无需自行搜索和配置编译器。此外,使用打包器通常会增加一项额外功能:如果你正确使用 SCSS @use 语句,并将所需内容分段到需要的位置,那么打包器编译器包就不会在你的视图中生成未使用的 CSS(这部分内容将在另一篇文章中详细说明,但现在你知道了它的存在,可以搜索一些相关信息)。
最佳实践 - 第 9 章:分而治之
第 7 章之后的另一个简单易行的规则。不要为了单一目的而输入大量样式,而是尝试以逻辑形式抽象它以供将来使用。
如果您即将编写 CSS 组件,您可能希望将其隔离,以便不依赖其他 CSS 规则来工作。
把可折叠元素想象成一个组件,把手风琴折叠面板想象成一组可折叠元素。现在,如果你要编写手风琴折叠面板的代码,别再自己动手了。直接编写一个可折叠元素就行了。这样,你就可以一个接一个地添加可折叠元素,然后“瞧!”你就得到了一个手风琴折叠面板。
您可以在此处看到独立可折叠/手风琴代码的示例,该代码既可以用作单个可折叠元素,也可以用作由 N 个可折叠元素构成的手风琴。
现在你必须把这段代码放在样式表的某个地方,但是放在哪里呢?如果你遵循第十章的规则(虽然不是必须的,但了解一下也没关系),这个问题就不会存在。但如果你有这个问题,答案是:这取决于你的环境。如果你使用 SCSS,并且只在每个视图中导入你需要的内容,那么答案显然是“在你的项目中添加一个新的 collapsible.scss 文件”,可以作为独立组件、部分组件或其他任何组件,具体取决于你的方法。
如果需要一些变量,例如品牌颜色,只需确保在此文件上添加所需的@use。
最佳实践 - 第 10 章:CSS 方法论
这是一个更广泛的问题,我在这里不做详细说明(我正在获取相关信息并对其进行构建,以便将其添加到初学者和非初学者完整 CSS 指南的新块中),但如果您处于学习曲线的高级阶段,并且想要立即了解更多信息,请查看以下概念:
范式/方法论 | 描述 |
海外合作与交流服务 |
OOCSS 代表面向对象的 CSS,因此在面向对象编程的背景下更容易理解。 专注于灵活、模块化、可替换的组件,专注于做好一件事。OOCSS 专注于单一职责原则、关注点分离以及面向对象编程的更多基础概念。 |
边界元法 | BEM 是 OOCSS 的一个具体应用。BEM 代表“块元素修饰符”,它描述了每个 CSS 对象类名的模式。本质上,每个 BEM 类都以一个块(即一个对象名)开头。我们先从 开始.example 。然后,对于该块的子元素,添加一个元素,并用两个下划线分隔:.example__name 。最后,您可以通过添加修饰符来修改任何类(块或元素),并用两个连字符分隔:.example--expanded 。 |
斯玛特-麦克斯 | SMACSS 是 CSS 的可扩展模块化架构 (Scalable and Modular Architecture for CSS) 的缩写。它是一本 CSS 编写书籍和方法论(由 Jonathan Snook 创作),但其最重要和最具影响力的方面是它的组织系统,该系统旨在提供一组用于组织 CSS 的存储桶。 |
由于 OOCSS 是一种抽象的编码方法,BEM 是 OOCSS 的具体应用,而 SMACSS 是一种以 OOCSS 为中心的组织结构,因此它们实际上可以很好地协同工作,特别是使用 Sass / SCSS。
脚注
还有很多最佳实践,有些人可能会反驳或不同意我写的某些内容。很久以前,我读过类似的帖子,然后尝试自己尝试一下,看看哪些更适合我,哪些建议只适用于具有特定规格的项目,或者哪些建议可以用于更现代的特定技术用法。
如果您知道我留下的一些建议,或者您想根据您的经验添加一些内容,请将其添加到评论部分,以便我们也可以从您的经验中学习。
如果您想了解更多关于在开发时将 Sass / SCSS 编译成 CSS 的信息,或者如何安装和开始使用捆绑器,您可以阅读本教程,它涵盖了您在现代公司可以找到的所有开发流程,简化且易于学习。
一如既往地感谢您的阅读,希望它能以某种方式对您有所帮助,我将感谢您通过反应和评论给予的支持。
此致,
乔尔
文章来源:https://dev.to/joelbonetr/css-and-scss-best-practices-3h6a