6

为啥CSS不会支持双斜杠(//)注释?

 1 year ago
source link: https://www.fly63.com/article/detial/12508
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

众所周知,css 仅支持多行注释,也就是/**/注释

/* 这是CSS注释 */
div{
  color: red;
}

习惯了 SCSS或者LESS这些预处理器的同学,肯定非常希望有双斜杠注释

// SCSS注释
div{
  color: red; // SCSS注释
}

很明显这种写法要比/**/简洁的多,那么,为啥官方迟迟不支持双斜杠注释呢?

下面就来探讨一下这个问题以及关于 CSS 语法的一些思考。

一、语法冲突

CSS 中大部分属性和值都比较简单,乍一看,好像没有什么语法有双斜杠//,其实不然,只是非常少,但并不是没有。

举个例子,下面是border-image的一些写法

/* source | slice */
border-image: linear-gradient(red, blue) 27;

/* source | slice | repeat */
border-image: url("/images/border.png") 27 space;

/* source | slice | width */
border-image: linear-gradient(red, blue) 27 / 35px;

/* source | slice | width | outset | repeat */
border-image: url("/images/border.png") 27 23 / 50px 30px / 1rem round space;

看到第 4 中语法没,出现了两个斜杠,关键是,两斜杠中间的width还可以省略,这一点从border-image的语法规范可以看出

border-image = 
  <'border-image-source'>                             ||
  <'border-image-slice'> [ / <'border-image-width'> | / <'border-image-width'>? / <'border-image-outset'> ]?  ||
  <'border-image-repeat'>   

看到<'border-image-width'>后面的问号没?这个就表示可选的意思,所以理论上border-image可以有以下的写法

border-image: 0//0;

这种写法其实等同于

border-image-source: none;
border-image-slice: 0;
border-image-width: 1;
border-image-outset: 0;
border-image-repeat: stretch;

我们可以打开控制台来验证一下这个语法的合法性

6486af68bc41e.jpg

可以看到,这种写法完全是有效的(暂不考虑实际功能)

所以,双斜杠语法可能会造成语法冲突

还有一个和border-image比较像的属性,叫做-webkit-mask-box-image,也可以实现双斜杠语法

-webkit-mask-box-image - CSS: Cascading Style Sheets | MDN (mozilla.org)
-webkit-mask-box-image: 0//0;

不过这种毕竟是小部分,如果有新规范,也很容易规避这个问题。更要命的其实是下面这个原因,如果要是支持了,可能会让以前的CSS规范全部崩塌!

二、无法兼容现版本

为啥说这个问题更大呢?我们可以换个角度来思考,如果现在CSS支持了双斜杠语法会怎么样?

举个例子:

<div>CSS COMMENT</div>

下面加了一行注释

div{
  font-size: 30px; // 字号
  background-color: yellow;
  color: blue;
}

如果浏览器支持这个特性,那非常符合直觉,那如果浏览器不支持(现阶段),你觉得最终的样式是?

A. 30px字号,黄色背景,蓝色文字
B. 30px字号,蓝色文字
C. 黄色背景,蓝色文字
D. 蓝色文字
E. 全部不生效,默认样式

思考两分钟...答案是 B,你猜对了吗?

为啥会这样呢?这要“归功”于 CSS 强大且精准的“容错”解析规则:

CSS 解析中并不存在换行规则,每个属性和对应值通过分号;区分,在选择器内部,如果碰到非法语句,则会依次寻找到下一个;为止,也可以通过{}进行分块区分。

上面这一段是我自己总结的一套规则,可能还是有些不好理解,拿上面那个例子来说,你可以把两行连起来看,实际上等同于

div{
  font-size: 30px; 
  // 字号 background-color: yellow;
  color: blue;
}

也就是// 字号 background-color当成了一个新的属性,但是这个属性无效,所以最终的表现就是30px字号,蓝色文字

这样就带来了一个非常严重的问题,在不支持注释的浏览器上产生了不符合预期的解析错误,也就是说,一般的不兼容语法只是不起作用,但是这种注释却影响到了其他样式,这才是最要不得的

三、注释的其他写法

再来看一些常见的注释写法,看看有什么副作用

<div>CSS COMMENT</div>

首先是最常见的注释

div{
  // font-size: 30px; 
  background-color: yellow;
  color: blue;
}

这种写法其实是符合预期的,在目前阶段也是可以正常解析,因为//会向后找到第一个;,也就是整行 // font-size: 30px; 无效

然后是这种注释

div{
  // 标题
  font-size: 30px; 
  background-color: yellow;
  color: blue;
}

根据前面的分析,其实可以等同于

div{
  // 标题 font-size: 30px; 
  background-color: yellow;
  color: blue;
}

所以第一行就无效了,结果和前面一致

如果需要不影响现有样式,可以在后面加上;,直接终止解析,如下

div{
  // 标题;
  font-size: 30px; 
  background-color: yellow;
  color: blue;
}

然后是选择器外面的写法

<div>CSS COMMENT</div>
<p>CSS COMMENT</p>
// 标题 
div{
  font-size: 30px; 
  background-color: yellow;
  color: blue;
}
p{
  color: red
}

这种会如何解析呢?

其实你可以将这个注释想象成一个选择器,也就是和下面的div连起来了

// 标题 div{
  font-size: 30px; 
  background-color: yellow;
  color: blue;
}
p{
  color: red
}

