您可以通过编程语言如何 强类型或弱类型 来对其进行分类。此处,“类型”是指在编译时是否已知变量。例如,将整数 (1
) 添加到包含整数的字符串 ("1"
) 中。
result = 1 + "1";
包含整数的字符串可能是由于一系列复杂逻辑和大量移动部件意外生成的。它也可能是有意从单个真实来源生成的。
尽管“弱”和“强”这两个词的含义如此,但强类型编程语言并不一定比弱类型编程语言更好。在某些情况下,可能需要灵活性而不是严格性,反之亦然。与编程的许多方面一样,答案取决于多个外部上下文(即“视情况而定”)。
另一个有趣的部分是,强类型或弱类型没有正式的定义。这意味着,人们对强类型或弱类型语言的理解各不相同,并且可能随着时间的推移而发生变化。
TypeScript
JavaScript 被认为是一种弱类型语言,这种灵活性促成了其在网络上的早期采用。但是,随着网络的成熟和工业化,JavaScript 的用例变得更加复杂。
像 TypeScript 这样的扩展是为了解决这个问题而创建的。可以将其视为 JavaScript 的“插件”,它将强类型移植到该语言中。这有助于程序员处理复杂的设置。例如,用于电子商务的数据密集型单页应用程序。
TypeScript 目前在 Web 开发行业非常流行,许多新项目在首次设置时默认使用 TypeScript。
编译时间
编译时间 是编程语言转换为机器代码的时刻。它是 运行时 的前奏,运行时是计算机执行机器代码的时刻。
与网络上的许多事情一样,编译时间有点棘手。使用 TypeScript 的设置将把 JavaScript 代码的组件部分缝合在一起,并将其编译成单个 JavaScript 文件,供浏览器读取和运行。
组件部分编译的时间是它们全部组合在一起的时候。TypeScript 充当一种监督者,如果在组合发生之前您尝试违反为自己设置的类型约定,它会向您发出警告。

