Bagaimana cara memuat file CSS menggunakan Javascript?

316

Apakah mungkin untuk mengimpor stylesheet css ke halaman html menggunakan Javascript? Jika demikian, bagaimana itu bisa dilakukan?

PS javascript akan di-host di situs saya, tetapi saya ingin pengguna dapat memasukkan <head>tag situs web mereka, dan itu harus dapat mengimpor file css yang di-host di server saya ke halaman web saat ini. (baik file css dan file javascript akan di-host di server saya).

Klik Upvote
sumber
Ada juga pertanyaan tentang jQuery stackoverflow.com/questions/2685614/…
jcubic

Jawaban:

416

Inilah cara "jadul" untuk melakukannya, yang diharapkan bekerja di semua browser. Secara teori, Anda akan menggunakan setAttributesayangnya IE6 tidak mendukungnya secara konsisten.

var cssId = 'myCss';  // you could encode the css path itself to generate id..
if (!document.getElementById(cssId))
{
    var head  = document.getElementsByTagName('head')[0];
    var link  = document.createElement('link');
    link.id   = cssId;
    link.rel  = 'stylesheet';
    link.type = 'text/css';
    link.href = 'http://website.com/css/stylesheet.css';
    link.media = 'all';
    head.appendChild(link);
}

Contoh ini memeriksa apakah CSS sudah ditambahkan sehingga hanya menambahkannya sekali.

Masukkan kode itu ke file javascript, minta pengguna akhir cukup memasukkan javascript, dan pastikan path CSS absolut sehingga dimuat dari server Anda.

VanillaJS

Berikut adalah contoh yang menggunakan JavaScript biasa untuk menyuntikkan tautan CSS ke headelemen berdasarkan bagian nama file URL:

<script type="text/javascript">
var file = location.pathname.split( "/" ).pop();

var link = document.createElement( "link" );
link.href = file.substr( 0, file.lastIndexOf( "." ) ) + ".css";
link.type = "text/css";
link.rel = "stylesheet";
link.media = "screen,print";

document.getElementsByTagName( "head" )[0].appendChild( link );
</script>

Masukkan kode tepat sebelum headtag penutup dan CSS akan dimuat sebelum halaman diberikan. Menggunakan .jsfile JavaScript ( ) eksternal akan menyebabkan Flash konten tanpa gaya ( FOUC ) muncul.

card100
sumber
6
Bagaimana dengan menjalankan callback setelah file CSS dimuat?
jchook
1
Ini cukup rumit untuk dilakukan dengan andal. Pustaka Javascript populer sekarang biasanya memiliki beberapa bentuk memuat javascript dan stylesheet dengan panggilan balik. Sebagai contoh, lihat YUI Get .
9
mungkin akan lebih baik untuk menggunakan karakter yang berbeda dari $ untuk pintasan dokumen, karena dapat mengganggu jQuery dengan mudah (seperti dalam kasus saya);)
Zathrus Writer
2
@jonnybojangles Menggunakan jQuery.noConflict berarti mengganti nama semua referensi Anda ke jQuery menjadi $. Akan jauh lebih sederhana hanya dengan menggunakan nama variabel yang berbeda untuk loader CSS.
tommypyatt
2
@ jchook Saya bisa melampirkan panggilan balik dengan menambahkan link.onload = function(){ ... }sebelum menambahkan
Lounge9
74

Jika Anda menggunakan jquery:

$('head').append('<link rel="stylesheet" type="text/css" href="style.css">');
BoumTAC
sumber
1
ini hanya bekerja jika stylesheet disuntikkan sebelum pageload kan? Ketika saya menjalankan perintah ini di dalam konsol pada halaman yang dimuat dengan file css yang saya host di dropbox itu tidak akan berfungsi. Tahu bagaimana saya bisa membuat ini bekerja:$('head').append('<link rel="stylesheet" type="text/css" href="https://dl.dropboxusercontent.com/s/ep1nzckmvgjq7jr/remove_transitions_from_page.css">');
thomas
50

Saya kira sesuatu seperti script ini akan lakukan:

<script type="text/javascript" src="/js/styles.js"></script>

File JS ini berisi pernyataan berikut:

if (!document.getElementById) document.write('<link rel="stylesheet" type="text/css" href="https://stackoverflow.com/css/versions4.css">');

