Làm cách nào để tải lên các tệp CSS bằng Javascript?


316

Có thể nhập biểu định kiểu css vào trang html bằng Javascript không? Nếu vậy, làm thế nào nó có thể được thực hiện?

PS javascript sẽ được lưu trữ trên trang web của tôi, nhưng tôi muốn người dùng có thể đặt <head>thẻ của trang web của họ và nó có thể nhập tệp css được lưu trữ trên máy chủ của tôi vào trang web hiện tại. (cả tệp css và tệp javascript sẽ được lưu trữ trên máy chủ của tôi).


Ngoài ra còn có câu hỏi về jQuery stackoverflow.com/questions/2685614/ từ
jcubic

Câu trả lời:


416

Đây là cách làm "trường học cũ", hy vọng sẽ hoạt động trên tất cả các trình duyệt. Về lý thuyết, bạn sẽ setAttributekhông may sử dụng IE6 không hỗ trợ nó một cách nhất quán.

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

Ví dụ này kiểm tra xem CSS đã được thêm hay chưa, vì vậy nó chỉ thêm một lần.

Đặt mã đó vào tệp javascript, yêu cầu người dùng cuối chỉ cần bao gồm javascript và đảm bảo đường dẫn CSS là tuyệt đối để nó được tải từ máy chủ của bạn.

VanillaJS

Dưới đây là một ví dụ sử dụng JavaScript đơn giản để đưa liên kết CSS vào headphần tử dựa trên phần tên tệp của 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>

Chèn mã ngay trước headthẻ đóng và CSS sẽ được tải trước khi trang được hiển thị. Sử dụng .jstệp JavaScript ( ) bên ngoài sẽ khiến Flash có nội dung không được lọc ( FOUC ) xuất hiện.


6
Điều gì về việc chạy một cuộc gọi lại sau khi tệp CSS đã được tải?
jchook

1
Điều này là khá phức tạp để làm đáng tin cậy. Các thư viện Javascript phổ biến hiện nay thường có một số hình thức tải javascript và bảng định kiểu với một cuộc gọi lại. Ví dụ, xem YUI Get .

9
có lẽ sẽ tốt hơn nếu sử dụng một ký tự khác với $ cho phím tắt tài liệu, vì nó có thể can thiệp vào jQuery một cách dễ dàng (như trong trường hợp của tôi);)
Nhà văn Zathrus

2
@jonnybojangles Sử dụng jQuery.noConflict có nghĩa là đổi tên tất cả các tham chiếu của bạn thành jQuery thành $. Sẽ đơn giản hơn nhiều nếu chỉ sử dụng một tên biến khác cho trình tải CSS.
tommypyatt

2
@jchook Tôi đã có thể đính kèm một cuộc gọi lại bằng cách thêm link.onload = function(){ ... }trước khi nối thêm
Lounge9

74

Nếu bạn sử dụng jquery:

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

1
Điều này chỉ hoạt động nếu bản định kiểu được tiêm trước khi tải trang phải không? Khi tôi chạy lệnh này bên trong bàn điều khiển trên một trang được tải với tệp css mà tôi đã lưu trữ trên dropbox, nó sẽ không hoạt động. Mọi ý tưởng làm thế nào tôi có thể làm cho công việc này:$('head').append('<link rel="stylesheet" type="text/css" href="https://dl.dropboxusercontent.com/s/ep1nzckmvgjq7jr/remove_transitions_from_page.css">');
thomas

50

Tôi đoán một cái gì đó như kịch bản này sẽ làm:

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

Tệp JS này chứa câu lệnh sau:

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

Địa chỉ của javascript và css sẽ cần phải tuyệt đối nếu chúng được tham chiếu đến trang web của bạn.

Nhiều kỹ thuật nhập CSS được thảo luận trong bài viết "Nói không với các bản hack CSS với các kỹ thuật phân nhánh" này.

Nhưng bài viết "Sử dụng JavaScript để thêm động các biểu định kiểu CSS của Portlet" cũng đề cập đến khả năng CreatStyleSheet (phương thức độc quyền cho 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);
}
//]]>

