Créer une règle / classe CSS avec jQuery au moment de l'exécution

192

Habituellement, j'ai un fichier CSS qui a la règle suivante:

#my-window {
    position: fixed;
    z-index: 102;
    display:none;
    top:50%;
    left:50%;
}

Comment éviter de créer un tel fichier CSS statique en ajoutant les informations CSS lors des actions d'exécution au corps, ou quelque chose de similaire? (en utilisant uniquement jQuery)

Je veux le définir une fois mais avec jQuery et l'utiliser plusieurs fois plus tard; c'est pourquoi je ne veux pas l'ajouter à chaque fois aux éléments spécifiques du DOM.

Je connais les fonctionnalités simples ( css("attr1", "value");), mais comment puis-je créer une règle CSS réutilisable complète?

stephan
la source

Réponses:

272

Vous pouvez créer un élément de style et l'insérer dans le DOM

$("<style type='text/css'> .redbold{ color:#f00; font-weight:bold;} </style>").appendTo("head");
$("<div/>").addClass("redbold").text("SOME NEW TEXT").appendTo("body");

testé sur Opera10 FF3.5 iE8 iE6

Taras Bulba
la source
L'essentiel est autosuffisant. Vous pouvez le créer localement et cela fonctionnera très bien. Lien direct vers le lien de téléchargement: gist.github.com/gists/714352/download
Daniel Ribeiro
Aucun problème. Parfois, il peut s'agir d'un bogue de version mineure de jQuery ou simplement d'une configuration incorrecte. Le problème avec les applications js est le suivant: si elles ne fonctionnent pas, elles ne fonctionnent tout simplement pas. Pas de pardon.
Daniel Ribeiro
1
Lève une erreur « Appel inattendu à la méthode ou à l'accès à la propriété » pour moi dans IE8. J'ai dû suivre cet article pour le faire fonctionner.
Brandon Boone
6
Il ne peut y avoir que 31 styles dans la page dans IE9- blogs.msdn.com/b/ieinternals/archive/2011/05/14/…
IvanH
1
Si ça ne marche pas. Essayez d'ajouter un style à body. ie$("<style>...</style>").appendTo("body");
inDream
120

Simplement

$("<style>")
    .prop("type", "text/css")
    .html("\
    #my-window {\
        position: fixed;\
        z-index: 102;\
        display:none;\
        top:50%;\
        left:50%;\
    }")
    .appendTo("head");

Vous avez remarqué les barres obliques arrière? Ils sont utilisés pour joindre des chaînes qui sont sur de nouvelles lignes. Les laisser de côté génère une erreur.

bogonko
la source
6
Ce. Devrait être la réponse acceptée. Cela répond en fait à la question.
Johannes Pille
2
Je suis d'accord avec @JohannesPille, c'est la vraie réponse!
bayu
ne fonctionne pas dans cordova ios. voulez-vous s'il vous plaît suggérer à ce sujet?
RamGrg
2
Assez efficace et simple. Une fois la nouvelle règle injectée dans l'en-tête, vous pouvez la récupérer n'importe où dans votre page, y compris depuis PHP.
Brice Coustillas
17

vous pouvez appliquer css à un objet. Vous pouvez donc définir votre objet dans votre javascript comme ceci:

var my_css_class = { backgroundColor : 'blue', color : '#fff' };

Et puis appliquez-le simplement à tous les éléments que vous souhaitez

$("#myelement").css(my_css_class);

C'est donc réutilisable. Dans quel but feriez-vous cela?

Yuval Karmi
la source
22
Je dirais que c'est une règle CSS et non une classe CSS.
hippietrail
17
Cette réponse est trompeuse. Le demandeur voulait créer une règle CSS au moment de l'exécution, et non définir le style d'un élément particulier sur une déclaration CSS constante (réutilisable).
Dan Dascalescu
4
Ce n'est pas tout à fait ce qu'ils ont demandé, mais c'est la bonne solution :) Remplir le dom avec des éléments <style> supplémentaires a une odeur de code désagréable
Kevin
3
Comment allez-vous supprimer ces règles appliquées lorsque vous en avez besoin, c'est possible avec d'autres solutions ...
Vishwanath
@Kevin - c'est peut-être le cas, mais il y a des moments où c'est exactement ce dont vous avez besoin. par exemple - lorsqu'un élément est recréé par un script ajax et que vous devez conserver une nouvelle règle de style.
billynoah
12

