Як завантажити файли CSS за допомогою Javascript?


316

Чи можливо імпортувати таблиці стилів css на сторінку html за допомогою Javascript? Якщо так, то як це зробити?

PS На моєму веб-сайті розміщується javascript, але я хочу, щоб користувачі могли розмістити <head>тег свого веб-сайту, і він повинен мати можливість імпортувати файл css, розміщений на моєму сервері, на поточну веб-сторінку. (на моєму сервері розміститься і файл css, і файл javascript).


Існує також питання про JQuery stackoverflow.com/questions/2685614 / ...
jcubic

Відповіді:


416

Ось "стара школа" спосіб це зробити, який, сподіваємось, працює у всіх браузерах. Теоретично, ви б, setAttributeна жаль, використовували IE6, не підтримує його послідовно.

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

Цей приклад перевіряє, чи CSS вже додано, тому він додає його лише один раз.

Помістіть цей код у файл javascript, а кінцевий користувач просто включить javascript і переконайтеся, що шлях CSS є абсолютним, щоб він завантажувався з ваших серверів.

VanillaJS

Ось приклад, який використовує звичайний JavaScript для введення CSS-посилання в headелемент на основі частини імені файлу 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>

Вставте код безпосередньо перед закриваючим headтегом, і CSS буде завантажений до того, як сторінка буде надана. Використання зовнішнього .jsфайлу JavaScript ( ) призведе до появи спалаху нестилізованого вмісту ( FOUC ).


6
Що з запуском зворотного дзвінка після завантаження файлу CSS?
jchook

1
Це досить складно зробити надійно. У популярних бібліотеках Javascript зараз зазвичай є певна форма завантаження javascript та таблиць стилів із зворотним дзвоном. Як приклад, див. YUI Get .

9
можливо, було б краще використовувати інший символ, ніж $ для ярлика документа, оскільки він може легко втручатися в jQuery (як у моєму випадку);)
Zathrus Writer

2
@jonnybojangles Використання jQuery.noConflict означатиме перейменування всіх ваших посилань на jQuery як $. Набагато простіше було б просто використовувати іншу назву змінної для завантажувача CSS.
tommypyatt

2
@jchook Мені вдалося вкласти зворотний дзвінок, додавши його link.onload = function(){ ... }перед додаванням
Lounge9

74

Якщо ви використовуєте jquery:

$('head').append('<link rel="stylesheet" type="text/css" href="style.css">');

1
це працює лише в тому випадку, якщо таблиця стилів вводиться перед завантаженням сторінки правильно? Коли я запускаю цю команду всередині консолі на завантаженій сторінці з файлом css, який я розмістив у Dropbox, вона не працюватиме. Будь-яка ідея, як я можу зробити цю роботу:$('head').append('<link rel="stylesheet" type="text/css" href="https://dl.dropboxusercontent.com/s/ep1nzckmvgjq7jr/remove_transitions_from_page.css">');
thomas

50

Я здогадуюсь щось подібне до цього сценарію:

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

Цей файл JS містить таке твердження:

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

Адреса javascript та css повинна бути абсолютною, якщо вони стосуватимуться вашого сайту.

Багато статей імпорту CSS обговорюються в цій статті "Не кажіть хакам CSS методами розгалуження" .

Але стаття "Використання JavaScript для динамічного додавання таблиць стилів портлетів CSS" згадує також можливість CreateStyleSheet (власний метод для 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);
}
//]]>

ось що я придумав додати document.createStyleSheet()до браузерів, у яких його немає: stackoverflow.com/questions/524696/…
Крістоф

1
Не точно знаєте, у якому випадку, але в деяких випадках, document.writeне рекомендується, оскільки це переписує все тіло вашого веб-сайту.
Едуард Лука

@VonC, Чи є функція безпосередньо отримати <style>елемент, а не вважати, що він є першим дочкою <head>через ("head")[0]?
Пейс’єр

@Pacerier Я вважаю, що ви знайдете те, що обговорювалося в groups.google.com/forum/#!topic/prototype-scriptaculous/… . Це було б, наприклад:var style = document.getElementsByTagName("style")[0];
VonC

20

Element.insertAdjacentHTML має дуже гарну підтримку браузера і може додати таблицю стилів в одному рядку.

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

12

Якщо ви хочете знати (або чекати), поки сам стиль завантажиться, це працює:

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

як я цим користуюся
Радж Шарма

Ви зробили б fetchStyle (url) .then (функція ({{сюди йде тут}) читайте на обіцянках
Бен Таліадорос

8

Я знаю, що це досить стара нитка, але ось мої 5 копійок.

Є ще один спосіб зробити це залежно від ваших потреб.

У мене є випадок, коли я хочу, щоб файл css був активним лише деякий час. Як перемикання css. Активуйте css, а потім після іншої події деактивуйте його.

Замість того, щоб завантажувати css динамічно, а потім видаляти його, ви можете додати Class / id перед усіма елементами нового css, а потім просто переключити цей клас / id базового вузла вашого css (як тег body).

У цьому рішенні ви б спочатку завантажили більше файлів css, але у вас є більш динамічний спосіб перемикання макетів css.


7

У сучасному браузері ви можете користуватися promiseтаким. Створіть функцію завантажувача з обіцянкою:

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

Тоді, очевидно, ви хочете щось зробити після завантаження CSS. Ви можете викликати функцію, яку потрібно запустити після завантаження CSS:

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

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

    return DoAfterCSSHasLoaded();
} );

Корисні посилання, якщо ви хочете глибоко зрозуміти, як це працює:

Офіційні документи про обіцянки

Корисний посібник для обіцянок

Чудове вступне відео про обіцянки


6

Використовуйте цей код:

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

4

Існує загальний плагін jquery, який завантажує файли css та JS синхронізувати та асистувати на вимогу. Він також відстежує те, що вже завантажено :) див. Http://code.google.com/p/rloader/


4

Ось спосіб із методом створення елементів jQuery (моє вподобання) та із зворотним викликом 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);

3

Бібліотека YUI може бути тим, що ви шукаєте. Він також підтримує міждоменне завантаження.

Якщо ви використовуєте jquery, цей плагін робить те саме.



2

Нижче повний код, що використовується для завантаження JS та / або 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'])) ();

1

Я хотів би поділитися ще одним способом завантаження не лише css, але й усіх активів (js, css, images) та обробляти події onload для купки файлів. Це async-assets-loader. Дивіться приклад нижче:

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

За асинхронним активів-навантажувачем документи


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

Я використовую чебрець, і це прекрасно. Дякую


Який сенс додати th:hrefатрибут на стороні клієнта? Він не обробить Чебрець, тому це здається зайвим.
Слава Семушин
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.