web-dev-qa-db-fra.com

Comment créer dynamiquement une classe CSS en JavaScript et l'appliquer?

J'ai besoin de créer dynamiquement une classe de feuille de style CSS en JavaScript et de l'assigner à des éléments HTML tels que - div, table, span, tr, etc., et à certains contrôles tels qu'asp: Textbox, Dropdownlist et datalist.

C'est possible?

Ce serait bien avec un échantillon.

252
Himadri

Bien que je ne sache pas pourquoi vous voulez créer des classes CSS avec JavaScript, voici une option:

var style = document.createElement('style');
style.type = 'text/css';
style.innerHTML = '.cssClass { color: #F00; }';
document.getElementsByTagName('head')[0].appendChild(style);

document.getElementById('someElementId').className = 'cssClass';
343
I.devries

Trouvé une meilleure solution, qui fonctionne sur tous les navigateurs.
Utilise document.styleSheet pour ajouter ou remplacer des règles. La réponse acceptée est courte et pratique, mais cela fonctionne avec IE8 et avec moins. 

function createCSSSelector (selector, style) {
  if (!document.styleSheets) return;
  if (document.getElementsByTagName('head').length == 0) return;

  var styleSheet,mediaType;

  if (document.styleSheets.length > 0) {
    for (var i = 0, l = document.styleSheets.length; i < l; i++) {
      if (document.styleSheets[i].disabled) 
        continue;
      var media = document.styleSheets[i].media;
      mediaType = typeof media;

      if (mediaType === 'string') {
        if (media === '' || (media.indexOf('screen') !== -1)) {
          styleSheet = document.styleSheets[i];
        }
      }
      else if (mediaType=='object') {
        if (media.mediaText === '' || (media.mediaText.indexOf('screen') !== -1)) {
          styleSheet = document.styleSheets[i];
        }
      }

      if (typeof styleSheet !== 'undefined') 
        break;
    }
  }

  if (typeof styleSheet === 'undefined') {
    var styleSheetElement = document.createElement('style');
    styleSheetElement.type = 'text/css';
    document.getElementsByTagName('head')[0].appendChild(styleSheetElement);

    for (i = 0; i < document.styleSheets.length; i++) {
      if (document.styleSheets[i].disabled) {
        continue;
      }
      styleSheet = document.styleSheets[i];
    }

    mediaType = typeof styleSheet.media;
  }

  if (mediaType === 'string') {
    for (var i = 0, l = styleSheet.rules.length; i < l; i++) {
      if(styleSheet.rules[i].selectorText && styleSheet.rules[i].selectorText.toLowerCase()==selector.toLowerCase()) {
        styleSheet.rules[i].style.cssText = style;
        return;
      }
    }
    styleSheet.addRule(selector,style);
  }
  else if (mediaType === 'object') {
    var styleSheetLength = (styleSheet.cssRules) ? styleSheet.cssRules.length : 0;
    for (var i = 0; i < styleSheetLength; i++) {
      if (styleSheet.cssRules[i].selectorText && styleSheet.cssRules[i].selectorText.toLowerCase() == selector.toLowerCase()) {
        styleSheet.cssRules[i].style.cssText = style;
        return;
      }
    }
    styleSheet.insertRule(selector + '{' + style + '}', styleSheetLength);
  }
}

La fonction est utilisée comme suit. 

createCSSSelector('.mycssclass', 'display:none');

Notez que même si le nom de la fonction est createClass, il crée en réalité un sélecteur. Donc n'oubliez pas d'ajouter. (Point) avant le nom de votre classe . Inutile de mentionner que vous pouvez créer d'autres sélecteurs avec cette fonction 

104
Vishwanath

Réponse courte, ceci est compatible "sur tous les navigateurs" (en particulier, IE8/7):