Vous pouvez utiliser insertRule si vous n'avez pas besoin de prendre en charge IE <9, selon dottoro . Il y a aussi un peu de code cross browser là-bas.

document.styleSheets[0].insertRule('#my-window {\
    position: fixed;\
    z-index: 102;\
    display:none;\
    top:50%;\
    left:50%;\
}', 0)
Sean
la source
9

Voici un plugin jquery qui vous permet d'injecter du CSS:

https://github.com/kajic/jquery-injectCSS

Exemple:

$.injectCSS({
    "#my-window": {
        "position": "fixed",
        "z-index": 102,
        "display": "none",
        "top": "50%",
        "left": "50%"
    }
});
Robert Kajic
la source
9

Ce n'est pas quelque chose de nouveau par rapport à certaines des autres réponses car il utilise le concept décrit ici et ici , mais je voulais utiliser une déclaration de style JSON:

function addCssRule(rule, css) {
  css = JSON.stringify(css).replace(/"/g, "").replace(/,/g, ";");
  $("<style>").prop("type", "text/css").html(rule + css).appendTo("head");
}

Usage:

addCssRule(".friend a, .parent a", {
  color: "green",
  "font-size": "20px"
});

Je ne sais pas si cela couvre toutes les fonctionnalités de CSS, mais jusqu'à présent, cela fonctionne pour moi. Si ce n'est pas le cas, considérez-le comme un point de départ pour vos propres besoins. :)

sjngm
la source
Pour plus de clarté, je suggérerais de nommer les paramètres selectoret body. Le remplacement de la virgule posera des problèmes lors de la spécification des polices ou de l'utilisation de rgb (), etc., mais dans l'ensemble, cette idée est bonne.
Palec
7

Si vous ne voulez pas coder en dur le CSS dans un bloc / fichier CSS, vous pouvez utiliser jQuery pour ajouter dynamiquement du CSS aux éléments HTML, aux ID et aux classes.

$(document).ready(function() {
  //Build your CSS.
  var body_tag_css = {
    "background-color": "#ddd",
    "font-weight": "",
    "color": "#000"
  }
  //Apply your CSS to the body tag.  You can enter any tag here, as
  //well as ID's and Classes.
  $("body").css(body_tag_css);
});
Mike Trpcic
la source
5
Cette réponse n'est pas tout à fait ce que le demandeur a demandé. Le demandeur voulait créer une règle CSS au moment de l'exécution, et non définir le style d'un élément particulier sur une déclaration CSS constante.
Dan Dascalescu
Je comprends, mais c'est une solution alternative, alors je l'ai fournie.
Mike Trpcic
2
@MikeTrpcic Le problème est qu'il y a aussi d'autres personnes qui recherchent cette solution - pour ajouter des règles css à une page - et votre réponse ne résout pas cela.
nate le
6

Notez que jQuery().css()cela ne change pas les règles de la feuille de style, cela change simplement le style de chaque élément correspondant.

Au lieu de cela, voici une fonction javascript que j'ai écrite pour modifier les règles de la feuille de style elles-mêmes.

    /**
     * Modify an existing stylesheet.
     * - sheetId - the id of the <link> or <style> element that defines the stylesheet to be changed
     * - selector - the id/class/element part of the rule.  e.g. "div", ".sectionTitle", "#chapter2"
     * - property - the CSS attribute to be changed.  e.g. "border", "font-size"
     * - value - the new value for the CSS attribute.  e.g. "2px solid blue", "14px"
     */
    function changeCSS(sheetId, selector, property, value){
        var s = document.getElementById(sheetId).sheet;
        var rules = s.cssRules || s.rules;
        for(var i = rules.length - 1, found = false; i >= 0 && !found; i--){
            var r = rules[i];
            if(r.selectorText == selector){
                r.style.setProperty(property, value);
                found = true;
            }
        }
        if(!found){
            s.insertRule(selector + '{' + property + ':' + value + ';}', rules.length);
        }
    }

Avantages:

  • Les styles peuvent être calculés dans un <head>script avant la création des éléments DOM et donc avant le premier rendu du document, évitant ainsi un rendu visuellement ennuyeux, puis calculer, puis re-rendre. Avec jQuery, vous devez attendre que les éléments DOM soient créés, puis les re-styliser et les restituer.
  • Les éléments qui sont ajoutés dynamiquement après le restyle verront automatiquement les nouveaux styles appliqués sans appel supplémentaire à jQuery(newElement).css()

