link和@import的区别浅析
我们都知道,外部引入 CSS 有2种方式,link
标签和@import
。
它们有何本质区别,有何使用建议,在考察外部引入 CSS 这部分内容时,经常被提起。
如今,很多学者本着知其然不欲知其所以然的学习态度,不求甚解,只求结论。
所以,本文遵循 css hack 的渐进识别原则,
结论 → 区别 → 争议 → 细节 → 祖坟 → 感想,逐渐加深理论层级,
力争每个 level 的读者,都能 get 到自己想要的内容,不必继续阅读下去。
结论
就结论而言,强烈建议使用link
标签,慎用@import
方式。
这样可以避免考虑@import
的语法规则和注意事项,避免产生资源文件下载顺序混乱和http请求过多的烦恼。
区别
1.从属关系区别@import
是 CSS 提供的语法规则,只有导入样式表的作用;link
是HTML提供的标签,不仅可以加载 CSS 文件,还可以定义 RSS、rel 连接属性等。
2.加载顺序区别
加载页面时,link
标签引入的 CSS 被同时加载;@import
引入的 CSS 将在页面加载完毕后被加载。
3.兼容性区别@import
是 CSS2.1 才有的语法,故只可在 IE5+ 才能识别;link
标签作为 HTML 元素,不存在兼容性问题。
4.DOM可控性区别
可以通过 JS 操作 DOM ,插入link
标签来改变样式;由于 DOM 方法是基于文档的,无法使用@import
的方式插入样式。
5.权重区别(该项有争议,下文将详解)link
引入的样式权重大于@import
引入的样式。
争议
不知从什么时候开始,当你在网上搜索link
和@import
的区别时,千篇一律的答案里就悄悄的多了一句“link
引入的样式权重大于@import
引入的样式”。
但是并没有一份答案,附带着对这句话的任何解释或实例。
这句话究竟是什么意思,该怎么理解呢?
发扬探索精神,我们不妨继续查阅资料。后来发现,还是有不少文章和帖子,对这句话表示质疑,进而自己写了 demo 去验证,验证的结果,确实无法与这句话相吻合。
而且,笔者也并未发现能清楚、正确、有理有据的解释这个结论到底对,还是不对的文章。
那么这个结论,最初是从哪里来的,可能已经无从考证了。
换个思维方式,不去争辩它的对错了,探索未果,我们就从这个结论的核心关键词“权重”出发,去研究它。
说到“权重”,有必要再解释一下:CSS 中的权重,指的是选择器的优先级。
CSS 选择器的权重高,即选择器的优先级高。
CSS 的优先级特性表现为,对同一 HTML 元素设置样式时,不同选择器的优先级不同,优先级低的样式将被高优先级的样式层叠掉。
CSS 权重优先级顺序简单表示为:!important > 行内样式 > ID > 类、伪类、属性 > 标签名 > 继承 > 通配符
为了便于理解权重的计算方式,我们按以下方式进行数值假设分析:
选择器 | 权重 |
---|---|
通配符 | 0 |
标签 | 1 |
类/伪类/属性 | 10 |
ID | 100 |
行内样式 | 1000 |
important | 1/0(无穷大) |
再举实例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style type="text/css">
#myid { /* id选择器权重为100 */
background-color: pink;
}
#divid .myspan input { /* 权重为 100 + 10 + 1 = 111 */
background-color: yellow;
}
input[type="button"] { /* 权重为 10 */
color: white !important; /* !important权重为无穷大 */
}
input.myclass { /* 此为标签指定式选择器,权重为 1 + 10 = 11 */
color: black;
}
</style>
</head>
<body>
<div id="divid">
<span class="myspan">
<input type="button" id="myid" class="myclass" name="myname"
value="点我" style=" color: green;">
<!-- style样式的权重为1000 -->
</span>
</div>
</body>
</html>
每个样式的权重值,都在实例中,以注释的形式标明。
根据权重值可知,最终,这个按钮的样式一定是,蓝色背景,白色字,结果如下图:
存在!important
时,不作他想,一定是权重最大的样式。
既然我们了解了,CSS 中的权重是怎么回事,那回到主题,“link
引入的样式权重大于@import
引入的样式”,
难道 CSS 的引入方式也有权重吗?其实我们不必纠结它是否有权重之说,我们只需理论结合实际的去分析,各种情况下,结果如何即可。
现有如下3个css文件:
/* green.css */
div {
background-color: green;
border: 3px solid red;
}
/* yellow.css */
div {
background-color: yellow;
border: 3px solid black;
}
/* blue.css */
@import url("green.css");
div{
background-color: blue;
}
实例1:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<!-- 实例1\. link标签引入yellow.css,内联样式引入green.css -->
<link rel="stylesheet" href="yellow.css">
<style type="text/css">
@import url("green.css");
</style>
</head>
<body>
<div style="width: 50px; height: 50px;"></div>
<!-- 盒子为,绿色背景,红色边框,即green.css生效 -->
</body>
</html>
实例1结果如下图:
实例2:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<!-- 实例2\. 内联样式引入green.css,link标签引入yellow.css -->
<style type="text/css">
@import url("green.css");
</style>
<link rel="stylesheet" href="yellow.css">
</head>
<body>
<div style="width: 50px; height: 50px;"></div>
<!-- 盒子为黄色背景,黑色边框,即yellow.css生效 -->
</body>
</html>
实例2结果如下图:
对比实例1和实例2这两个正好相反的结果可知,link
和@import
并没有产生类似权重的效果,只是单纯的体现了CSS的层叠性,写在后面的样式,覆盖前面的样式。
实例3:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<!-- 实例3\. 内联样式引入green.css,内联样式中设置粉色背景 -->
<style type="text/css">
@import url("green.css");
div {
background-color: pink;
}
</style>
</head>
<body>
<div style="width: 50px; height: 50px;"></div>
<!-- 盒子为粉色背景,红色边框,即green.css已生效,但背景色被内联样式层叠为粉色 -->
</body>
</html>
实例3结果如下图:
实例4:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<!-- 实例4\. link标签引入blue.css,blue.css中引入green.css -->
<link rel="stylesheet" href="blue.css">
</head>
<body>
<div style="width: 50px; height: 50px;"></div>
<!-- 盒子为蓝色背景,红色边框,即green.css已生效,但背景色被blue.css层叠为蓝色 -->
</body>
</html>
实例4结果如下图:
分析实例3和实例4的结果可知:
对于实例3,我们看到红色边框,证明内联样式中使用@import
引入的green.css
已经生效,但其背景样式被内联样式中的粉色背景层叠掉,这个现象表明,@import
不只是如我们看到的那样,处于内联样式顶部,其被引入的样式,在结构上,也确实是被置于内联样式之前,所以内联样式才能够层叠掉它。
同理,实例4中,在link
标签引入的blue.css
文件内,顶部同样存在@import
引入的green.css
,红色边框依然可以证明,green.css
已经生效,但其背景样式被blue.css
本身的蓝色背景层叠掉,@import
引入的样式在blue.css
中也是被置于它本身样式之前的。
到此为止,我展开了大胆的猜想,“link
引入的样式权重大于@import
引入的样式”,这个结论的给出者,是想告诉大家:
在link
标签引入的 CSS 文件中,使用@import
时需注意,如果已经存在相同样式,@import
引入的这个样式将被该 CSS 文件本身的样式层叠掉,表现出link
标签引入的样式权重大于@import
引入的样式这样的直观效果。
对于我设想的结论,似乎挺能说通的,毕竟这是实践出的结果。
那些验证过此结论的前人,他们都是在一个 HTML 页面中,一前一后分别使用link
和内联样式的@import
去比较的,我在实例1和实例2中也是如此做的,并不能反推出“link
引入的样式权重大于@import
引入的样式”这个结论,所以,我不自量力的认为,这个结论其实最初只是丢了个已知条件而已。
那么我们一起把这个结论重新梳理一下:在link
标签引入的 CSS 文件中使用@import
时,相同样式将被该 CSS 文件本身的样式层叠。
Ps.首先感谢各种看官的阅读。笔者属于学习阶段,学识尚浅,虽然本文结论已得到笔者编码验证,但不排除笔者大脑短路、措辞有误的可能,有缘阅读到此处的都是真爱,希望诸位大拿、大牛、大仙、大圣、大神们不吝赐教,及时指正,避免诱导萌新误入歧途,再次向你们表达笔者的谢意!
细节
既然已经说了这么多,就顺便提一下关于@import
使用时的其它细节。
在《CSS权威指南》中写道:
@import
一定要写在除@charset
外的其他任何 CSS 规则之前,如果置于其它位置将会被浏览器忽略,而且,在@import
之后如果存在其它样式,则@import
之后的分号是必须书写,不可省略的。
到此为止,似乎事情都弄清楚了,但是突然又有个疑点浮现出来:
在讨论区别的时候,不是说加载页面时,link
标签引入的 CSS 先于@import
引入的 CSS 加载吗,那link
标签引入的样式又怎会把@import
引入的样式层叠掉呢?
要回答这个问题,首先我们要一起明确一些有关浏览器的概念:
浏览器执行过程可以简单分为加载、解析、渲染,这三个步骤。
加载:根据请求的URL进行域名解析,向服务器发送请求,接收响应文件(如 HTML、JS、CSS、图片等)。
解析:对加载到的资源(HTML、JS、CSS等)进行语法解析,构建相应的内部数据结构(比如HTML的DOM树,JS对象的属性表,CSS的样式规则等)。
渲染:构建渲染树,对各个元素进行位置计算、样式计算等,然后根据渲染树完成页面布局及绘制的过程(可以理解为“画”页面元素)。
这几个过程不是完全孤立的,会有交叉,比如HTML加载后就会进行解析,然后拉取HTML中指定的CSS、JS等。`
现在,我们应该已经了解了加载和渲染的概念,明白它们是两个不同的过程,那么对上文中抛出的疑问继续追问:
link
先于@import
加载,是不是也先于@import
渲染呢?
实际上,渲染的动作一般都会执行多次,最后一次渲染,一定是依据之前加载过的所有样式整合后的渲染树进行绘制页面的,已经被渲染过的页面元素,也会被重新渲染。
那么我们就可以把@import
这种导入 CSS 文件的方式理解成一种替换,CSS 解析引擎在对一个 CSS 文件进行解析时,如在文件顶部遇到@import
,将被替换为该@import
导入的 CSS 文件中的全部样式。
峰回路转,柳暗花明,终于弄明白为何@import
引入的样式,会被层叠掉了。其虽然后被加载,却会在加载完毕后置于样式表顶部,最终渲染时自然会被下面的同名样式层叠。
至此为止,“link
引入的样式权重大于@import
引入的样式”这个结论,我终于为它圆了场。但愿此结论的作者,本意真如我的猜测,否则若是我多心而跑偏了的话,不敢想象这背后究竟隐藏着多大的秘密。
祖坟
有些细心而专业的读者可能已经发现了,我用自己的思路和措辞,粗略的解释了有关 CSS 加载和渲染的知识,有些涉世未深的前端爱好者可能会一头雾水,无法作为系统学习的依据。这不打紧,出来混,祖坟总是要刨的,想要透彻的学习相关内容,进一步了解底层原理的学者,我早已为你备下了丰厚的见面礼~
有关link
和@import
在性能分析方面的比较,国外的高手早在多年前就曾执过笔:
爱好母语的请戳我:https://www.stevesouders.com/blog/2009/04/09/dont-use-import/
阅读英语的请戳我:https://www.qianduan.net/high-performance-web-site-do-not-use-import/
有关浏览器内部工作原理的神作,也是几年前出自歪果仁大牛:
1 为普通话:https://kb.cnblogs.com/page/129756/
2 for English:http://taligarsiel.com/Projects/howbrowserswork1.htm
link和@import的区别浅析的更多相关文章
- 【转载】link和@import的区别
link和@import的区别 原文地址:http://www.cnblogs.com/zbo/archive/2010/11/17/1879590.html 页面中使用CSS的方式主要有3种:行内添 ...
- 引入CSS文件的方式,以及link与@import的区别
一.引入css的方式 在HTML中引入css的方法主要有4种:行内式.内嵌式.链接式和导入式. 1.行内式 <div style="background:yellow;"&g ...
- 页面引入css用link和import的区别
假设有一个css文件a.css,文件里的内容如下: p { font-size: 18px; } 现在分别使用两种方式引入a.css: 1.使用html的link标签 <link rel=&qu ...
- 由link和@import的区别引发的CSS渲染杂谈
我们都知道,外部引入 CSS 有2种方式,link标签和@import. 它们有何本质区别,有何使用建议,在考察外部引入 CSS 这部分内容时,经常被提起. 如今,很多学者本着知其然不欲知其所以然的学 ...
- 【12】link与@import的区别
[12]link与@import的区别 link是HTML方式, @import是CSS方式 link最大限度支持并行下载,@import过多嵌套导致串行下载,出现FOUC link可以通过rel=& ...
- css 样式引入的方法 link 与import的区别
<link> 元素所参考的样式用户可以自由的选择加以改变,而导入的样式表单就自动的与剩下的样式表融合在一起了 CSS与HTML文档结合的4中方法:1 使用<link>元素链接到 ...
- link与@import的区别
我们都知道link与@import都可以引入css样式表,那么这两种的区别是什么呢?先说说它们各自的链接方式,然后说说它们的区别~~~ link链入的方式: <link rel="st ...
- CSS中link与import的区别
一.import的用法 1,在html文件中 <style type="text/css"> @import url(http://www.dreamdu.com/st ...
- css引入的两种方法link和@import的区别和用法
link和@import都是HTML中引入CSS的语法单词. 两者的基本语法 link语法结构 <link href="外部CSS文件的URL路径" rel="st ...
随机推荐
- mysql通过mysqldunp命令重做从库详细操作步骤
mysql通过mysqldunp命令重做从库详细操作步骤 背景 生产环境上的主从复制集群,因为一些异常或人为原因,在从库做了一些操作,导致主从同步失败.一般修复起来比较麻烦,通过重做mysql从库的方 ...
- JZ-034-第一个只出现一次的字符位置
第一个只出现一次的字符位置 题目描述 在一个字符串(0<=字符串长度<=10000,全部由字母组成)中找到第一个只出现一次的字符,并返回它的位置, 如果没有则返回 -1(需要区分大小写). ...
- LeetCode-092-反转链表 II
反转链表 II 题目描述:给你单链表的头指针 head 和两个整数 left 和 right ,其中 left <= right .请你反转从位置 left 到位置 right 的链表节点,返回 ...
- tep完整教程帮你突破pytest
持续维护的教程 tep教程会随着版本更新或经验积累,持续维护在电子书中,最新的最全的内容请锁定这篇文章[最新]tep完整教程帮你突破pytest: https://dongfanger.gitee.i ...
- 报错———http://mybatis.org/dtd/mybatis-3-mapper.dtd 报红解决方案
初次使用mybatis时,下面红线上的地址报红. 解决方法是:将http://mybatis.org/dtd/mybatis-3-mapper.dtd拷贝.添加到下面标记处.
- 域渗透 | kerberos认证及过程中产生的攻击
文章首发于公众号<Z2O安全攻防> 直接公众号文章复制过来的,排版可能有点乱, 可以去公众号看. https://mp.weixin.qq.com/s/WMGkQoMnQdyG8UmS ...
- 浅析Java反射--Java
前言 上篇文章我们提到了可以使用反射机制破解单例模式.这篇文章我们就来谈一谈什么是反射,反射有什么用,怎么用,怎么实现反射. 概述 Java的反射(reflection)机制:是指在程序的运行状态中, ...
- 12.16 JAVA swing
------------恢复内容开始------------ 12.16JAVA swing 1.框架 JFrame>JPanel>组件JButton JTestfilled JTable ...
- Android BLE 蓝牙开发——扫码枪基于BLESSED
一.蓝牙模式HID与BLE 当扫码枪与手机连接时,通常采用的是蓝牙HID(Human Interface Device)模式.本质上是一个把扫码枪作为一个硬件键盘,按照键盘协议把扫码后的结果逐个输入到 ...
- 《前端运维》五、k8s--3灰度发布、滚动更新与探针
一.灰度发布 灰度发布是一种发布方式,也叫金丝雀发布,起源是矿工在下井之前会先放一只金丝雀到井里,如果金丝雀不叫了,就代表瓦斯浓度高.原因是金丝雀对瓦斯气体很敏感.灰度发布的做法是:会在现存旧应用的基 ...