Alamat javascript dan css harus mutlak jika mereka merujuk ke situs Anda.

Banyak teknik impor CSS dibahas dalam artikel "Katakan tidak pada peretasan CSS dengan teknik percabangan" ini.

Tetapi artikel "Menggunakan JavaScript untuk menambahkan secara dinamis Portlet CSS stylesheet" juga menyebutkan kemungkinan CreateStyleSheet (metode kepemilikan untuk IE):

<script type="text/javascript">
//<![CDATA[
if(document.createStyleSheet) {
  document.createStyleSheet('http://server/stylesheet.css');
}
else {
  var styles = "@import url(' http://server/stylesheet.css ');";
  var newSS=document.createElement('link');
  newSS.rel='stylesheet';
  newSS.href='data:text/css,'+escape(styles);
  document.getElementsByTagName("head")[0].appendChild(newSS);
}
//]]>
VONC
sumber
inilah yang saya datangi untuk menambahkan document.createStyleSheet()ke browser yang tidak memilikinya: stackoverflow.com/questions/524696/…
Christoph
1
Tidak yakin persis dalam hal apa, tetapi dalam beberapa kasus, document.writetidak disarankan karena menimpa seluruh tubuh situs web Anda.
Eduard Luca
@VonC, Apakah ada fungsi untuk langsung mendapatkan <style>elemen alih-alih mengasumsikan itu anak pertama <head>via ("head")[0]?
Pacerier
@Pacerier Saya yakin Anda akan menemukan hal itu dibahas di groups.google.com/forum/#!topic/prototype-scriptaculous/… . Itu akan menjadi misalnya:var style = document.getElementsByTagName("style")[0];
VonC
20

Element.insertAdjacentHTML memiliki dukungan browser yang sangat baik, dan dapat menambahkan stylesheet dalam satu baris.

document.getElementsByTagName("head")[0].insertAdjacentHTML(
    "beforeend",
    "<link rel=\"stylesheet\" href=\"path/to/style.css\" />");
dangowans
sumber
12

Jika Anda ingin tahu (atau menunggu) sampai gaya itu sendiri dimuat ini berfungsi:

// this will work in IE 10, 11 and Safari/Chrome/Firefox/Edge
// add ES6 poly-fill for the Promise, if needed (or rewrite to use a callback)

let fetchStyle = function(url) {
  return new Promise((resolve, reject) => {
    let link = document.createElement('link');
    link.type = 'text/css';
    link.rel = 'stylesheet';
    link.onload = function() { resolve(); console.log('style has loaded'); };
    link.href = url;

    let headScript = document.querySelector('script');
    headScript.parentNode.insertBefore(link, headScript);
  });
};
sandstrom
sumber
bagaimana cara saya menggunakan ini
Raj Sharma
Anda akan melakukan fetchStyle (url) .then (function () {stuff goes here}) membaca janji
Ben Taliadoros
8

Saya tahu ini adalah utas yang cukup lama tetapi inilah 5 sen saya.

Ada cara lain untuk melakukan ini tergantung pada apa kebutuhan Anda.

Saya memiliki kasus di mana saya ingin file css aktif hanya sebentar. Seperti css switching. Aktifkan css dan kemudian setelah acara lain matikan.

Alih-alih memuat css secara dinamis dan kemudian menghapusnya Anda dapat menambahkan Kelas / id di depan semua elemen di css baru dan kemudian hanya beralih kelas / id dari simpul dasar css Anda (seperti tag tubuh).

Anda akan dengan solusi ini memiliki lebih banyak file css pada awalnya dimuat tetapi Anda memiliki cara yang lebih dinamis untuk beralih tata letak css.

JohanSellberg
sumber
7

Di peramban modern Anda dapat menggunakan promiseseperti ini. Buat fungsi loader dengan janji di dalamnya:

function LoadCSS( cssURL ) {

    // 'cssURL' is the stylesheet's URL, i.e. /css/styles.css

    return new Promise( function( resolve, reject ) {

        var link = document.createElement( 'link' );

        link.rel  = 'stylesheet';

        link.href = cssURL;

        document.head.appendChild( link );

        link.onload = function() { 

            resolve(); 

            console.log( 'CSS has loaded!' ); 
        };
    } );
}