Đây là những gì tôi đã đưa ra để thêm document.createStyleSheet()vào các trình duyệt không có nó: stackoverflow.com/questions/524696/ mẹo
Christoph

1
Không chắc chắn chính xác trong trường hợp nào, nhưng trong một số trường hợp, document.writekhông được đề xuất vì nó ghi đè lên toàn bộ trang web của bạn.
Eduard Luca

@VonC, Có chức năng trực tiếp lấy <style>phần tử thay vì cho rằng đó là đứa con đầu tiên của <head>thông qua ("head")[0]không?
Pacerier

@Pacerier Tôi tin rằng bạn sẽ tìm thấy điều đó được thảo luận trong nhóm.google.com/forum/# ! topic/prototype-scriptacificent/ . Đó là ví dụ:var style = document.getElementsByTagName("style")[0];
VonC

20

Element.insertAdjighborHTML có hỗ trợ trình duyệt rất tốt và có thể thêm biểu định kiểu trong một dòng.

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

12

Nếu bạn muốn biết (hoặc chờ) cho đến khi chính kiểu đó đã tải thì hoạt động này:

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

Làm thế nào để tôi sử dụng cái này
Raj Sharma

Bạn sẽ thực hiện fetchStyle (url) .then (function () {Stuff vào đây}) đọc các lời hứa
Ben Taliadoros

8

Tôi biết đây là một chủ đề khá cũ nhưng ở đây có 5 xu của tôi.

Có một cách khác để làm điều này tùy thuộc vào nhu cầu của bạn là gì.

Tôi có một trường hợp tôi muốn một tệp css chỉ hoạt động một lúc. Giống như chuyển đổi css. Kích hoạt css và sau đó sau một sự kiện khác làm hỏng nó.

Thay vì tải động css một cách linh hoạt và sau đó loại bỏ nó, bạn có thể thêm Class / id trước tất cả các thành phần trong css mới và sau đó chỉ cần chuyển lớp / id đó của nút cơ sở của css của bạn (như thẻ body).

Bạn sẽ với giải pháp này có nhiều tệp css được tải ban đầu nhưng bạn có cách chuyển đổi bố cục css linh hoạt hơn.


7

Trong một trình duyệt hiện đại, bạn có thể sử dụng promisenhư thế này. Tạo một hàm nạp với một lời hứa trong đó:

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

Sau đó, rõ ràng bạn muốn một cái gì đó được thực hiện sau khi CSS đã được tải. Bạn có thể gọi hàm cần chạy sau khi CSS được tải như thế này:

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

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

    return DoAfterCSSHasLoaded();
} );

Các liên kết hữu ích nếu bạn muốn hiểu sâu về cách thức hoạt động của nó:

Tài liệu chính thức về lời hứa

Hướng dẫn hữu ích cho những lời hứa

Một video giới thiệu tuyệt vời về những lời hứa


6

Sử dụng mã này:

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

Đây là một cách với phương thức tạo phần tử của jQuery (sở thích của tôi) và với hàm gọi lại 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

Các thư viện YUI có thể là những gì bạn đang tìm kiếm. Nó cũng hỗ trợ tải tên miền chéo.

Nếu bạn sử dụng jquery, plugin này cũng làm điều tương tự.



2

Bên dưới mã đầy đủ sử dụng để tải JS và / hoặc 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

Tôi muốn chia sẻ thêm một cách để tải không chỉ css mà tất cả các tài sản (js, css, hình ảnh) và xử lý sự kiện onload cho bó tệp. Đó là async-assets-loader. Xem ví dụ dưới đây:

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

Theo tài liệu trình tải async-property-loader


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

Tôi đang sử dụng thymeleaf và điều này hoạt động tốt. Cảm ơn


Điểm để thêm th:hrefthuộc tính ở phía khách hàng là gì? Nó sẽ không được xử lý bởi Thymeleaf nên có vẻ như dư thừa ở đây.
Slava Semushin
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.