Crea una regola / classe CSS con jQuery in fase di esecuzione


189

Di solito ho un file CSS che ha la seguente regola:

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

Come posso evitare di creare un file CSS statico aggiungendo al corpo le informazioni CSS durante le azioni di runtime o qualcosa di simile? (usando solo jQuery)

Voglio definirlo una volta ma con jQuery e usarlo molte volte dopo; ecco perché non voglio aggiungerlo ogni volta agli elementi DOM specifici.

Conosco le funzionalità semplici ( css("attr1", "value");), ma come posso creare una regola CSS riutilizzabile completa?

Risposte:


269

Puoi creare un elemento di stile e inserirlo in DOM

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

testato su Opera10 FF3.5 iE8 iE6


L'essenza è autosufficiente. Puoi crearlo localmente e funzionerà perfettamente. Link diretto al link di download: gist.github.com/gists/714352/download
Daniel Ribeiro

Nessun problema. A volte può essere un bug della versione minore di jQuery o solo una configurazione errata. L'accordo con le app js è questo: se non funzionano, semplicemente non funzionano affatto. Nessun perdono
Daniel Ribeiro,

1
Genera un errore " Chiamata imprevista al metodo o accesso alla proprietà " per me in IE8. Ho dovuto seguire questo articolo per farlo funzionare.
Brandon Boone,

6
Ci possono essere solo 31 stili nella pagina di IE9- blogs.msdn.com/b/ieinternals/archive/2011/05/14/…
IvanH,

1
Se non funziona. Prova ad aggiungere stile a body. vale a dire$("<style>...</style>").appendTo("body");
inDream

118

Semplicemente

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

Hai notato le barre posteriori? Sono usati per unire stringhe che si trovano su nuove linee. Lasciarli fuori genera un errore.


6
Questo. Dovrebbe essere la risposta accettata. In realtà risponde alla domanda.
Johannes Pille,

2
Sono d'accordo con @JohannesPille, questa è la vera risposta!
Bayu,

non funziona in Cordova iOS. potresti per favore suggerire questo?
RamGrg,

2
Abbastanza efficiente e semplice. Una volta iniettata la nuova regola nell'intestazione, puoi recuperarla in qualsiasi punto della tua pagina, incluso da PHP.
Brice Coustillas,


17

puoi applicare css an an object. Quindi puoi definire il tuo oggetto nel tuo javascript in questo modo:

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

E poi semplicemente applicalo a tutti gli elementi che desideri

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

Quindi è riutilizzabile. Per quale scopo lo faresti?


22
Direi che questa è una regola CSS e non una classe CSS.
hippietrail,

17
Questa risposta è fuorviante. Il richiedente voleva creare una regola CSS in fase di esecuzione, non impostare lo stile di un elemento particolare su una dichiarazione CSS costante (riutilizzabile).
Dan Dascalescu il

4
Non è proprio quello che hanno chiesto, ma è la soluzione giusta :) Riempire il dom con elementi <style> extra ha un cattivo odore di codice
Kevin

3
Come rimuoverai queste regole applicate quando è necessario, questo è possibile con altre soluzioni ...
Vishwanath,

@Kevin - potrebbe essere così ma ci sono momenti in cui è proprio quello di cui hai bisogno. per esempio - quando un elemento viene ricreato da alcuni script ajax e devi persistere una nuova regola di stile.
Billynoah,

12

È possibile utilizzare insertRule se non è necessario supportare IE <9, secondo dottoro . C'è anche un po 'di codice cross browser laggiù.

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


9

Questa non è una novità rispetto ad alcune delle altre risposte in quanto utilizza il concetto descritto qui e qui , ma volevo fare uso della dichiarazione in stile JSON:

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

Uso:

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

Non sono sicuro che copra tutte le funzionalità dei CSS, ma finora funziona per me. In caso contrario, consideralo un punto di partenza per le tue esigenze. :)


7

Se non si desidera codificare il CSS in un blocco / file CSS, è possibile utilizzare jQuery per aggiungere dinamicamente CSS a elementi, ID e classi HTML.

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