Maka jelas Anda ingin sesuatu dilakukan setelah CSS dimuat. Anda dapat memanggil fungsi yang perlu dijalankan setelah CSS dimuat seperti ini:

LoadCSS( 'css/styles.css' ).then( function() {

    console.log( 'Another function is triggered after CSS had been loaded.' );

    return DoAfterCSSHasLoaded();
} );

Tautan yang berguna jika Anda ingin memahami cara kerjanya secara mendalam:

Dokumen resmi tentang janji

Panduan yang berguna untuk janji-janji

Video intro yang bagus tentang janji

Arthur Tarasov
sumber
6

Gunakan kode ini:

var element = document.createElement("link");
element.setAttribute("rel", "stylesheet");
element.setAttribute("type", "text/css");
element.setAttribute("href", "external.css");
document.getElementsByTagName("head")[0].appendChild(element);
Gaurav Tripathi
sumber
4

Inilah cara dengan metode pembuatan elemen jQuery (preferensi saya) dan dengan panggilan balik onLoad:

var css = $("<link>", {
  "rel" : "stylesheet",
  "type" :  "text/css",
  "href" : "style.css"
})[0];

css.onload = function(){
  console.log("CSS IN IFRAME LOADED");
};

document
  .getElementsByTagName("head")[0]
  .appendChild(css);
Lounge9
sumber
3

The perpustakaan YUI mungkin apa yang Anda cari. Ini juga mendukung pemuatan lintas domain.

Jika Anda menggunakan jquery, plugin ini melakukan hal yang sama.

anand.trex
sumber
2

Di bawah ini adalah kode lengkap yang digunakan untuk memuat JS dan / atau CSS

function loadScript(directory, files){
  var head = document.getElementsByTagName("head")[0]
  var done = false
  var extension = '.js'
  for (var file of files){ 
    var path = directory + file + extension 
    var script = document.createElement("script")
    script.src = path        
    script.type = "text/javascript"
    script.onload = script.onreadystatechange = function() {
        if ( !done && (!this.readyState ||
            this.readyState == "loaded" || this.readyState == "complete") ) {
            done = true
            script.onload = script.onreadystatechange = null   // cleans up a little memory:
            head.removeChild(script)  // to avoid douple loading
        }
  };
  head.appendChild(script) 
  done = false
 }
}

function loadStyle(directory, files){
  var head = document.getElementsByTagName("head")[0]
  var extension = '.css'
  for (var file of files){ 
   var path = directory + file + extension 
   var link = document.createElement("link")
   link.href = path        
   link.type = "text/css"
   link.rel = "stylesheet" 
   head.appendChild(link) 
 }
}

(() => loadScript('libraries/', ['listen','functions', 'speak', 'commands', 'wsBrowser', 'main'])) ();
(() => loadScript('scripts/', ['index'])) ();

(() => loadStyle('styles/', ['index'])) ();
Hasan A Yousef
sumber
1

Saya ingin berbagi satu cara lagi untuk memuat tidak hanya css tetapi semua aset (js, css, gambar) dan menangani acara onload untuk banyak file. Ini async-assets-loader. Lihat contoh di bawah ini:

<script src="https://unpkg.com/async-assets-loader"></script>
<script>
var jsfile = "https://code.jquery.com/jquery-3.4.1.min.js";
var cssfile = "https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css";
var imgfile = "https://logos.keycdn.com/keycdn-logo-black.png";
var assetsLoader = new asyncAssetsLoader();
assetsLoader.load([
      {uri: jsfile, type: "script"},
      {uri: cssfile, type: "style"},
      {uri: imgfile, type: "img"}
    ], function () {
      console.log("Assets are loaded");
      console.log("Img width: " + assetsLoader.getLoadedTags()[imgfile].width);
    });
</script> 

Menurut async-aset-loader docs

v.babak
sumber
0
var fileref = document.createElement("link")
fileref.setAttribute("rel", "stylesheet")
fileref.setAttribute("type", "text/css")
fileref.setAttribute("th:href", "@{/filepath}")
fileref.setAttribute("href", "/filepath")

Saya menggunakan thymeleaf dan ini berfungsi dengan baik. Terima kasih

ekoindra0912
sumber
Apa gunanya menambahkan th:hrefatribut di sisi klien? Itu tidak akan diproses oleh Thymeleaf jadi sepertinya berlebihan di sini.
Slava Semushin