如何异步加载CSS

Pau*_*ina 62 html css asynchronous

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

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

Vla*_*ero 109

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

<link rel="stylesheet" href="css.css" media="none">
Run Code Online (Sandbox Code Playgroud)

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

<link rel="stylesheet" href="css.css" media="none" onload="if(media!='all')media='all'">
Run Code Online (Sandbox Code Playgroud)

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

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

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

您可以在www.itcha.edu.sv中查看该操作

在此输入图像描述

来源http://keithclark.co.uk/

  • 看起来这个技巧不再起作用了. (17认同)
  • 那么如何防止页面在重新渲染所有内容时闪烁呢?另外,您是否内联核心应用程序外壳样式,以便您的页面具有一些初始布局,而不是呈现 Lynx 引以为豪的内容? (3认同)
  • 这对我有用(08年7月8日).它在pagespeed洞察力方面给出了很好的分数 (3认同)
  • 似乎仍然适合我.执行此操作后,我知道更长时间在PageSpeed Insights中收到此文件的警告. (2认同)
  • 恕我直言,[jabachetta 使用“预加载”的新答案](/sf/answers/3272562541/) 可能是现在的首选解决方案。如果有人有理由认为*这个*答案仍然更好,请添加评论解释原因。理想情况下,链接到一个资源,以确认为什么/何时这种方法仍然可能更可取。[假设您使用 polyfill 来支持 Firefox 和旧版浏览器上的“预加载” - 请参阅该答案第一条评论中的链接]。 (2认同)

jab*_*tta 51

预载

现在,您可以使用preload关键字link元素.

同步版本:

<link href="style.css" rel="stylesheet">
Run Code Online (Sandbox Code Playgroud)

异步版本:

<link href="style.css" rel="preload" as="style">
Run Code Online (Sandbox Code Playgroud)

注意

最近这个功能在现代浏览器中得到广泛支持.如果您需要旧版浏览器的后备,请使用loadCSS.

更新(07/18)

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

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

  • 无需使用loadCSS,polyfill就足够了:https://github.com/filamentgroup/loadCSS/blob/master/src/cssrelpreload.js (3认同)
  • 答案已更新,以提供完整浏览器支持的解决方案以及其他说明。 (2认同)
  • @jabacchetta 非常感谢 2020 年更新,谢谢。我特别地寻找最近编写的说明,其中浏览器支持通常更好。三年来网络发生了很多变化! (2认同)
  • 显然,最好 `onload="this.rel='stylesheet'; this.onload = null"`。显然,有必要将 `this.onload` 设置为 `null` 以避免在某些浏览器中调用两次。 (2认同)

Fli*_*imm 12

使用media="print"onload

filament group 最近(2019 年 7 月)发表了一篇文章,给出了他们关于如何异步加载 CSS 的最新建议。尽管他们是流行的 Javascript 库loadCSS的开发者,但他们实际上推荐了这个不需要 Javascript 库的解决方案:

<link
  rel="stylesheet"
  href="/path/to/my.css"
  media="print"
  onload="this.media='all'; this.onload = null"
>
Run Code Online (Sandbox Code Playgroud)

Usingmedia="print"将指示浏览器不要在屏幕上使用此样式表,而是在打印时使用。浏览器确实会下载这些打印样式表,但是是异步的,这正是我们想要的。我们还希望样式表在下载后立即使用,为此我们设置了onload="this.media='all'; this.onload = null". (有些浏览器会调用onload两次,要解决这个问题,我们需要设置this.onload = null。)如果需要,您可以<noscript>为没有启用 Javascript 的少数用户添加后备。

原来的文章值得一读,因为它进入更详细的比我在这里。csswizardry.com 上的这篇文章也值得一读。

  • 这种方法有一个警告:它不适用于不使用“unsafe-inline”的 CSP script-src。示例:`拒绝执行内联事件处理程序,因为它违反了以下内容安全策略指令:“script-src 'self' 'unsafe-eval'”。启用内联执行需要“unsafe-inline”关键字、哈希值(“sha256-...”)或随机数(“nonce-...”)。请注意,哈希不适用于事件处理程序、样式属性和 javascript: 导航,除非存在“unsafe-hashes”关键字。 (2认同)

kam*_*mus 6

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

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>
Run Code Online (Sandbox Code Playgroud)

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>
Run Code Online (Sandbox Code Playgroud)

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

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

  • 示例2加载Javascript,但问题是加载CSS.如果你从`<script>`改为`<style rel = stylesheet>`,你知道例2是否也适用于CSS吗?(只是好奇.我将使用`loadCSS`(即你的例子3),如果我需要稍后加载CSS.) (3认同)

Rou*_*ica 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);
Run Code Online (Sandbox Code Playgroud)

  • @TecMan 是的。正如你所看到的,这个函数在 `window.load` 事件上完成它的工作。因此,下载所有内容后就开始下载。没有运气。您需要尽快开始非阻塞加载。 (2认同)

vir*_*hra 5

Async CSS Loading Approaches

there are several ways to make a browser load CSS asynchronously, though none are quite as simple as you might expect.

<link rel="preload" href="mystyles.css" as="style" onload="this.rel='stylesheet'">
Run Code Online (Sandbox Code Playgroud)