Cree una regla / clase CSS con jQuery en tiempo de ejecución

189

Por lo general, tengo un archivo CSS que tiene la siguiente regla:

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

¿Cómo puedo evitar crear un archivo CSS estático agregando la información CSS durante las acciones de tiempo de ejecución al cuerpo, o algo similar? (solo usando jQuery)

Quiero definirlo una vez pero con jQuery y usarlo muchas veces más tarde; Es por eso que no quiero agregarlo cada vez a los elementos DOM específicos.

Conozco las características simples ( css("attr1", "value");), pero ¿cómo puedo crear una regla CSS reutilizable completa?

stephan
fuente

Respuestas:

269

Puede crear un elemento de estilo e insertarlo en DOM

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

probado en Opera10 FF3.5 iE8 iE6

Taras Bulba
fuente
La esencia es autosuficiente. Puede crearlo localmente y funcionará bien. Enlace directo al enlace de descarga: gist.github.com/gists/714352/download
Daniel Ribeiro
No hay problema. A veces puede ser un error de versión menor de jQuery, o simplemente una configuración incorrecta. El trato con las aplicaciones js es este: si no funcionan, simplemente no funcionan en absoluto. Sin perdón.
Daniel Ribeiro
1
Lanza un error ' Llamada inesperada al método o acceso a la propiedad ' para mí en IE8. Tuve que seguir este artículo para que funcione.
Brandon Boone
66
Solo puede haber 31 estilos en la página en IE9- blogs.msdn.com/b/ieinternals/archive/2011/05/14/…
IvanH
1
Si no funciona Intenta agregar estilo a body. es decir$("<style>...</style>").appendTo("body");
inDream
118

Simplemente

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

Notado las barras diagonales? Se usan para unir cadenas que están en nuevas líneas. Dejarlos fuera genera un error.

bogonko
fuente
66
Esta. Debería ser la respuesta aceptada. En realidad responde la pregunta.
Johannes Pille
2
Estoy de acuerdo con @JohannesPille, ¡esta es la verdadera respuesta!
bayu
no funciona en cordova ios. ¿podría sugerirme esto?
RamGrg
2
Bastante eficiente y directo. Una vez que la nueva regla se inyecta en el encabezado, puede recuperarla en cualquier lugar de su página, incluso desde PHP.
Brice Coustillas
17

Puede aplicar CSS y un objeto. Para que pueda definir su objeto en su JavaScript de esta manera:

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

Y luego simplemente aplíquelo a todos los elementos que desee

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

Entonces es reutilizable. ¿Para qué propósito harías esto?

Yuval Karmi
fuente
22
Yo diría que esta es una regla CSS y no una clase CSS.
hippietrail
17
Esta respuesta es engañosa. El autor de la pregunta quería crear una regla CSS en tiempo de ejecución, no establecer el estilo de un elemento particular en una declaración CSS constante (reutilizable).
Dan Dascalescu
44
No es exactamente lo que pidieron, pero es la solución correcta :) Llenar el dom con elementos <style> adicionales tiene un olor desagradable a código
Kevin
3
¿Cómo va a eliminar estas reglas aplican cuando es necesario, es posible que con otras soluciones ...
Vishwanath
@Kevin: puede ser así, pero hay momentos en que eso es justo lo que necesitas. por ejemplo, cuando un elemento está siendo recreado por algún script ajax y necesita persistir una nueva regla de estilo.
billynoah
12

Puede usar insertRule si no necesita admitir IE <9, según dottoro . También hay un poco de código de navegador cruzado allí.

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

Aquí hay un complemento jquery que le permite inyectar CSS:

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

Ejemplo:

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

Esto no es nada nuevo en comparación con algunas de las otras respuestas, ya que utiliza el concepto descrito aquí y aquí , pero quería utilizar la declaración de estilo 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"
});

No estoy seguro de si cubre todas las capacidades de CSS, pero hasta ahora funciona para mí. Si no es así, considérelo un punto de partida para sus propias necesidades. :)

sjngm
fuente
7

