Cambiar los valores CSS con Javascript

105

Es fácil establecer valores CSS en línea con javascript. Si quiero cambiar el ancho y tengo un html como este:

<div style="width: 10px"></div>

Todo lo que necesito hacer es:

document.getElementById('id').style.width = value;

Cambiará los valores de la hoja de estilo en línea. Normalmente esto no es un problema, porque el estilo en línea anula la hoja de estilo. Ejemplo:

<style>
   #tId {
      width: 50%;
   }
</style>

<div id="tId"></div>

Usando este Javascript:

document.getElementById('tId').style.width = "30%";

Obtengo lo siguiente:

<style>
   #tId {
      width: 50%;
   }
</style>

<div id="tId" style="width: 30%";></div>

Esto es un problema, porque no solo no quiero cambiar los valores en línea, si busco el ancho antes de configurarlo, cuando tengo:

<div id="tId"></div>

El valor devuelto es Nulo, por lo que si tengo Javascript que necesita saber el ancho de algo para hacer algo de lógica (aumento el ancho en un 1%, no a un valor específico), obtengo Null cuando espero la cadena "50% "realmente no funciona.

Entonces mi pregunta: tengo valores en un estilo CSS que no están ubicados en línea, ¿cómo puedo obtener estos valores? ¿Cómo puedo modificar el estilo en lugar de los valores en línea, dada una identificación?

Coltin
fuente
¿podrías editar tu publicación? hay algunas oraciones incompletas al principio, no estoy seguro de lo que estaba buscando ...
Jason S
Todavía estoy un poco confundido sobre lo que estás preguntando. ¿Está pidiendo 1) que cambie el CSS mismo que cambiará todos los elementos a la vez? o 2) ¿cambiar el CSS de un solo elemento a la vez?
Mike
También estoy confundido en cuanto a la pregunta real. El estilo actual de un objeto no necesariamente será el mismo que el atributo 'estilo' de la etiqueta.
MattJ
Lo siento, lo editaré para que quede más claro. No quiero configurar CSS en línea. Me gustaría poder aumentar / disminuir el ancho del estilo. Editaré con un ejemplo completo de lo que estoy buscando.
Coltin
Respuesta de Codepen codepen.io/quezo/post/dynamically-updating-css
Nick Mitchell

Respuestas:

90

Bien, parece que desea cambiar el CSS global para que cambie de manera eficiente todos los elementos de un estilo peticular a la vez. Recientemente aprendí cómo hacer esto yo mismo con un tutorial de Shawn Olson . Puede hacer referencia directamente a su código aquí .

Aquí está el resumen:

Puede recuperar las hojas de estilo a través de document.styleSheets. En realidad, esto devolverá una matriz de todas las hojas de estilo en su página, pero puede saber en cuál se encuentra a través de la document.styleSheets[styleIndex].hrefpropiedad. Una vez que haya encontrado la hoja de estilo que desea editar, debe obtener la matriz de reglas. Esto se denomina "reglas" en IE y "cssRules" en la mayoría de los demás navegadores. La forma de saber en qué CSSRule se encuentra es mediante la selectorTextpropiedad. El código de trabajo se parece a esto:

var cssRuleCode = document.all ? 'rules' : 'cssRules'; //account for IE and FF
var rule = document.styleSheets[styleIndex][cssRuleCode][ruleIndex];
var selector = rule.selectorText;  //maybe '#tId'
var value = rule.value;            //both selectorText and value are settable.

Hágame saber cómo funciona esto para usted y comente si ve algún error.

Miguel
fuente
1
Cambiar CSS de esta manera es mucho más rápido si tiene más de 100 elementos. Digamos, por ejemplo, cambiar todas las celdas de una determinada parte de una tabla a la vez.
EdH
5
No puedo encontrar rule.valueen FF 20. Sin rule.styleembargo, hay, que se puede configurar y se comporta como element.style. Cf. https://developer.mozilla.org/en-US/docs/DOM/CSSStyleRule . rule.type == rule.STYLE_RULETambién puede ser una buena idea buscar antes de acceder rule.selectorText.
Christian Aichinger
1
¡ESO FUE ASOMBROSO! Estaba trabajando en transiciones de imágenes y el CSS realmente se ralentiza cuando comienzas a poner una imagen grande en 36 URI separados para cortar. Esto solo quitó una tonelada de gastos generales de mi guión. ¡Gracias!
Jason Maggard
document.styleSheets[styleIndex].cssRules.[ruleIndex].style = {'color':'red', 'background-color':'green'};funcionó para mí, gracias!
Pavel
43