然后,缝合在一起的 JavaScript 文件由 浏览器获取,浏览器也有自己的编译时间。浏览器编译时间变化很大,具体取决于
- 浏览器所在的设备,
- 浏览器正在执行的其他工作,以及
- 设备的其他程序正在执行的其他工作。
浏览器不会直接使用 TypeScript,但可以感受到它的存在。 JavaScript 很脆弱。 TypeScript 通过尝试在代码编辑器中上游防止错误来帮助解决这种脆弱性。这降低了浏览器读取的 JavaScript 中出现错误的可能性——这些错误会导致 JavaScript 停止在用户使用的网站或 Web 应用程序上运行。
CSS
CSS 是一种声明式、特定于领域的编程语言。它也是强类型的。在大多数情况下,CSS 中的值保持声明为已编写。如果值无效,浏览器将丢弃整个属性。
CSS 中的类型
CSS 中的类型列表 很全面。它们是
文本类型
- 全局范围的关键字
initial
inherit
unset
revert
- 自定义标识符,专门用于特定事物,例如提供
grid-area
名称 - 字符串,例如
"hello"
- URL,例如
https://css-tricks.org.cn/
- 带破折号的标识符 (
--
),用于创建自定义属性(稍后会详细介绍)
数字类型
- 整数,即十进制数字 0-9
- 实数,例如
3.14
- 百分比,例如
25%
- 尺寸,在数字后附加单位的数字,例如 (
100px
或3s
) - 比率,例如
16/9
- flex,用于 CSS 网格计算的可变长度
数量类型
尺寸和长度可能看起来相似,但尺寸可以包含百分比,而长度则不能。
颜色类型
- 关键字
- 命名颜色,例如
papayawhip
transparent
currentColor
- 命名颜色,例如
- RGB 颜色
- 十六进制表示法,例如
#FF8764
- RGB/RGBa 表示法,例如
rgba(105, 221, 174, 0.5)
- 十六进制表示法,例如
- HSL/HSLA 颜色,例如
hsl(287, 76%, 50%)
- 系统颜色,例如
ButtonText
图像类型
- 图像,它是对图像文件或渐变的 URL 引用
color-stop-list
,两个或多个颜色停止点的列表,用于渐变符号linear-color-stop
,用于指示渐变颜色停止点的颜色和长度表达式linear-color-hint
,用于插值颜色的长度百分比ending-shape
,它使用circle
或ellipse
关键字之一,用于径向渐变
2D 定位类型
- 关键字
top
right
bottom
left
center
- 百分比长度,例如
25%
CSS 中的编程
CSS 中的大部分编程都是编写选择器,然后指定一系列属性及其所需的值。选择器集合会为内容提供视觉形式,就像 JavaScript 逻辑集合会创建功能一样。
CSS 有函数。它可以执行 计算、条件逻辑、算法表达式、状态 和 基于模式的行为。它还有 自定义属性,它们实际上是 CSS 变量,允许动态更新值。甚至可以用 CSS 解决 FizzBuzz 问题。
像其他编程语言一样,CSS 也有一层“元”层,包含关于如何 组织、管理和维护 的不同思路和技巧。
抛出错误
与其他编程语言不同的是,其他编程语言的代码很大程度上存在于后台,而 CSS 则高度可视化。如果您对属性声明使用无效值,您不会在控制台中看到警告或错误,但您会看到不符合您预期的视觉效果。
这是因为 CSS 很健壮。当由于结构错误的声明而导致视觉效果无法更新时,CSS 会优先考虑 **确保内容无论如何都能显示**,并尽可能地渲染所有其他有效的声明。这符合 语言的设计原则、平台的原则 以及 Web 任务的总体目标。
证明
让我们通过三个例子来演示 CSS 中的强类型如何保持护栏:一个使用简单的属性/值声明,一个使用计算,以及一个重新定义自定义属性的例子。
示例 1:简单的属性/值声明
查看 CodePen 中 Eric Bailey (@ericwbailey) 的 基本示例。
在这个例子中,浏览器不理解横幅的 border-style
“potato”声明。请注意,其他 .banner
类选择器属性/值声明被浏览器识别并渲染,即使 border-style
存在类型不匹配。这是一个关于 CSS 健壮性的例子。
border-style
声明需要以下文本样式类型之一:
- 全局范围关键字,或
- 自定义属性的虚线缩进。
如果我们将 border-style
更新为使用有效的类型值为 dotted
,浏览器将渲染边框!
示例 2:计算
CSS 中的 calc()
函数 允许我们使用两个参数和一个运算符来返回计算结果。如果其中一个参数没有使用有效类型,则计算将无法进行。
在这个 CodePen 中,p
选择器的 font-size
属性需要一个具有数值维度类型的的值(例如 1.5rem
)。但是,计算函数为 font-size
属性生成了一个无效类型值。这是因为 calc()
函数中的第二个参数是一个字符串 ("2rem"
),而不是一个数值维度类型。
因此,段落的字体大小将回退到下一个最适用的父节点——body
元素上声明的 font-size
为 1.5rem
。
这有点深入,但值得指出:在 calc()
函数中组合两个自定义属性可能会导致错误。虽然两个自定义属性本身可能是有效的,但 calc()
不会接受带破折号缩进的文本类型。假设我们可能尝试将包含不匹配单位的自定义属性相乘,例如 --big: 500px
和 --small: 1em
。
示例 3:重新定义自定义属性
与 JavaScript 变量类似,自定义属性值可以重新定义。这种灵活性允许进行一些操作,例如轻松创建深色模式颜色主题。
在这个 CodePen 的 :root
选择器中,我设置了一个名为 --color-cyan
的自定义属性,其值为 #953FE3
。然后,在 .square
类中,我将 --color-cyan
自定义属性的值更新为 top
。虽然 top
是一个有效的类型值,但它不是 background-color
接受的类型。
请注意,更新后的自定义属性的范围是 .square
,不会影响其他用法,例如短语“Don’t play to type”的右侧边框。如果您从 .square
中删除重新定义的自定义属性,您将看到青色背景颜色恢复。
虽然这有点牵强,但它可以作为一个例子,说明如果您不注意的话,重新定义自定义属性可能会失控。
这种现象可能发生在通信不良、CSS 代码库庞大以及使用 CSS 预处理器大规模构建自定义属性的项目中。
工具
事后看来,我认为 CSS 缺少控制台警告是一个缺陷,并且导致了人们对该语言的许多负面看法。
希望开发人员能注意到可能很小的视觉变化要求太高,并且不符合他们大多数其他日常工具的现状。我知道有一些尝试解决这个问题的举措。
第一个是 stylelint,一个专门用于处理 CSS 和类似 CSS 的预处理语言的 linter。stylelint 可以与代码编辑器、任务运行器、命令行工具和 GitHub 操作集成,帮助您控制 CSS。这使它能够满足开发人员已经在使用的工具。