Mises en garde:

  • Je l'ai utilisé sur Chrome et IE10. Je pense qu'il faudra peut-être une petite modification pour que cela fonctionne bien sur les anciennes versions d'IE. En particulier, les anciennes versions d'IE peuvent ne pas avoir été s.cssRulesdéfinies, elles reviendront donc à s.rulesce qui présente certaines particularités, telles que le comportement étrange / bogué lié aux sélecteurs délimités par des virgules, comme "body, p". Si vous évitez ceux-ci, vous pourriez être d'accord avec les anciennes versions d'IE sans modification, mais je ne l'ai pas encore testé.
  • Actuellement, les sélecteurs doivent correspondre exactement: utilisez des minuscules et soyez prudent avec les listes séparées par des virgules; l'ordre doit correspondre et ils doivent être au format, "first, second"c'est-à-dire que le délimiteur est une virgule suivie d'un espace.
  • On pourrait probablement passer un peu plus de temps dessus à essayer de détecter et de gérer intelligemment les sélecteurs qui se chevauchent, tels que ceux des listes délimitées par des virgules.
  • On pourrait également ajouter la prise en charge des requêtes multimédias et du !importantmodificateur sans trop de problèmes.

Si vous souhaitez apporter des améliorations à cette fonction, vous trouverez ici des documents d'API utiles: https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleSheet

Craig
la source
5

L'ajout de règles personnalisées est utile si vous créez un widget jQuery qui nécessite un CSS personnalisé (comme l'extension du framework CSS jQueryUI existant pour votre widget particulier). Cette solution s'appuie sur la réponse de Taras (la première ci-dessus).

En supposant que votre balisage HTML comporte un bouton avec un identifiant "addrule" et un div avec un identifiant "target" contenant du texte:

Code jQuery:

$( "#addrule" ).click(function () { addcssrule($("#target")); });

function addcssrule(target) 
{ 
var cssrules =  $("<style type='text/css'> </style>").appendTo("head");

cssrules.append(".redbold{ color:#f00; font-weight:bold;}"); 
cssrules.append(".newfont {font-family: arial;}"); 
target.addClass("redbold newfont");     
}       

L'avantage de cette approche est que vous pouvez réutiliser des règles css variables dans votre code pour ajouter ou soustraire des règles à volonté. Si cssrules est incorporé dans un objet persistant tel qu'un widget jQuery, vous avez une variable locale persistante avec laquelle travailler.