¡Por favor! ¡Pregúntele a w3 ( http://www.quirksmode.org/dom/w3c_css.html )! O en realidad, me tomó cinco horas ... ¡pero aquí está!

function css(selector, property, value) {
    for (var i=0; i<document.styleSheets.length;i++) {//Loop through all styles
        //Try add rule
        try { document.styleSheets[i].insertRule(selector+ ' {'+property+':'+value+'}', document.styleSheets[i].cssRules.length);
        } catch(err) {try { document.styleSheets[i].addRule(selector, property+':'+value);} catch(err) {}}//IE
    }
}

La función es realmente fácil de usar ... ejemplo:

<div id="box" class="boxes" onclick="css('#box', 'color', 'red')">Click Me!</div>
Or:
<div class="boxes" onmouseover="css('.boxes', 'color', 'green')">Mouseover Me!</div>
Or:
<div class="boxes" onclick="css('body', 'border', '1px solid #3cc')">Click Me!</div>

Oh..


EDITAR: como @ user21820 describió en su respuesta, podría ser un poco innecesario cambiar todas las hojas de estilo en la página. La siguiente secuencia de comandos funciona con IE5.5 y con la última versión de Google Chrome, y agrega solo la función css () descrita anteriormente.

(function (scope) {
    // Create a new stylesheet in the bottom
    // of <head>, where the css rules will go
    var style = document.createElement('style');
    document.head.appendChild(style);
    var stylesheet = style.sheet;
    scope.css = function (selector, property, value) {
        // Append the rule (Major browsers)
        try { stylesheet.insertRule(selector+' {'+property+':'+value+'}', stylesheet.cssRules.length);
        } catch(err) {try { stylesheet.addRule(selector, property+':'+value); // (pre IE9)
        } catch(err) {console.log("Couldn't add style");}} // (alien browsers)
    }
})(window);
Leonard Pauli
fuente
Implementación realmente fácil. Gracias
Kaleb Anderson
1
¿Hay alguna razón para modificar cada hoja de estilo en lugar de una sola recién creada como en mi respuesta?
user21820
Muy buena implementación. Felicitaciones a usted señor.
Jason Maggard
1
@ user21820, probablemente no. Supongo que realmente quería estar seguro. Respuesta finalmente actualizada, felicitaciones :)
Leonard Pauli
10

Al reunir el código en las respuestas, escribí esta función que parece funcionar bien en mi FF 25.

function CCSStylesheetRuleStyle(stylesheet, selectorText, style, value){
  /* returns the value of the element style of the rule in the stylesheet
  *  If no value is given, reads the value
  *  If value is given, the value is changed and returned
  *  If '' (empty string) is given, erases the value.
  *  The browser will apply the default one
  *
  * string stylesheet: part of the .css name to be recognized, e.g. 'default'
  * string selectorText: css selector, e.g. '#myId', '.myClass', 'thead td'
  * string style: camelCase element style, e.g. 'fontSize'
  * string value optionnal : the new value
  */
  var CCSstyle = undefined, rules;
  for(var m in document.styleSheets){
    if(document.styleSheets[m].href.indexOf(stylesheet) != -1){
     rules = document.styleSheets[m][document.all ? 'rules' : 'cssRules'];
     for(var n in rules){
       if(rules[n].selectorText == selectorText){
         CCSstyle = rules[n].style;
         break;
       }
     }
     break;
    }
  }
  if(value == undefined)
    return CCSstyle[style]
  else
    return CCSstyle[style] = value
}

Esta es una forma de poner valores en el CSS que se usarán en JS incluso si el navegador no los entiende. por ejemplo, maxHeight para un tbody en una tabla desplazada.

Llamada :

CCSStylesheetRuleStyle('default', "#mydiv", "height");

CCSStylesheetRuleStyle('default', "#mydiv", "color", "#EEE");

FrViPofm
fuente
1
Si el estilo está incrustado en la página HTML, document.styleSheets[m].hrefserá nulo y fallará.
JCM
4

No sé por qué las otras soluciones revisan la lista completa de hojas de estilo para el documento. Hacerlo crea una nueva entrada en cada hoja de estilo, lo cual es ineficiente. En su lugar, simplemente podemos agregar una nueva hoja de estilo y simplemente agregar nuestras reglas CSS deseadas allí.

style=document.createElement('style');
document.head.appendChild(style);
stylesheet=style.sheet;
function css(selector,property,value)
{
    try{ stylesheet.insertRule(selector+' {'+property+':'+value+'}',stylesheet.cssRules.length); }
    catch(err){}
}

Tenga en cuenta que podemos anular incluso los estilos en línea establecidos directamente en los elementos agregando "! Important" al valor de la propiedad, a menos que ya existan declaraciones de estilo "! Important" más específicas para esa propiedad.

user21820
fuente
1
Consulte developer.mozilla.org/en-US/docs/Web/API/CSSStyleSheet/… para obtener una versión más complicada.
user21820
1
Muy cierto. Asegúrese de usar .addRule (selector, propiedad + ':' + valor) si .insertRule falla (para soporte previo a IE9).
Leonard Pauli
3

No tengo suficiente representante para comentar, así que formatearé una respuesta, pero es solo una demostración del problema en cuestión.

Al parecer, cuando los estilos de elementos se definen en hojas de estilo, no son visibles para getElementById ("someElement"). Style