由于并不存在// 标题 div这样的选择器,并且也不是一个合法的选择器(斜杠需要转义),所以整个DIV样式完全无效,但并不影响后面选择器(p)的样式

6486af7d93d92.jpg

如果需要不影响现有样式,需要在后面加上{},告诉浏览器这是一个区块,如下

// 标题{}
div{
  font-size: 30px; 
  background-color: yellow;
  color: blue;
}
p{
  color: red
}

四、CSS 语法其实从未改变

CSS 发展这么多年,各种属性和新特性层出不穷,其实最核心的语法规则从未改变过,这也是设计之初就决定好的。

像之前出现的CSS变量

:root{
  --c: red;
}

本质上其实就是一个特殊的属性,即便旧浏览器不支持也不会有其他影响,就相当于不存在一样。

这也是为啥 CSS 为何不能像 SASS 那样直接将语法放在最外层,就像这样

--c: red;
div{
  color: var(--c)
}

如果按照 CSS 的解析规则,必然导致连同下面的 div样式整体失效

还有一些@符号的新语法,例如@property

@property --speed{
  syntax: '<number>';
  inherits: false;
  initial-value: 0;
}

其实从结构上来讲,和@font-face并没有什么区别

@font-face {
  font-family: "Trickster";
  src: xxx;
}

或者说也满足下面这种更通用格式

选择器 {
  属性1: 值;
  属性2: 值;
}

所以即使不支持,也不会影响其他 CSS 语句。再想想看,有什么新特性会让其他样式“挂掉”?

五、最后总结一下

这下大概能明白为啥不支持双斜杠语法了吧,以上就是关于CSS语法的一些思考了,相信大家对 CSS 的语法又有了一个新的认识,下面总结一下

  1. 有部分属性值会出现双斜杠语法,比如border-image、-webkit-mask-box-image
  2. 不支持双斜杠注释最主要的原因是无法兼容现版本,会对现有 CSS 带来副作用
  3. 为了兼容现有版本,CSS 新特性不能影响其他 CSS 语句,语法规则也从未改变过

可以肯定地说,CSS 以后也不会有双斜杠注释的规则。另外,本文的很多观点和结论都是归纳总结而来,并没有追究官方资料,可能有少许不准确或者有误的地方,欢迎评论区赐教。

欢迎关注我的公众号:前端侦探
原文:https://segmentfault.com/a/1190000043885414

链接: https://www.fly63.com/article/detial/12508


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK