CSSを非同期にロードする方法


94

私のサイトでレンダリングがブロックされている2つのCSSファイルを削除しようとしています-それらはGooglePage SpeedInsightsに表示されます。私はさまざまな方法に従いましたが、どれも成功しませんでした。しかし、最近、Thinking Asyncに関する投稿を見つけました<script async src="https://third-party.com/resource.js"></script>。このコードを適用すると、問題は解決しました。

ただし、公開後、ページのスタイルが失われました。コードが機能するため、何が起こっているのかよくわかりませんが、アップロード後のスタイリングが機能しません。これであなたの助けをいただければ幸いです。ありがとう


2
スタイルまたはスクリプトに非同期を適用していますか?ページを読み込んだ後、スタイルが読み込まれますか、それとも表示されませんか?
kamus 2015

async属性をスタイルに適用し、ヘッダーに配置しました。
Paulina994 2015

2
スタイルの問題は、それらを遅く(たとえば本体に)ロードすると再レンダリングがトリガーされ、標準では許可されていないことです(ただし、ブラウザーは非常に寛容なので、とにかく機能します)。問題がサードパーティのサーバーからの応答時間が遅いことである場合、おそらく代わりにサーバーでそれらをホストすることができますか?
Josef Engelfrost 2015

回答:


131

非同期スタイルシートのダウンロードをトリガーする秘訣は、<link>要素を使用して、メディア属性に無効な値を設定することです(media = "none"を使用していますが、どの値でもかまいません)。メディアクエリがfalseと評価された場合でも、ブラウザはスタイルシートをダウンロードしますが、ページをレンダリングする前にコンテンツが利用可能になるのを待ちません。

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

スタイルシートのダウンロードが完了したら、スタイルルールがドキュメントに適用されるように、メディア属性を有効な値に設定する必要があります。onloadイベントは、メディアプロパティをすべてに切り替えるために使用されます。

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

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>

あなたはwww.itcha.edu.svで操作を見ることができます

ここに画像の説明を入力してください

http://keithclark.co.uk/のソース


わかりました。名前を指定するだけで、オンハンドラーの要素属性を参照できることを知りませんでした。私はいつも「イベント」が唯一の例外だと思っていました。
Teemoh 2017年

1
では、ページがすべてを再レンダリングするときに、ページが点滅しないようにするにはどうすればよいでしょうか。さらに、コアアプリのシェルスタイルをインライン化して、Lynxが誇るものをレンダリングする代わりに、ページに初期レイアウトを設定しますか?
クリス・ラブ

2
まだ私のために働いているようです。これを行った後、PageSpeedInsightsでこのファイルの警告が表示されることがわかりました。
AndyWarren

3
これは私のために働いています(2018年7月8日)。そして、それはページスピードの洞察で良いスコアを与えます
abilash er 2018

1
「プリロード」を使用したjabachettaの新しい回答であるIMHOは、現在、おそらく推奨されるソリューションです。この答えがまだ望ましいと思う理由がある場合は、その理由を説明するコメントを追加してください。理想的には、このアプローチが依然として望ましい理由/時期を確認するリソースにリンクします。[ preloadFirefoxおよび古いブラウザでサポートするためにポリフィルを使用すると仮定します-その回答の最初のコメントのリンクを参照してください]。
ToolmakerSteve

118

2020年の更新


簡単な答え(完全なブラウザサポート):

<link rel="stylesheet" href="style.css" media="print" onload="this.media='all'">

文書化された回答(オプションのプリロードとスクリプトが無効なフォールバックを使用):

 <!-- Optional, if we want the stylesheet to get preloaded. Note that this line causes stylesheet to get downloaded, but not applied to the page. Use strategically — while preloading will push this resource up the priority list, it may cause more important resources to be pushed down the priority list. This may not be the desired effect for non-critical CSS, depending on other resources your app needs. -->
 <link rel="preload" href="style.css" as="style">

 <!-- Media type (print) doesn't match the current environment, so browser decides it's not that important and loads the stylesheet asynchronously (without delaying page rendering). On load, we change media type so that the stylesheet gets applied to screens. -->
 <link rel="stylesheet" href="style.css" media="print" onload="this.media='all'">

 <!-- Fallback that only gets inserted when JavaScript is disabled, in which case we can't load CSS asynchronously. -->
 <noscript><link rel="stylesheet" href="style.css"></noscript>

プリロードと非同期の組み合わせ:

プリロードされた非同期CSSが必要な場合、このソリューションは、上記の文書化された回答の2行を組み合わせるだけで、少しすっきりします。ただし、Firefoxではpreloadキーワードがサポートされるまでこれは機能しません。また、上記の文書化された回答で詳しく説明されているように、プリロードは実際には有益ではない場合があります。

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

追加の考慮事項:

一般に、CSSを非同期でロードする場合、CSSは理由からレンダリングをブロックするリソースであるため重要なCSSをインライン化することをお勧めします。

多くの非同期CSSソリューションのフィラメントグループの功績です。


3
loadCSSを使用する必要はありません。ポリフィルで十分です:github.com/filamentgroup/loadCSS/blob/master/src/…–
nathan

