如何异步加载CSS

时间:2015-09-24 10:40:09

标签: html css asynchronous

我正在尝试消除在我的网站上呈现阻止的2个CSS文件 - 它们出现在Google Page Speed Insights上。我遵循了不同的方法,但都没有成功。但是,最近,我发现了一篇关于Thinking Async的帖子,当我应用此代码时:<script async src="https://third-party.com/resource.js"></script>它确实消除了这个问题。

然而,在发布后,该页面失去了样式。我不太确定会发生什么,因为代码可以工作但是上传后的样式不起作用。非常感谢您的帮助。感谢

11 个答案:

答案 0 :(得分:94)

触发异步样式表下载的技巧是使用<link>元素并为media属性设置无效值(我使用media =“none”,但任何值都可以)。当媒体查询评估为false时,浏览器仍会下载样式表,但在呈现页面之前不会等待内容可用。

<link rel="stylesheet" href="css.css" media="none">

样式表下载完成后,必须将media属性设置为有效值,以便将样式规则应用于文档。 onload事件用于将media属性切换为all:

<link rel="stylesheet" href="css.css" media="none" onload="if(media!='all')media='all'">

这种加载CSS的方法将比标准方法更快地向访问者提供可用内容。关键CSS仍然可以使用通常的阻塞方法(或者你可以内联它以获得最佳性能),非关键样式可以逐步下载并在解析/渲染过程中稍后应用。

此技术使用JavaScript,但您可以通过在<link>元素中包含等效的阻止<noscript>元素来满足非JavaScript浏览器:

<link rel="stylesheet" href="css.css" media="none" onload="if(media!='all')media='all'"><noscript><link rel="stylesheet" href="css.css"></noscript>

您可以在www.itcha.edu.sv

中查看操作

enter image description here

http://keithclark.co.uk/

中的来源

答案 1 :(得分:47)

预压

现在,您可以将preload keyword用于link元素。

同步版本:

<link href="style.css" rel="stylesheet">

异步版本:

<link href="style.css" rel="preload" as="style">

注意

此功能最近才成为现代浏览器中的widely supported。如果您需要旧版浏览器的后备广告,请使用loadCSS

更新(07/18)

Firefox中默认禁用此功能。在Firefox实施解决方案之前,loadCSS(如上所述)可能是您最好的选择。以下评论取自this discussion

  

我们决定采用不同的方法来实现rel = preload。我做   不知道什么时候会实施。

答案 2 :(得分:7)

你可以尝试以很多方式获得它:

1.在脚下使用media="bogus"<link>

<head>
    <!-- unimportant nonsense -->
    <link rel="stylesheet" href="style.css" media="bogus">
</head>
<body>
    <!-- other unimportant nonsense, such as content -->
    <link rel="stylesheet" href="style.css">
</body>

2.以旧方式插入DOM

<script type="text/javascript">
(function(){
  var bsa = document.createElement('script');
     bsa.type = 'text/javascript';
     bsa.async = true;
     bsa.src = 'https://s3.buysellads.com/ac/bsa.js';
  (document.getElementsByTagName('head')[0]||document.getElementsByTagName('body')[0]).appendChild(bsa);
})();
</script>

3.如果你可以试试插件,你可以试试     loadCSS

<script>
  // include loadCSS here...
  function loadCSS( href, before, media ){ ... }
  // load a file
  loadCSS( "path/to/mystylesheet.css" );
</script>

答案 3 :(得分:5)

下面的函数将创建并向文档添加您希望异步加载的所有样式表。 (但是,感谢Event Listener,它只会在所有窗口的其他资源都已加载后才会这样做。)

请参阅以下内容:

function loadAsyncStyleSheets() {

    var asyncStyleSheets = [
    '/stylesheets/async-stylesheet-1.css',
    '/stylesheets/async-stylesheet-2.css'
    ];

    for (var i = 0; i < asyncStyleSheets.length; i++) {
        var link = document.createElement('link');
        link.setAttribute('rel', 'stylesheet');
        link.setAttribute('href', asyncStyleSheets[i]);
        document.head.appendChild(link);
    }
}

window.addEventListener('load', loadAsyncStyleSheets, false);