function createClass(name,rules){
    var style = document.createElement('style');
    style.type = 'text/css';
    document.getElementsByTagName('head')[0].appendChild(style);
    if(!(style.sheet||{}).insertRule) 
        (style.styleSheet || style.sheet).addRule(name, rules);
    else
        style.sheet.insertRule(name+"{"+rules+"}",0);
}
createClass('.whatever',"background-color: green;");

Et ce dernier bit applique la classe à un élément:

function applyClass(name,element,doRemove){
    if(typeof element.valueOf() == "string"){
        element = document.getElementById(element);
    }
    if(!element) return;
    if(doRemove){
        element.className = element.className.replace(new RegExp("\\b" + name + "\\b","g"));
    }else{      
        element.className = element.className + " " + name;
    }
}

Voici également une petite page de test: https://Gist.github.com/shadybones/9816763

Le facteur clé est le fait que les éléments de style ont une propriété "styleSheet"/"sheet" que vous pouvez utiliser pour ajouter/supprimer des règles.

24
shadybones

Un plugin jQuery léger permet de générer des déclarations CSS: jQuery-injectCSS

En fait, il utilise JSS (CSS décrit par JSON), mais il est assez facile à manipuler pour générer des feuilles de style CSS dynamiques.

$.injectCSS({
    "#test": {
        height: 123
    }
});
14
Yako

YUI a de loin le meilleur utilitaire de stylesheet que j’ai déjà vu. Je vous encourage à vérifier, mais voici un avant-goût:

// style element or locally sourced link element
var sheet = YAHOO.util.StyleSheet(YAHOO.util.Selector.query('style',null,true));

sheet = YAHOO.util.StyleSheet(YAHOO.util.Dom.get('local'));


// OR the id of a style element or locally sourced link element
sheet = YAHOO.util.StyleSheet('local');


// OR string of css text
var css = ".moduleX .alert { background: #fcc; font-weight: bold; } " +
          ".moduleX .warn  { background: #eec; } " +
          ".hide_messages .moduleX .alert, " +
          ".hide_messages .moduleX .warn { display: none; }";

sheet = new YAHOO.util.StyleSheet(css);

Il existe évidemment d'autres moyens beaucoup plus simples de changer de style à la volée, tels que ceux suggérés ici. S'ils ont un sens pour votre problème, ils le seraient peut-être mieux, mais il y a certainement des raisons pour lesquelles la modification de CSS est une meilleure solution. Le cas le plus évident est lorsque vous devez modifier un grand nombre d'éléments. L'autre cas important est si vous avez besoin que vos changements de style impliquent la cascade. Utiliser le dom pour modifier un élément aura toujours une priorité plus élevée. C'est l'approche sledgehammer et équivaut à utiliser l'attribut style directement sur l'élément html. Ce n'est pas toujours l'effet désiré.

7
Russell Leggett

A partir de IE 9. Vous pouvez maintenant charger un fichier texte et définir une propriété style.innerHTML. En gros, vous pouvez maintenant charger un fichier css via ajax (et obtenir le rappel) et ensuite définir le texte à l'intérieur d'une balise de style comme ceci.

Cela fonctionne dans les autres navigateurs, vous ne savez pas à quelle distance en arrière. Mais tant que vous n'avez pas besoin de supporter IE8, cela fonctionnera.

// RESULT: doesn't work in IE8 and below. Works in IE9 and other browsers.
$(document).ready(function() {
    // we want to load the css as a text file and append it with a style.
    $.ajax({
        url:'myCss.css',
        success: function(result) {
            var s = document.createElement('style');
            s.setAttribute('type', 'text/css');
            s.innerHTML = result;
            document.getElementsByTagName("head")[0].appendChild(s);
        },
        fail: function() {
            alert('fail');
        }
    })
});

et alors vous pouvez l'avoir tirer un fichier externe comme le myCss.css