fbloggs
la source
Quelle belle idée! Je l'ai utilisé en conjonction avec l'extrait de code sur cette page ssdtutorials.com/tutorials/title/jquery-flashing-text.html pour permettre de basculer une couleur (l'original basculerait une classe uniquement). Merci!
bgmCoder
5

Dans les cas (inhabituels) où vous voulez pouvoir changer de style dynamiquement souvent - par exemple une application de création de thème - l'ajout de balises <style> ou l'appel de CSSStyleSheet.insertRule () entraînera une feuille de style croissante, qui peut avoir des performances et un design implications de débogage.

Mon approche n'autorise qu'une seule règle par combo sélecteur / propriété, effaçant tout élément existant lors de la définition d'une règle. L'API est simple et flexible:

function addStyle(selector, rulename, value) {
    var stylesheet = getAppStylesheet();
    var cssRules = stylesheet.cssRules || stylesheet.rules;
    var rule = stylesheet.insertRule(selector + ' { ' + rulename + ':' + value + ';}', cssRules.length);
}

function clearStyle(selector, rulename) {
    var stylesheet = getAppStylesheet();
    var cssRules = stylesheet.cssRules || stylesheet.rules;
    for (var i=0; i<cssRules.length; i++) {
        var rule = cssRules[i];
        if (rule.selectorText == selector && rule.style[0] == rulename) {
            stylesheet.deleteRule(i);
            break;
        }
    }       
}

function addStyles(selector, rules) {
    var stylesheet = getAppStylesheet();
    var cssRules = stylesheet.cssRules || stylesheet.rules;
    for (var prop in rules) {
        addStyle(selector, prop, rules[prop]);
    }
}

function getAppStylesheet() {
    var stylesheet = document.getElementById('my-styles');
    if (!stylesheet) {
        stylesheet = $('<style id="my-styles">').appendTo('head')[0];
    }
    stylesheet = stylesheet.sheet;
    return stylesheet;
}

Usage:

addStyles('body', {
    'background-color': 'black',
    color: 'green',
    margin: 'auto'
});

clearStyle('body', 'background-color');
addStyle('body', 'color', '#333')
Jason Boyd
la source
3

Et si vous écriviez dynamiquement une section <script> sur votre page (avec vos règles dynamiques), puis utilisiez jQuerys .addClass (classe) pour ajouter ces règles créées dynamiquement?

Je n'ai pas essayé cela, je propose simplement une théorie qui pourrait fonctionner.

Bryan Denny
la source
couture la meilleure façon en ce moment. J'ai trouvé quelque chose de jQuery.cssRule mais c'est une sorte de plugin: - /
stephan
2
$ ("head"). append ($ ("<style type = 'text / css'> ... is one way
stephan
2

Réponse un peu paresseuse à cette question, mais l'article suivant peut vous aider: http://www.javascriptkit.com/dhtmltutors/externalcss3.shtml

Essayez également de taper "modifier les règles CSS" dans Google

Je ne sais pas ce qui se passerait si vous essayiez d'encapsuler un document.styleSheets [0] avec jQuery () bien que vous puissiez l'essayer

James Wiseman
la source
2

Vous pouvez utiliser un plug-in cssRule . Le code était alors simple:

$.cssRule("#my-window {
    position: fixed;
    z-index: 102;
    display:none;
    top:50%;
    left:50%;
}");

Un des commentaires jusqu'à présent demandait pourquoi on voudrait faire une telle chose. Par exemple, créer des styles pour une liste où chaque élément a besoin d'une couleur d'arrière-plan distincte (par exemple, la liste de calendriers de GCal) où le nombre de colonnes n'est pas connu avant l'exécution.

Robert Gowland
la source
@Daniel, oui c'est vrai; déclaration supprimée.
Robert Gowland
semble ne pas prendre en charge une règle comme celle-ci:div:before{content:'name: ';}
liuyanghejerry
2

Voici une configuration qui donne la commande sur les couleurs avec cet objet json

 "colors": {
    "Backlink": ["rgb(245,245,182)","rgb(160,82,45)"],
    "Blazer": ["rgb(240,240,240)"],
    "Body": ["rgb(192,192,192)"],
    "Tags": ["rgb(182,245,245)","rgb(0,0,0)"],
    "Crosslink": ["rgb(245,245,182)","rgb(160,82,45)"],
    "Key": ["rgb(182,245,182)","rgb(0,118,119)"],
    "Link": ["rgb(245,245,182)","rgb(160,82,45)"],
    "Link1": ["rgb(245,245,182)","rgb(160,82,45)"],
    "Link2": ["rgb(245,245,182)","rgb(160,82,45)"],
    "Manager": ["rgb(182,220,182)","rgb(0,118,119)"],
    "Monitor": ["rgb(255,230,225)","rgb(255,80,230)"],
    "Monitor1": ["rgb(255,230,225)","rgb(255,80,230)"],
    "Name": ["rgb(255,255,255)"],
    "Trail": ["rgb(240,240,240)"],
    "Option": ["rgb(240,240,240)","rgb(150,150,150)"]
  }

cette fonction

 function colors(fig){
    var html,k,v,entry,
    html = []
    $.each(fig.colors,function(k,v){
        entry  = "." + k ;
        entry += "{ background-color :"+ v[0]+";";
        if(v[1]) entry += " color :"+ v[1]+";";
        entry += "}"
        html.push(entry)
    });
    $("head").append($(document.createElement("style"))
        .html(html.join("\n"))
    )
}

pour produire cet élément de style

.Backlink{ background-color :rgb(245,245,182); color :rgb(160,82,45);}
.Blazer{ background-color :rgb(240,240,240);}
.Body{ background-color :rgb(192,192,192);}
.Tags{ background-color :rgb(182,245,245); color :rgb(0,0,0);}
.Crosslink{ background-color :rgb(245,245,182); color :rgb(160,82,45);}
.Key{ background-color :rgb(182,245,182); color :rgb(0,118,119);}
.Link{ background-color :rgb(245,245,182); color :rgb(160,82,45);}
.Link1{ background-color :rgb(245,245,182); color :rgb(160,82,45);}
.Link2{ background-color :rgb(245,245,182); color :rgb(160,82,45);}
.Manager{ background-color :rgb(182,220,182); color :rgb(0,118,119);}
.Monitor{ background-color :rgb(255,230,225); color :rgb(255,80,230);}
.Monitor1{ background-color :rgb(255,230,225); color :rgb(255,80,230);}
.Name{ background-color :rgb(255,255,255);}
.Trail{ background-color :rgb(240,240,240);}
.Option{ background-color :rgb(240,240,240); color :rgb(150,150,150);}
Chris Glasier
la source
1

si vous ne voulez pas attribuer un affichage: aucun à une classe css, la bonne approche pour ajouter au style, jQuery.Rule fera le travail.

Dans certains cas, vous souhaitez appliquer des stiles avant l'événement d'ajout du contenu ajax et fondre le contenu après l'ajout et c'est tout!

Mattia
la source
1

Ici, vous avez une fonction pour obtenir la définition complète d'une classe CSS:

getCSSStyle = function (className) {
   for (var i = 0; i < document.styleSheets.length; i++) {
       var classes = document.styleSheets[i].rules || document.styleSheets[i].cssRules;
       for (var x = 0; x < classes.length; x++) {
           if (classes[x].selectorText  && - 1 != classes[x].selectorText.indexOf(className)) {
               return classes[x].cssText || classes[x].style.cssText;
           }
       }
   }
   return '';
};
berniecc
la source
1

Vous pouvez utiliser cette bibliothèque appelée cssobj

var result = cssobj({'#my-window': {
  position: 'fixed',
  zIndex: '102',
  display:'none',
  top:'50%',
  left:'50%'
}})

À tout moment, vous pouvez mettre à jour vos règles comme ceci:

result.obj['#my-window'].display = 'block'
result.update()

Ensuite, vous avez changé la règle. jQuery n'est pas la bibliothèque qui fait cela.

James Yang
la source
0

J'ai récemment joué avec certains de ces problèmes et j'ai utilisé deux approches différentes lors de la programmation d'un site iPhone / iPod.

La première façon dont je suis tombée sur la recherche de changements d'orientation afin que vous puissiez voir si le téléphone est en mode portrait ou paysage, c'est une manière très statique mais simple et intelligente:

En CSS:

#content_right,
#content_normal{
 display:none;
}

Dans le fichier JS:

function updateOrientation(){
  var contentType = "show_";
  switch(window.orientation){
   case 0:
   contentType += "normal";
   break;

   case -90:
   contentType += "right";
   break; document.getElementById("page_wrapper").setAttribute("class",contentType);
}

En PHP / HTML (importez d'abord votre fichier JS puis dans la balise body):

<body onorientationchange="updateOrientation();">

Cela choisit essentiellement un bloc CSS prédéfini différent à exécuter en fonction du résultat renvoyé par le fichier JS.

De plus, la manière la plus dynamique que j'ai préférée était un ajout très simple à une balise de script ou à votre fichier JS:

document.getelementbyid(id).style.backgroundColor = '#ffffff';

Cela fonctionne pour la plupart des navigateurs, mais pour IE, il est préférable de retirer ses munitions avec quelque chose de plus serré:

var yourID = document.getelementbyid(id); 
 if(yourID.currentstyle) { 
  yourID.style.backgroundColor = "#ffffff";      // for ie :@ 
 } else { 
  yourID.style.setProperty("background-color", "#ffffff");        // everything else :)
 }

Ou vous pouvez utiliser getElementByClass()et modifier une gamme d'articles.

J'espère que cela t'aides!

Cendre.

Cendre
la source
-2

Vous pouvez peut-être mettre les informations de style dans une classe distincte dans votre fichier css, par exemple:

.specificstyle {
    position: fixed;
    z-index: 102;
    display:none;
    top:50%;
    left:50%;
}

puis utilisez jQuery au moment de votre choix pour ajouter ce nom de classe à l'élément?

JorenB
la source
1
et vous ne voulez pas non plus mettre les informations dans la section head de votre page (entre les balises de style)?
JorenB
-2

Vous pouvez simplement créer une classe css appelée quelque chose comme .fixed-object qui contient tout votre css ...

.fixed-object{
    position: fixed;
    z-index: 102;
    display:none;
    top:50%;
    left:50%;
}

Ensuite, dans jquery, chaque fois que vous voulez que quelque chose ait ce style, ajoutez-y simplement cette classe ...

$(#my-window).addClass('fixed-object');

Cela semble être le moyen le plus simple de le faire, à moins que je ne comprenne mal ce que vous devez faire.

Sir David de Lee
la source
-9

En utilisant .addClass () dans jquery, nous pouvons ajouter dynamiquement du style aux éléments de la page. par exemple. nous avons du style

.myStyle
{
  width:500px;
  height:300px;
  background-color:red;
 }

Maintenant dans l'état prêt de jquery, nous pouvons ajouter des css comme .addClass (myStyle)

Avinash
la source