Si no desea codificar el CSS en un bloque / archivo CSS, puede usar jQuery para agregar dinámicamente CSS a elementos, identificaciones y clases 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);
});
Mike Trpcic
fuente
55
Esta respuesta no es exactamente lo que pidió el autor de la pregunta. El autor de la pregunta quería crear una regla CSS en tiempo de ejecución, no establecer el estilo de un elemento particular en una declaración CSS constante.
Dan Dascalescu
Entiendo, pero esta es una solución alternativa, así que la proporcioné.
Mike Trpcic
2
@MikeTrpcic El problema es que hay otras personas que también buscan esta solución, para agregar reglas CSS a una página, y su respuesta no resuelve eso.
nate
5

Agregar reglas personalizadas es útil si crea un widget jQuery que requiere CSS personalizado (como extender el marco CSS jQueryUI existente para su widget en particular). Esta solución se basa en la respuesta de Taras (la primera de arriba).

Suponiendo que su marcado HTML tiene un botón con una identificación de "addrule" y un div con una identificación de "destino" que contiene algo de texto:

Código 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");     
}       

La ventaja de este enfoque es que puede reutilizar cssrules variables en su código para agregar o restar reglas a voluntad. Si cssrules está incrustado en un objeto persistente como un widget jQuery, tiene una variable local persistente con la que trabajar.

fbloggs
fuente
¡Qué buena idea! Lo utilicé junto con el fragmento de esta página ssdtutorials.com/tutorials/title/jquery-flashing-text.html para permitir alternar un color (el original alternaría solo una clase). ¡Gracias!
bgmCoder
5

Tenga en cuenta que jQuery().css()no cambia las reglas de la hoja de estilo, solo cambia el estilo de cada elemento coincidente.

En cambio, aquí hay una función de JavaScript que escribí para modificar las reglas de la hoja de estilo.

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

Ventajas:

  • Los estilos se pueden calcular en una <head>secuencia de comandos antes de que se creen los elementos DOM y, por lo tanto, antes de la primera representación del documento, evitando una representación visualmente molesta, luego computar y luego volver a representar. Con jQuery, tendrías que esperar a que se creen los elementos DOM, luego cambiarles el estilo y volver a representarlos.
  • Los elementos que se agregan dinámicamente después del rediseño tendrán automáticamente los nuevos estilos aplicados sin una llamada adicional a jQuery(newElement).css()

Advertencias:

  • Lo he usado en Chrome e IE10. Creo que podría necesitar una pequeña modificación para que funcione bien en versiones anteriores de IE. En particular, las versiones anteriores de IE podrían no haberse s.cssRulesdefinido, por lo que recurrirán a s.rulesalgunas peculiaridades, como el comportamiento extraño / con errores relacionado con los selectores delimitados por comas, como"body, p" . Si los evita, es posible que esté bien en versiones anteriores de IE sin modificación, pero aún no lo he probado.
  • Actualmente, los selectores deben coincidir exactamente: use minúsculas y tenga cuidado con las listas delimitadas por comas; el orden debe coincidir y deben estar en el formato, "first, second"es decir, el delimitador es una coma seguida de un carácter de espacio.
  • Probablemente se podría pasar un tiempo adicional intentando detectar y manejar inteligentemente selectores superpuestos, como los de las listas delimitadas por comas.
  • También se podría agregar soporte para consultas de medios y el !importantmodificador sin demasiados problemas.

Si tiene ganas de hacer algunas mejoras en esta función, encontrará algunos documentos API útiles aquí: https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleSheet

Craig
fuente
5

En los casos (inusuales) en los que desea poder cambiar dinámicamente los estilos a menudo, por ejemplo, una aplicación de creación de temas, agregar etiquetas <style> o llamar a CSSStyleSheet.insertRule () dará como resultado una hoja de estilos en crecimiento, que puede tener rendimiento y diseño implicaciones de depuración.

Mi enfoque solo permite una sola regla por combinación de selector / propiedad, borrando cualquier existente al establecer cualquier regla. La API es simple y 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;
}

Uso:

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

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