Este código ilustra el problema ... Código de abajo en jsFiddle .

En la Prueba 2, en la primera llamada, el valor de los elementos que quedan no está definido, por lo que lo que debería ser un simple cambio se estropea. Para mi uso, definiré mis valores de estilo importantes en línea, pero parece frustrar parcialmente el propósito de la hoja de estilo.

Aquí está el código de la página ...

<html>
  <head>
    <style type="text/css">
      #test2a{
        position: absolute;
        left: 0px;
        width: 50px;
        height: 50px;
        background-color: green;
        border: 4px solid black;
      }
      #test2b{
        position: absolute;
        left: 55px;
        width: 50px;
        height: 50px;
        background-color: yellow;
        margin: 4px;
      }
    </style>
  </head>
  <body>

  <!-- test1 -->
    Swap left positions function with styles defined inline.
    <a href="javascript:test1();">Test 1</a><br>
    <div class="container">
      <div id="test1a" style="position: absolute;left: 0px;width: 50px; height: 50px;background-color: green;border: 4px solid black;"></div>
      <div id="test1b" style="position: absolute;left: 55px;width: 50px; height: 50px;background-color: yellow;margin: 4px;"></div>
    </div>
    <script type="text/javascript">
     function test1(){
       var a = document.getElementById("test1a");
       var b = document.getElementById("test1b");
       alert(a.style.left + " - " + b.style.left);
       a.style.left = (a.style.left == "0px")? "55px" : "0px";
       b.style.left = (b.style.left == "0px")? "55px" : "0px";
     }
    </script>
  <!-- end test 1 -->

  <!-- test2 -->
    <div id="moveDownThePage" style="position: relative;top: 70px;">
    Identical function with styles defined in stylesheet.
    <a href="javascript:test2();">Test 2</a><br>
    <div class="container">
      <div id="test2a"></div>
      <div id="test2b"></div>
    </div>
    </div>
    <script type="text/javascript">
     function test2(){
       var a = document.getElementById("test2a");
       var b = document.getElementById("test2b");
       alert(a.style.left + " - " + b.style.left);
       a.style.left = (a.style.left == "0px")? "55px" : "0px";
       b.style.left = (b.style.left == "0px")? "55px" : "0px";
     }
    </script>
  <!-- end test 2 -->

  </body>
</html>

Espero que esto ayude a aclarar el tema.

Omitir

BentFX
fuente
2

Puede obtener los estilos "calculados" de cualquier elemento.

IE usa algo llamado "currentStyle", Firefox (y supongo que otros navegadores "compatibles con el estándar") usa "defaultView.getComputedStyle".

Necesitará escribir una función de navegador cruzado para hacer esto, o usar un buen marco de Javascript como prototype o jQuery (busque "getStyle" en el archivo prototipo de javascript y "curCss" en el archivo jquery javascript).

Dicho esto, si necesita la altura o el ancho, probablemente debería usar element.offsetHeight y element.offsetWidth.

El valor devuelto es Nulo, por lo que si tengo Javascript que necesita saber el ancho de algo para hacer algo de lógica (aumento el ancho en un 1%, no a un valor específico)

Tenga en cuenta que si agrega un estilo en línea al elemento en cuestión, puede actuar como el valor "predeterminado" y será legible por Javascript al cargar la página, ya que es la propiedad de estilo en línea del elemento:

<div style="width:50%">....</div>

fuente
0

Esta simple esencia de 32 líneas le permite identificar una hoja de estilo dada y cambiar sus estilos muy fácilmente:

var styleSheet = StyleChanger("my_custom_identifier");
styleSheet.change("darkolivegreen", "blue");
solendil
fuente
0

Nunca he visto un uso práctico de esto, pero probablemente debería considerar las hojas de estilo DOM . Sin embargo, honestamente creo que es una exageración.

Si simplemente desea obtener el ancho y el alto de un elemento, independientemente de dónde se apliquen las dimensiones, simplemente use element.offsetWidthy element.offsetHeight.

Rakesh Pai
fuente
Mi uso: <style> #tid {width: 10%; } </style> <div id = 'tid' onclick = "aumento ('tid')"> </div> aumento comprobará si el ancho es <100%, si es así, aumentará en un 1%. document.getElementById.style.width devuelve nulo porque no hay un valor en línea. ¿Existe una forma más sencilla que las hojas de estilo DOM?
Coltin
0

Quizás intente esto:

function CCSStylesheetRuleStyle(stylesheet, selectorText, style, value){
  var CCSstyle = undefined, rules;
  for(var m in document.styleSheets){
    if(document.styleSheets[m].href.indexOf(stylesheet) != -1){
     rules = document.styleSheets[m][document.all ? 'rules' : 'cssRules'];
     for(var n in rules){
       if(rules[n].selectorText == selectorText){
         CCSstyle = rules[n].style;
         break;
       }
     }
     break;
    }
  }
  if(value == undefined)
    return CCSstyle[style]
  else
    return CCSstyle[style] = value
}
Shaq
fuente