1
Preloadのスペックステータスは最終的に[ W3CCandidate Recommendation]になります。(w3.org / TR / preload /…)Firefoxはそれをサポートしていますが、デフォルトでは無効になっています。それを制御するFirefoxフラグの「CanIUse」の説明については、回答の「広くサポートされている」リンクをクリックしてください。
ToolmakerSteve

1
追加の説明とともに、完全なブラウザサポートのソリューションを提供するために更新された回答。
jabacchetta

1
@ jabacchetta2020アップデートは大歓迎です。ありがとうございます。私は特に、ブラウザのサポートが一般的に優れている最近書かれた指示を探していました。ウェブ上で3年間で多くの変化があります!
Brandito 2010年

2
どうやら、する方が良いonload="this.rel='stylesheet'; this.onload = null"です。どうやら、一部のブラウザではこれが2回呼び出されないように設定this.onloadする必要がありnullます。
Flimm

10

media="print"およびの使用onload

フィラメントグループは最近(2019年7月)、 CSSを非同期でロードする方法に関する最新の推奨事項を示す記事公開しました。彼らは人気のあるJavascriptライブラリloadCSSの開発者ですが、実際にはJavascriptライブラリを必要としないこのソリューションを推奨しています。

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

を使用media="print"すると、このスタイルシートを画面ではなく印刷で使用するようにブラウザに指示されます。ブラウザは実際にこれらの印刷スタイルシートをダウンロードしますが、非同期でダウンロードします。また、ダウンロード後にスタイルシートを使用する必要があるため、を設定しonload="this.media='all'; this.onload = null"ます。(一部のブラウザーはonload2回呼び出しthis.onload = nullます。これを回避するには、設定する必要があります。)必要に<noscript>応じて、Javascriptが有効になっていないまれなユーザーのフォールバックを追加できます。

元の記事には、それは私がここにいるよりも詳細に入ると、読み取りの価値があります。csswizardry.comのこの記事も読む価値があります。


5

あなたは多くの方法でそれを手に入れることを試みることができます:

1.Usingmedia="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.Ifはあなたが試みることができる loadCSSを

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

3
例2はJavascriptをロードしますが、問題はCSSのロードに関するものです。から<script>に変更した場合、例2がCSSでも機能するかどうか知ってい<style rel=stylesheet>ますか?(興味があります。loadCSS後でCSSをロードする必要がある場合は、代わりに(つまり、例3)を使用します。)
KajMagnus 2017

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);

1
loadCSSアプローチと比較すると、この方法の欠点はありますか?ページ本文のタグvar newStyle = document.createElement("link"); newStyle.rel = "stylesheet"; newStyle.href = "stylesheet.css"; document.getElementsByTagName("head")[0].appendChild(newStyle);内の従来のコード<script>は、MSIE8のような古いブラウザでもうまく機能しているようです。
TecMan 2018

2
@TecManはいあります。ご覧のとおり、この関数はwindow.loadイベントで機能します。したがって、すべてがダウンロードされるとダウンロードが開始されます。運がない。開始するには、できるだけ早くノンブロッキングロードが必要です。
ミロシュĐakonović

5

非同期CSS読み込みアプローチ

ブラウザにCSSを非同期にロードさせる方法はいくつかありますが、予想するほど単純な方法はありません。

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

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);
}

0

@ vladimir-salguero回答を許可しない厳格なコンテンツセキュリティポリシーがある場合は、これを使用できます(スクリプトをメモしてください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>

asyncスクリプトタグにはsrc非同期でロードするためのがないため、属性は無視されると思います...またはここで本当に役立ちますか?また、どの値をnonce?として使用するかについてもう少し詳しく説明できますか?
フィリップ

0

上記のすべてがグーグルページスピードの洞察を今印象づけることができないので、答えを更新するように注意してください。

グーグルによると、これはあなたが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>

1
前述のpreloadキーワードアプローチを使用している場合は、誤検知(PageSpeedバグ)の可能性があります。github.com/filamentgroup/loadCSS/issues/53
jabacchetta

1
更新:Googleは、この問題が発生したPageSpeedバージョン4を非推奨にし、シャットダウンしました。これは、この非同期コードが推奨されたバージョンでした。私はPageSpeed5でテストしていませんが、現在のテスト方法の説明と、「link」の「preload」タグのサポートを考えると、Googleにとってはjabachettaの答えの方がおそらく良い答えです。
ToolmakerSteve

1
@ToolmakerSteveはいこの回答は頻繁にモデレートする必要があります。ただし、このコードは、ページ速度を100にするために機能します。
kaushikgandhi19年

0

私は使用しようとしました:

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

正常に動作しますが、rel = "preload"を使用すると、cssをダウンロードするだけで、すぐには適用されないため、累積的なレイアウトシフトも発生します。

DOMがリストにul、liタグを含む場合の例では、デフォルトでliタグの前に箇条書きがあり、CSSを適用して、これらの箇条書きをリスト用のカスタムスタイルに削除します。そのため、ここでは累積的なレイアウトシフトが発生しています。

そのための解決策はありますか?


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'">
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.