.myClass { background:#F00; }
5
Codeguy

https://jsfiddle.net/xk6Ut/256/

Une option pour créer et mettre à jour dynamiquement une classe CSS en JavaScript:

  • Utiliser un élément de style pour créer une section CSS 
  • Utiliser un identifiant pour l'élément de style afin de pouvoir mettre à jour le CSS
    classe

.....

function writeStyles(styleName, cssText) {
    var styleElement = document.getElementById(styleName);
    if (styleElement) 
             document.getElementsByTagName('head')[0].removeChild(
        styleElement);
    styleElement = document.createElement('style');
    styleElement.type = 'text/css';
    styleElement.id = styleName;
    styleElement.innerHTML = cssText;
    document.getElementsByTagName('head')[0].appendChild(styleElement);
}

... 

    var cssText = '.testDIV{ height:' + height + 'px !important; }';
    writeStyles('styles_js', cssText)
3
Razan Paul

Voici la solution de Vishwanath légèrement réécrite avec des commentaires:

function setStyle(cssRules, aSelector, aStyle){
    for(var i = 0; i < cssRules.length; i++) {
        if(cssRules[i].selectorText && cssRules[i].selectorText.toLowerCase() == aSelector.toLowerCase()) {
            cssRules[i].style.cssText = aStyle;
            return true;
        }
    }
    return false;
}

function createCSSSelector(selector, style) {
    var doc = document;
    var allSS = doc.styleSheets;
    if(!allSS) return;

    var headElts = doc.getElementsByTagName("head");
    if(!headElts.length) return;

    var styleSheet, media, iSS = allSS.length; // scope is global in a function
    /* 1. search for media == "screen" */
    while(iSS){ --iSS;
        if(allSS[iSS].disabled) continue; /* dont take into account the disabled stylesheets */
        media = allSS[iSS].media;
        if(typeof media == "object")
            media = media.mediaText;
        if(media == "" || media=='all' || media.indexOf("screen") != -1){
            styleSheet = allSS[iSS];
            iSS = -1;   // indication that media=="screen" was found (if not, then iSS==0)
            break;
        }
    }

    /* 2. if not found, create one */
    if(iSS != -1) {
        var styleSheetElement = doc.createElement("style");
        styleSheetElement.type = "text/css";
        headElts[0].appendChild(styleSheetElement);
        styleSheet = doc.styleSheets[allSS.length]; /* take the new stylesheet to add the selector and the style */
    }

    /* 3. add the selector and style */
    switch (typeof styleSheet.media) {
    case "string":
        if(!setStyle(styleSheet.rules, selector, style));
            styleSheet.addRule(selector, style);
        break;
    case "object":
        if(!setStyle(styleSheet.cssRules, selector, style));
            styleSheet.insertRule(selector + "{" + style + "}", styleSheet.cssRules.length);
        break;
    }
3
user3705905

Un projet intéressant qui pourrait vous aider dans votre tâche est JSS .

JSS est une meilleure abstraction sur CSS. Il utilise JavaScript comme langage décrire les styles de manière déclarative et maintenable. C'est un haut performance JS au compilateur CSS qui fonctionne au moment de l’exécution dans les navigateurs et côté serveur.

La bibliothèque JSS vous permet d’injecter dans la section DOM/head à l’aide de la fonction .attach().

Repl version en ligne pour évaluation.

En outre informations sur JSS .

Un exemple:

// Use plugins.
jss.use(camelCase())

// Create your style.
const style = {
  myButton: {
    color: 'green'
  }
}

// Compile styles, apply plugins.
const sheet = jss.createStyleSheet(style)

// If you want to render on the client, insert it into DOM.
sheet.attach()
2
GibboK
function createCSSClass(selector, style, hoverstyle) 
{
    if (!document.styleSheets) 
    {
        return;
    }

    if (document.getElementsByTagName("head").length == 0) 
    {

        return;
    }
    var stylesheet;
    var mediaType;
    if (document.styleSheets.length > 0) 
    {
        for (i = 0; i < document.styleSheets.length; i++) 
        {
            if (document.styleSheets[i].disabled) 
            {
                continue;
            }
            var media = document.styleSheets[i].media;
            mediaType = typeof media;

            if (mediaType == "string") 
            {
                if (media == "" || (media.indexOf("screen") != -1)) 
                {
                    styleSheet = document.styleSheets[i];
                }
            } 
            else if (mediaType == "object") 
            {
                if (media.mediaText == "" || (media.mediaText.indexOf("screen") != -1)) 
                {
                    styleSheet = document.styleSheets[i];
                }
            }

            if (typeof styleSheet != "undefined") 
            {
                break;
            }
        }
    }

    if (typeof styleSheet == "undefined") {
        var styleSheetElement = document.createElement("style");
        styleSheetElement.type = "text/css";
        document.getElementsByTagName("head")[0].appendChild(styleSheetElement);
        for (i = 0; i < document.styleSheets.length; i++) {
            if (document.styleSheets[i].disabled) {
                continue;
            }
            styleSheet = document.styleSheets[i];
        }

        var media = styleSheet.media;
        mediaType = typeof media;
    }

    if (mediaType == "string") {
        for (i = 0; i < styleSheet.rules.length; i++) 
        {
            if (styleSheet.rules[i].selectorText.toLowerCase() == selector.toLowerCase()) 
            {
                styleSheet.rules[i].style.cssText = style;
                return;
            }
        }

        styleSheet.addRule(selector, style);
    }
    else if (mediaType == "object") 
    {
        for (i = 0; i < styleSheet.cssRules.length; i++) 
        {
            if (styleSheet.cssRules[i].selectorText.toLowerCase() == selector.toLowerCase()) 
            {
                styleSheet.cssRules[i].style.cssText = style;
                return;
            }
        }

        if (hoverstyle != null) 
        {
            styleSheet.insertRule(selector + "{" + style + "}", 0);
            styleSheet.insertRule(selector + ":hover{" + hoverstyle + "}", 1);
        }
        else 
        {
            styleSheet.insertRule(selector + "{" + style + "}", 0);
        }
    }
}





createCSSClass(".modalPopup  .header",
                                 " background-color: " + lightest + ";" +
                                  "height: 10%;" +
                                  "color: White;" +
                                  "line-height: 30px;" +
                                  "text-align: center;" +
                                  " width: 100%;" +
                                  "font-weight: bold; ", null);
1
tushar

En utilisant google fermeture:

vous pouvez simplement utiliser le module ccsom:

goog.require('goog.cssom');
var css_node = goog.cssom.addCssText('.cssClass { color: #F00; }');

Le code javascript tente d’être croisé entre les navigateurs lorsqu’on place le nœud css dans la tête du document.

1
Joe Heyming

Examinez les réponses et il manque le plus évident et le plus simple: utilisez document.write() pour écrire le bloc CSS dont vous avez besoin.

Voici un exemple (voyez-le sur codepen: http://codepen.io/ssh33/pen/zGjWga ): 

<style>
   @import url(http://fonts.googleapis.com/css?family=Open+Sans:800);
   .d, body{ font: 3vw 'Open Sans'; padding-top: 1em; }
   .d {
       text-align: center; background: #aaf;
       margin: auto; color: #fff; overflow: hidden; 
       width: 12em; height: 5em;
   }
</style>

<script>
   function w(s){document.write(s)}
   w("<style>.long-shadow { text-shadow: ");
   for(var i=0; i<449; i++) {
      if(i!= 0) w(","); w(i+"px "+i+"px #444");
   }
   w(";}</style>");
</script> 

<div class="d">
    <div class="long-shadow">Long Shadow<br> Short Code</div>
</div>
1
Stack

Je cherchais certaines des réponses ici, et je ne trouvais rien qui ajoute automatiquement une nouvelle feuille de style s'il n'y en avait pas. Sinon, je modifie simplement une feuille existante qui contient déjà le style requis. devrait fonctionner sur tous les navigateurs, même s’il n’a pas été testé, utilise addRule et que seul le JavaScript natif de base suffit, laissez-moi savoir si cela fonctionne):

function myCSS(data) {
    var head = document.head || document.getElementsByTagName("head")[0];
    if(head) {
        if(data && data.constructor == Object) {
            for(var k in data) {
                var selector = k;
                var rules = data[k];

                var allSheets = document.styleSheets;
                var cur = null;

                var indexOfPossibleRule = null,
                    indexOfSheet = null;
                for(var i = 0; i < allSheets.length; i++) {
                    indexOfPossibleRule = findIndexOfObjPropInArray("selectorText",selector,allSheets[i].cssRules);
                    if(indexOfPossibleRule != null) {
                        indexOfSheet = i;
                        break;
                    }
                }

                var ruleToEdit = null;
                if(indexOfSheet != null) {

                    ruleToEdit = allSheets[indexOfSheet].cssRules[indexOfPossibleRule];

                } else {
                    cur = document.createElement("style");
                    cur.type =  "text/css";
                    head.appendChild(cur);
                    cur.sheet.addRule(selector,"");
                    ruleToEdit = cur.sheet.cssRules[0];
                    console.log("NOPE, but here's a new one:", cur);
                }
                applyCustomCSSruleListToExistingCSSruleList(rules, ruleToEdit, (err) => {
                    if(err) {
                        console.log(err);
                    } else {
                        console.log("successfully added ", rules, " to ", ruleToEdit);
                    }
                });
            }
        } else {
            console.log("provide one paramter as an object containing the cssStyles, like: {\"#myID\":{position:\"absolute\"}, \".myClass\":{background:\"red\"}}, etc...");
        }
    } else {
        console.log("run this after the page loads");
    }

};  

ensuite, ajoutez simplement ces 2 fonctions d’aide dans la fonction ci-dessus ou ailleurs:

function applyCustomCSSruleListToExistingCSSruleList(customRuleList, existingRuleList, cb) {
    var err = null;
    console.log("trying to apply ", customRuleList, " to ", existingRuleList);
    if(customRuleList && customRuleList.constructor == Object && existingRuleList && existingRuleList.constructor == CSSStyleRule) {
        for(var k in customRuleList) {
            existingRuleList["style"][k] = customRuleList[k];
        }

    } else {
        err = ("provide first argument as an object containing the selectors for the keys, and the second argument is the CSSRuleList to modify");
    }
    if(cb) {
        cb(err);
    }
}

function findIndexOfObjPropInArray(objPropKey, objPropValue, arr) {
    var index = null;
    for(var i = 0; i < arr.length; i++) {
        if(arr[i][objPropKey] == objPropValue) {
            index = i;
            break;
        }
    }
    return index;
}

(Notez que dans les deux cas, j'utilise une boucle for à la place de .filter, car les classes de styles/règles CSS ont uniquement une propriété length et aucune méthode .filter.)

Puis l'appeler:

myCSS({
    "#coby": {
        position:"absolute",
        color:"blue"
    },
    ".myError": {
        padding:"4px",
        background:"salmon"
    }
})

Faites-moi savoir si cela fonctionne pour votre navigateur ou donne une erreur.

0
bluejayke

Au profit des chercheurs; Si vous utilisez jQuery, vous pouvez effectuer les opérations suivantes:

var currentOverride = $('#customoverridestyles');

if (currentOverride) {
 currentOverride.remove();
}

$('body').append("<style id=\"customoverridestyles\">body{background-color:pink;}</style>");

De toute évidence, vous pouvez modifier le css interne en ce que vous voulez.

Certaines personnes préfèrent le JavaScript pur, mais cela fonctionne et a été assez robuste pour écrire/écraser des styles de manière dynamique.

0
HockeyJ