答案 4 :(得分:3)

使用media="print"onload="this.media='all'"

The filament group recently (July 2019) published an article给出了有关如何异步加载CSS的最新建议。即使他们是流行的Javascript库loadCSS的开发者,他们实际上还是建议使用不需要Javascript库的解决方案:

<link rel="stylesheet" href="/path/to/my.css" media="print" onload="this.media='all'">

使用media="print"将向浏览器指示不要在屏幕上使用此样式表,而应在打印时使用。浏览器实际上确实下载了这些打印样式表,但是异步地下载了,这正是我们想要的。我们还希望样式表一经下载即可使用,为此,我们设置了onload="this.media='all'"。如果需要,可以为未启用Javascript的罕见用户添加<noscript>后备广告。

original article值得一读,因为它比我在这里更详细。 This article on csswizardry.com也值得一读。

答案 5 :(得分:2)

异步CSS加载方法

有几种方法可以使浏览器异步加载CSS,尽管没有一种方法可以像您期望的那样简单。

<link rel="preload" href="mystyles.css" as="style" onload="this.rel='stylesheet'">

答案 6 :(得分:1)

如果您需要以编程方式和异步方式加载CSS链接:

// https://www.filamentgroup.com/lab/load-css-simpler/
function loadCSS(href, position) {
  const link = document.createElement('link');
  link.media = 'print';
  link.rel = 'stylesheet';
  link.href = href;
  link.onload = () => { link.media = 'all'; };
  position.parentNode.insertBefore(link, position);
}

答案 7 :(得分:0)

如果您有严格的内容安全政策但不允许@vladimir-salguero answer,则可以使用此政策(请注意脚本nonce ):

<script nonce="(your nonce)" async>
$(document).ready(function() {
    $('link[media="none"]').each(function(a, t) {
        var n = $(this).attr("data-async"),
            i = $(this);
        void 0 !== n && !1 !== n && ("true" == n || n) && i.attr("media", "all")
    })
});
</script>

只需将以下内容添加到样式表参考中:media="none" data-async="true"。这是一个例子:

<link rel="stylesheet" href="../path/script.js" media="none" data-async="true" />

jQuery示例:

<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/themes/smoothness/jquery-ui.css" type="text/css" media="none" data-async="true" crossorigin="anonymous" /><noscript><link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/themes/smoothness/jquery-ui.css" type="text/css" /></noscript>

答案 8 :(得分:0)

请谨慎更新答案,因为上述所有内容现在都无法打动Google Pagespeed见解。

根据Google,这是实现CSS异步加载的方式

 < noscript id="deferred-styles" >
        < link rel="stylesheet" type="text/css" href="small.css"/ >
    < /noscript >

<script>
  var loadDeferredStyles = function() {
    var addStylesNode = document.getElementById("deferred-styles");
    var replacement = document.createElement("div");
    replacement.innerHTML = addStylesNode.textContent;
    document.body.appendChild(replacement)
    addStylesNode.parentElement.removeChild(addStylesNode);
  };
  var raf = window.requestAnimationFrame || window.mozRequestAnimationFrame ||
      window.webkitRequestAnimationFrame || window.msRequestAnimationFrame;
  if (raf) raf(function() { window.setTimeout(loadDeferredStyles, 0); });
  else window.addEventListener('load', loadDeferredStyles);
</script>

答案 9 :(得分:0)

我尝试使用:

<link rel="preload stylesheet" href="mystyles.css" as="style">

它可以正常工作,但是它也会引起布局的累积偏移,因为当我们使用rel =“ preload”时,它只是下载css,而不是立即应用。

例如,当DOM加载一个包含ul,li标签的列表时,默认情况下,li标签之前有一个项目符号,然后应用CSS,我将这些项目符号删除为自定义样式以列出。 因此,这里发生了累积布局偏移。

有什么解决办法吗?

答案 10 :(得分:0)

使用rel="preload"使其独立下载,然后使用onload="this.rel='stylesheet'"将其应用于样式表(将as="style"应用于样式表是必要的,否则onload将不会工作)

<link rel="preload" as="style" type="text/css" href="mystyles.css" onload="this.rel='stylesheet'">