SamHwang1990/blog

<link> vs @import

Opened this issue · 0 comments

[toc]

引用外部样式表一般有两种方式。

第一种是使用html 的link标签:

<link href="external.css" rel="stylesheet" type="text/css">

第二种是使用css 的@import语法:

// a.css
@import url("b.css");

或是html style 标签内使用:

<style>
  @import url("b.css");
</style>

需要明确的一点是,@import声明只能在style 标签或css 文件的顶部,在其他位置声明是无效的。

这两种方式的差别其实挺大的,鉴于@import可能造成的交互、性能影响,我们强烈建议只使用<link>标签来加载外部样式表。

下面简单聊下两种方式的差别。

兼容性

<link>标签是标准的html 标签,从第一个版本开始就一直存在,故不存在兼容性问题。

@import语法是从css 2.1 开始引入的,所以只能兼容IE5 以上的浏览器。当然了,在当今世代,这根本不用担心。

加载次序

<link>@import造成的样式表加载方式是非常不一样的,这里面的区别会造成很多性能上和交互使用上的差异。下文罗列Steve Souders 对该问题的研究成果,参考自:don’t use @import

@import对性能的影响主要在于,该语法指向的样式表不能与<link>指向的样式表并发下载,只能等待后者的样式表加载完。具体场景例如:

@import and @import

同个css 文件或同个<style> 标签内出现多个@import声明,则这些声明指向的样式表会并发加载,谁先下载完就先解析并应用到文档上。

比如:

<style>
@import url('a.css');
@import url('b.css');
</style>

a.cssb.css会并发加载:

同级@import 声明并发下载

虽然a.css先声明,但假如b.cssa.css先加载完成,则b.css会先解析。

<link> and <link>

文档中使用<link>标签指向的外部样式表,都会并发下载,前提时同域名连接数没有超过浏览器限制:

<link rel='stylesheet' type='text/css' href='a.css'>
<link rel='stylesheet' type='text/css' href='b.css'>

using link ensures parallel downloads across all browsers

<link> mixed @import

当文档内使用<link>标签同时内联<style/>来使用@import声明时:

<link href="a.css" rel="stylesheet" type="text/css">
<style>
  @import url("b.css");
</style>

在IE6-8下,@import声明指向的样式表并不会与页面其他资源并发加载,而是等页面所有资源加载完成后才开始下载:

IE 下文档混合使用<link>与@import 会破块资源并发下载的行为

@import within <link>

@import声明位于<link>指向的外部样式表时,所有浏览器都不会并发加载该样式表,而是等页面所有资源加载完成后才开始。代码如下:

<link href="a.css" rel="stylesheet" type="text/css">
// a.css
@import url("b.css");

这种行为其实很容易理解,因为a.css本身时会在文档解析资源时并发加载,加载完后,自身也完成了解析,至于声明引用的b.css并不是文档本身,也就不需要并发加载b.css

<link> blocks @import

场景代码:

<link href="a.css" rel="stylesheet" type="text/css">
<link href="b.css" rel="stylesheet" type="text/css">
// a.css
@import url("c.css");

在文档中,分别用<link>标签引用了a.css、b.css,而a.css 又使用@import 声明引用了c.css。注意下次序结构:

+ a.css
	+ c.css
+ b.css

预期中,当a.css 加载并解析完的时候,应该就开始加载c.css

LINK doesn't block @import embedded stylesheets in browsers other than IE

然而,在IE 浏览器中(具体到哪个版本范围没测过),c.css 样式表的加载会被挂起,直到b.css 加载完成:

LINK blocks @import embedded in other stylesheets in IE

总结

在了解了<link>@import的兼容性、加载次序上的差别后,我们需要明确这些差别在日常开发中会带来的影响,以及为什么不推荐使用@import来加载外部样式表:

  • @import声明的样式表不能充分利用浏览器并发请求资源的行为,因为其加载行为往往会押后触发或会被其他资源加载挂起;
  • 由于@import样式表的延后加载,可能会导致页面样式闪烁;
  • 由于@import样式表的延后加载,很有可能会比页面中的javascript 脚本加载更晚,导致js 对html 元素样式的修改可能会被延后才解析的外部样式表所覆盖;

参考文章