第二个是 Firefox 在其 开发者工具 中提供的出色 CSS 检查选项套件。特别地,我想提请注意它识别未使用的 CSS 的功能。这对于识别可能出现类型不匹配的 选择器非常有用。

总结
CSS 自成为编程语言以来一直都是强类型的,作为一种编程语言,它已经存在很长时间了。它最近也经历了很大的成长。如果您还没有关注,有一些 新的惊人功能可用。
随着强类型 JavaScript 的流行,我希望它能帮助开发人员更快適应 CSS 坚定而灵活的方法。
感谢 Miriam Suzanne 提供的反馈。
很棒的文章!我真的很喜欢这种在教授 CSS 方面采取的务实方法。您将它视为一种真正的编程语言,而不是可以调整以使文本颜色不同的属性集。
除了 CSS 不是编程语言。您无法使用 CSS 创建程序。CSS 是一种数据语言(如 Json 或 YAML)。
这种看法既无聊又可预测。
它可能很无聊,但它是本文基础的一部分。
以下是 WWW 联盟官方网站的说法:“层叠样式表 (CSS) 是一种为 Web 文档添加样式(例如字体、颜色、间距)的简单机制。” https://www.w3.org/Style/CSS/Overview.en.html
这是一篇关于配置文件的文章
https://en.m.wikipedia.org/wiki/Configuration_file
CSS 仅仅是渲染引擎的一组配置文件。
这就是我的看法。
你可以认为它实际上就是这样的一个文件。
这是因为它以标记本身作为输入,并从属性中获取变量值。它实际上接收未设置样式的 html 并将其转换为一个非常好看的网页。
出于这个原因,在教我的学生时,我经常告诉他们,大括号内的内容可以被认为是 DIRECTIVES,而不是简单的无能为力的声明。就像在 JS 中调用函数一样(当然,这里浏览器通过加载页面来执行指令 - 请注意它的命令式含义 -,因此不一定是由该页面中发生的任何与人类相关的事件触发的,例如悬停、点击等等)。
我们实际上编写 CSS 代码是为了运行,而不仅仅是在代码编辑器中查看它。
这也许增加了 CSS 毕竟是一种编程语言的事实。它不仅仅是像记事本文本一样呈现,其中的一些语法暗示了你可以在浏览器中打开第一个文件(显然我指的是 html 文件)时导航到另一个文件。它实际上也与某种运行时相关联,可以说是在浏览器决定流动(或重新流动)页面时。它具有级联的事实证明了这一点(浏览器从每个元素的外部向内部填充主体,即从父元素到子元素,因此在执行此操作时有一个严格的顺序,具有像其他任何语言一样有条件的逻辑 /if then /or else/。事实是,JS 或任何语言也以级联模式工作(这里没有新东西),因为你不能正确使用变量值,直到它被赋值。因此,在幕后也存在一个可靠的级联逻辑。
因此,CSS 不仅仅是呈现,就像蒙娜丽莎也不是仅仅呈现一样,因为需要一些画家在画布上混合颜色,你同意吗?因此存在一个转换(就像任何其他编程语言旨在为我们提供便利一样),而 CSS 在浏览器中运行的事实并不能降低它的重要性。顺便说一句,所有需要有人“帮助他们工作”(即在实际运行任何代码之前编译它们)的语言,在某种程度上都不是编程世界中的低等公民。
我可以说它是相反的。
@Eve 让我举个例子,
假设我们用 JavaScript 做了一个程序,并为配置保留了一个 json 文件(用于存储一些关键属性的值),调整这个 json 中的值可能会严重影响我们代码的输出,但这并不意味着 json 是一种编程语言。
在事情进行得太远之前,似乎有些人将图灵完备性与编程语言混为一谈。正如文章中所链接的,领域特定语言 (DSL) 是计算机科学中公认的一门学科。
CSS、JSON、JavaScript、HTML 等等,都是你提供给编译器的一组指令,以获得结果。这就是编程。创建程序只是编程语言可以实现的众多输出类型之一。
当你质疑 CSS 是否是编程语言时,你就是在违背整个计算机科学领域。除非你在该领域获得了博士学位,否则我不太可能听你的。
再说一次,这种看法很无聊,很平庸,我不想再花更多时间和精力去关注它。一个更好的问题是,你最近在 CSS 中做了什么来推动对话向前发展?
即使自定义属性也可以有类型
https://mdn.org.cn/en-US/docs/Web/CSS/@property
它很新,只在 Chromium 浏览器中得到支持。
通过为自定义属性设置类型,浏览器也将能够对诸如背景渐变之类的值进行动画处理。查看以下示例:https://webdev.ac.cn/at-property/
感谢你的帖子!值得注意的是,你也可以在 CSS 中完成某种类型转换。以下是一些示例
* Cassie Evans 将整数转换为字符串使用
counter-reset()
* Carter Li 展示了如何使用
calc()
和@property
将浮点数转换为整数.可能还有更多可能的转换,我不太确定——但我经常在我的 HTML/CSS 图表实验中使用它们(例如,为了在伪工具提示中显示值)](https://ffoodd.github.io/chaarts/pie-charts.html).
我非常同意你的总体观点(CSS 是一种真实的编程语言,它是有类型的等等),但我希望你不要使用“弱类型”和“强类型”这两个术语。它们可能会令人困惑,甚至误导人。
“弱类型”基本上有两个定义
1:一种语言,你可以对变量指向的位进行任何操作,而不管它们的类型。汇编语言就是一个很好的例子。你可以创建一个字符串,它不会关心你是否对它进行浮点运算(尽管你可能会得到奇怪的结果)。JavaScript 并非如此!在混合类型时,JavaScript 可能会自动转换它们,或者会给你一个错误。
2:一种语言,其中语言的类型可以在运行时动态设置。这意味着每次你将变量设置为某样东西时,它的类型都可以改变。变量仍然有类型,它们通常在运行时检查类型!如果你混合了类型,该语言可能会在某些情况下自动转换它,或者抛出错误。这就是 JavaScript 的工作方式。
更好、更清晰、更不易混淆和更少争议的术语是“动态类型”和“静态类型”。在这个术语中,JavaScript 是动态类型的,因为它是在运行时解析类型的。它们仍然有类型,它不会让你对变量做任何事情,而不管类型如何。然后,像 TypeScript 这样的东西是静态类型的,因为它的类型是在编译时解析的。
我认为根据这个定义,CSS 是静态类型的,但我没有资格评论 CSS 的复杂性。无论哪种方式,我认为使用定义明确的定义是件好事。每当有人使用“弱类型”这个术语时,我经常想知道他们使用的是哪个术语定义(虽然,我很确定你在上面提到的第二个定义中使用的是这个术语)。
强/弱类型与静态/动态类型是正交的。你的第一个定义是弱类型。你的第二个定义是动态类型。我认为 JavaScript 是动态的和弱类型的——它确实非常努力地将值转换为类型,但它仍然在执行隐式转换。C 是一个有趣的案例研究——它是静态类型的,而不是强类型的;至少在算术方面是如此。它会自动在浮点数和整数之间进行转换,这可能会导致新开发人员出现意外的舍入错误。
我承认强/弱类型没有明确定义,但动态类型是明确定义的。动态类型语言在运行时进行类型检查,而静态类型语言在编译时进行类型检查。