5
Questa risposta non è esattamente ciò che chiedeva il richiedente. Il richiedente voleva creare una regola CSS in fase di esecuzione, non impostare lo stile di un particolare elemento su una costante dichiarazione CSS.
Dan Dascalescu il

Capisco, ma questa è una soluzione alternativa, quindi l'ho fornita.
Mike Trpcic,

2
@MikeTrpcic Il problema è che ci sono anche altre persone che cercano questa soluzione - per aggiungere regole CSS a una pagina - e la tua risposta non lo risolve.
Data

5

L'aggiunta di regole personalizzate è utile se si crea un widget jQuery che richiede CSS personalizzati (come l'estensione del framework CSS jQueryUI esistente per il proprio widget). Questa soluzione si basa sulla risposta di Taras (la prima sopra).

Supponendo che il markup HTML abbia un pulsante con un ID di "addrule" e un div con un ID di "target" contenente del testo:

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

Il vantaggio di questo approccio è che puoi riutilizzare variabili cssrules nel tuo codice per aggiungere o sottrarre regole a piacimento. Se cssrules è incorporato in un oggetto persistente come un widget jQuery, è necessario utilizzare una variabile locale persistente.


Che bella idea! L'ho usato insieme allo snippet in questa pagina ssdtutorials.com/tutorials/title/jquery-flashing-text.html per consentire di alternare un colore (l'originale commuterebbe solo una classe). Grazie!
bgmCoder

5

Nota che jQuery().css()non cambia le regole del foglio di stile, cambia solo lo stile di ogni elemento abbinato.

Invece, ecco una funzione javascript che ho scritto per modificare le regole del foglio di stile.

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

vantaggi:

  • Gli stili possono essere calcolati in uno <head>script prima della creazione degli elementi DOM e quindi prima del primo rendering del documento, evitando un rendering visivamente fastidioso, quindi calcolando, quindi eseguendo nuovamente il rendering. Con jQuery, dovresti attendere che gli elementi DOM vengano creati, quindi ridisegnali e ri-renderli.
  • Agli elementi che vengono aggiunti in modo dinamico dopo il restyle verranno automaticamente applicati i nuovi stili senza una chiamata aggiuntiva jQuery(newElement).css()

Avvertenze:

  • L'ho usato su Chrome e IE10. Penso che potrebbe essere necessaria una piccola modifica per farlo funzionare bene con le versioni precedenti di IE. In particolare, le versioni precedenti di IE potrebbero non essere state s.cssRulesdefinite, quindi ricadranno su quelle s.rulesche presentano alcune peculiarità, come il comportamento dispari / buggy relativo ai selettori delimitati da virgole, come "body, p". Se li eviti, potresti essere ok nelle versioni precedenti di IE senza modifiche, ma non l'ho ancora testato.
  • Attualmente i selettori devono corrispondere esattamente: utilizzare le lettere minuscole e fare attenzione agli elenchi delimitati da virgole; l'ordine deve corrispondere e devono essere nel formato, "first, second"ovvero il delimitatore è una virgola seguita da uno spazio.
  • Probabilmente si potrebbe dedicare un po 'di tempo aggiuntivo a tentare di rilevare e gestire in modo intelligente selettori sovrapposti, come quelli negli elenchi delimitati da virgole.
  • Si potrebbe anche aggiungere supporto per le query multimediali e il !importantmodificatore senza troppi problemi.

Se desideri apportare alcuni miglioramenti a questa funzione, troverai alcuni utili documenti API qui: https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleSheet


5

Nei casi (insoliti) in cui si desidera poter cambiare dinamicamente spesso gli stili, ad esempio un'app per la creazione di temi, l'aggiunta di tag <style> o la chiamata di CSSStyleSheet.insertRule () comporterà un foglio di stile in crescita, che può avere prestazioni e design implicazioni sul debug.

Il mio approccio consente solo una singola regola per selettore / proprietà combinata, cancellando qualsiasi esistente sull'impostazione di qualsiasi regola. L'API è semplice e flessibile:

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

Uso:

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

clearStyle('body', 'background-color');
addStyle('body', 'color', '#333')

3

Che cosa succede se hai scritto dinamicamente una sezione <script> sulla tua pagina (con le tue regole dinamiche) e poi hai usato jQuerys .addClass (classe) per aggiungere quelle regole create dinamicamente?

Non ho provato questo, offrendo solo una teoria che potrebbe funzionare.


cuciture nel modo migliore in questo momento. ho trovato qualcosa di jQuery.cssRule ma è una specie di plugin: - /
stephan

2
$ ("head"). append ($ ("<style type = 'text / css'> ... è a senso unico
stephan


2

È possibile utilizzare un plug-in cssRule . Il codice era semplice allora:

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

Uno dei commenti finora ha chiesto perché si vorrebbe fare una cosa del genere. Ad esempio, la creazione di stili per un elenco in cui ogni elemento necessita di un colore di sfondo distinto (ad esempio l'elenco di calendari di GCal) in cui il numero di colonne non è noto fino al runtime.


@Daniel, sì, lo fa; dichiarazione rimossa.
Robert Gowland,

sembra non supportare la regola in questo modo:div:before{content:'name: ';}
liuyanghejerry,

2

Ecco una configurazione che dà il comando sui colori con questo oggetto 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)"]
  }

questa funzione

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

per produrre questo elemento di stile

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

1

se non si desidera assegnare un display: nessuno a una classe css, l'approccio giusto per aggiungere allo stile, jQuery.Rule fa il lavoro.

Ho alcuni casi in cui vuoi applicare gli stili prima dell'evento append del contenuto ajax e sbiadire il contenuto dopo l'aggiunta e questo è tutto!


1

Qui hai una funzione per ottenere la definizione completa di una 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 '';
};

1

Puoi usare questa lib chiamata cssobj

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

Ogni volta che puoi aggiornare le tue regole in questo modo:

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

Quindi hai cambiato la regola. jQuery non è la lib che lo fa.


0

Di recente ho fatto un casino con questo e ho usato due approcci diversi durante la programmazione di un sito iPhone / iPod.

Il primo modo in cui mi sono imbattuto durante la ricerca di cambiamenti di orientamento in modo da poter vedere se il telefono è verticale o orizzontale, questo è un modo molto statico ma semplice e intelligente:

Nel CSS:

#content_right,
#content_normal{
 display:none;
}

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

In PHP / HTML (importa prima il tuo file JS e poi nel tag body):

<body onorientationchange="updateOrientation();">

Questo fondamentalmente sceglie un diverso blocco CSS preimpostato da eseguire in base al risultato restituito dal file JS.

Anche il modo più dinamico che ho preferito era un'aggiunta molto semplice a un tag script o al tuo file JS:

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

Questo funziona per la maggior parte dei browser, ma per IE è meglio togliere le munizioni con qualcosa di più stretto:

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

Oppure puoi usare getElementByClass()e modificare una gamma di articoli.

Spero che questo ti aiuti!

Cenere.


-2

Forse puoi inserire le informazioni di stile in una classe separata nel tuo file css, ad esempio:

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

e quindi utilizzare jQuery nel momento in cui si è scelto di aggiungere questo nome classe all'elemento?


1
e non vuoi mettere neanche le informazioni nella sezione head della tua pagina (tra tag di stile)?
JorenB,

-2

Potresti semplicemente creare una classe CSS chiamata qualcosa come .fixed-object che contiene tutti i tuoi CSS ...

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

Quindi in jquery ogni volta che vuoi che qualcosa abbia quello stile, aggiungi semplicemente quella classe ...

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

Sembra il modo più semplice per farlo, a meno che non fraintenda quello che devi fare.


-9

Usando .addClass () in jquery possiamo aggiungere dinamicamente stile agli elementi sulla pagina. per esempio. abbiamo stile

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

Ora nello stato pronto di jquery possiamo aggiungere css come .addClass (myStyle)

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.