¿Qué sucede si escribiste dinámicamente una sección <script> en tu página (con tus reglas dinámicas) y luego usaste jQuerys .addClass (clase) para agregar esas reglas creadas dinámicamente?

No he intentado esto, solo ofreciendo una teoría que podría funcionar.

Bryan Denny
fuente
parece la mejor manera en este momento. he encontrado algo jQuery.cssRule pero es algún tipo de complemento: - /
stephan
2
$ ("head"). append ($ ("<style type = 'text / css'> ... es unidireccional
stephan
2

Es un poco flojo responder esto, pero el siguiente artículo puede ayudar: http://www.javascriptkit.com/dhtmltutors/externalcss3.shtml

Además, intente escribir "modificar reglas CSS" en Google

No estoy seguro de lo que sucedería si intentara envolver un document.styleSheets [0] con jQuery () aunque podría intentarlo

James Wiseman
fuente
2

Puede usar el complemento cssRule . El código era simple entonces:

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

Uno de los comentarios hasta ahora preguntaba por qué uno querría hacer tal cosa. Por ejemplo, crear estilos para una lista donde cada elemento necesita un color de fondo distinto (por ejemplo, la lista de calendarios de GCal) donde el número de columnas no se conoce hasta el tiempo de ejecución.

Robert Gowland
fuente
@Daniel, sí, lo hace; declaración eliminada.
Robert Gowland el
Parece no soporta regla como la siguiente:div:before{content:'name: ';}
liuyanghejerry
2

Aquí hay una configuración que da comando sobre los colores con este objeto 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)"]
  }

esta función

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

para producir este elemento de estilo

.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
fuente
1

si no desea asignar una pantalla: ninguna a una clase css, el enfoque correcto para agregar estilo, jQuery.Rule hace el trabajo.

En algunos casos, desea aplicar stiles antes del evento de agregar contenido de ajax y desvanecer el contenido después de agregar, ¡y esto es todo!

Mattia
fuente
1

Aquí tiene una función para obtener la definición completa de una clase 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
fuente
1

Puedes usar esta lib llamada cssobj

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

En cualquier momento puede actualizar sus reglas de esta manera:

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

Entonces tienes la regla cambiada. jQuery no es la lib haciendo esto.

James Yang
fuente
0

He estado jugando con algo de esto recientemente y he usado dos enfoques diferentes al programar un sitio de iPhone / iPod.

La primera forma en que me encontré al buscar cambios de orientación para que pueda ver si el teléfono es vertical u horizontal, esta es una forma muy estática pero simple e inteligente:

En CSS:

#content_right,
#content_normal{
 display:none;
}

En archivo 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 (Importe su archivo JS primero y luego en la etiqueta del cuerpo):

<body onorientationchange="updateOrientation();">

Básicamente, esto elige un bloque CSS preestablecido diferente para ejecutarse dependiendo del resultado devuelto por el archivo JS.

También la forma más dinámica que preferí fue una adición muy simple a una etiqueta de script o su archivo JS:

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

Esto funciona para la mayoría de los navegadores, pero para IE es mejor quitarle las municiones con algo más estricto:

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

O puede usar getElementByClass()y cambiar una variedad de artículos.

¡Espero que esto ayude!

Ceniza.

Ceniza
fuente
-2

Tal vez pueda poner la información de estilo en una clase separada en su archivo CSS, por ejemplo:

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

y luego use jQuery en el punto que elija para agregar este nombre de clase al elemento?

JorenB
fuente
1
y tampoco quieres poner la información en la sección de encabezado de tu página (entre etiquetas de estilo)?
JorenB
-2

Podrías hacer una clase css llamada algo así como .fixed-object que tenga todo tu css en ella ...

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

Luego, en jquery cada vez que quieras que algo tenga ese estilo, solo agrega esa clase ...

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

Esa parece ser la forma más fácil de hacerlo, a menos que no entienda lo que necesita hacer.

Sir David de Lee
fuente
-9

Al usar .addClass () en jquery podemos agregar dinámicamente estilo a los elementos de la página. p.ej. tenemos estilo

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

Ahora en estado listo de jquery podemos agregar css como .addClass (myStyle)

Avinash
fuente