Alterar valores CSS com Javascript

105

É fácil definir valores CSS embutidos com javascript. Se eu quiser mudar a largura e tiver um html assim:

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

Tudo que eu preciso fazer é:

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

Isso mudará os valores da folha de estilo embutida. Normalmente, isso não é um problema, porque o estilo embutido substitui a folha de estilo. Exemplo:

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

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

Usando este Javascript:

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

Eu obtenho o seguinte:

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

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

Isso é um problema, porque não só não quero alterar os valores embutidos, Se eu olhar para a largura antes de defini-la, quando tenho:

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

O valor retornado é Nulo, então se eu tenho Javascript que precisa saber a largura de algo para fazer alguma lógica (eu aumento a largura em 1%, não para um valor específico), voltando Nulo quando espero a string "50% "realmente não funciona.

Portanto, minha pergunta: eu tenho valores em um estilo CSS que não estão localizados inline, como posso obter esses valores? Como posso modificar o estilo em vez dos valores embutidos, dado um id?

Coltin
fonte
você poderia editar sua postagem? existem algumas frases incompletas no início, não tenho certeza do que você estava procurando ...
Jason S
Ainda estou um pouco confuso sobre o que você está perguntando. Você está pedindo 1) para alterar o próprio CSS, o que mudará todos os elementos de uma vez? ou 2) para alterar o CSS para um único item por vez?
Mike
Também estou confuso quanto à questão real. O estilo atual de um objeto não será necessariamente o mesmo que o atributo 'estilo' da tag.
MattJ
Desculpe, vou editar para ficar mais claro. Não quero definir CSS embutido. Gostaria de poder aumentar / diminuir a largura do estilo. Vou editar com um exemplo completo do que estou procurando.
Coltin
Resposta da Codepen codepen.io/quezo/post/dynamically-updating-css
Nick Mitchell

Respostas:

90

Ok, parece que você deseja alterar o CSS global para que altere de forma eficaz todos os elementos de um estilo particular de uma vez. Recentemente, aprendi como fazer isso sozinho com um tutorial de Shawn Olson . Você pode consultar seu código diretamente aqui .

Aqui está o resumo:

Você pode recuperar as folhas de estilo via document.styleSheets. Na verdade, isso retornará uma matriz de todas as folhas de estilo em sua página, mas você pode dizer em qual delas está por meio da document.styleSheets[styleIndex].hrefpropriedade. Depois de encontrar a folha de estilo que deseja editar, você precisa obter o conjunto de regras. Isso é chamado de "regras" no IE e "cssRules" na maioria dos outros navegadores. A maneira de saber em qual CSSRule você está é pela selectorTextpropriedade. O código de trabalho é mais ou menos assim:

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.

Deixe-me saber como isso funciona para você e, por favor, comente se encontrar algum erro.

Mike
fonte
1
Alterar o CSS dessa forma é muito mais rápido se você tiver mais de 100 elementos. Digamos, por exemplo, mudar todas as células em uma determinada parte de uma mesa de uma vez.
EdH
5
Não consigo encontrar rule.valueem FF 20. Há rule.style, no entanto, que é configurável e se comporta como element.style. Cf. https://developer.mozilla.org/en-US/docs/DOM/CSSStyleRule . Verificar rule.type == rule.STYLE_RULEtambém pode ser uma boa ideia antes de acessar rule.selectorText.
Christian Aichinger de
1
ISSO FOI INCRÍVEL! Eu estava trabalhando em transições de imagem e o CSS realmente fica mais lento quando você começa a colocar uma imagem grande em 36 URIs separados para fatiar. Isso apenas tirou uma tonelada de sobrecarga do meu script. Obrigado!
Jason Maggard
document.styleSheets[styleIndex].cssRules.[ruleIndex].style = {'color':'red', 'background-color':'green'};funcionou para mim, obrigado!
Pavel
43

Por favor! Basta perguntar a w3 ( http://www.quirksmode.org/dom/w3c_css.html )! Ou, na verdade, demorei cinco horas ... mas aqui 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
    }
}

A função é realmente fácil de usar .. exemplo:

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

Ah ..


EDITAR: como @ user21820 descreveu em sua resposta, pode ser um pouco desnecessário alterar todas as folhas de estilo na página. O script a seguir funciona com IE5.5, bem como com o Google Chrome mais recente, e adiciona apenas a função css () descrita acima.

(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
fonte
Implementação muito fácil. Obrigado
Kaleb Anderson
1
Há um motivo para modificar cada folha de estilo em vez de apenas uma única recém-criada como na minha resposta?
user21820
Implementação muito boa. Parabéns a você, senhor.
Jason Maggard
1
@ user21820, provavelmente não. Acho que realmente queria estar no lado seguro .. Resposta finalmente atualizada, parabéns para você :)
Leonard Pauli
10

Reunindo o código nas respostas, escrevi esta função que parece funcionar bem no meu 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 é uma forma de colocar valores no css que serão usados ​​no JS mesmo que não sejam compreendidos pelo navegador. por exemplo, maxHeight para um tbody em uma tabela rolada.

Ligar :

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

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

FrViPofm
fonte
1
Se o estilo estiver embutido na página HTML, document.styleSheets[m].hrefserá nulo e falhará.
JCM de
4

Não sei por que as outras soluções percorrem toda a lista de folhas de estilo do documento. Fazer isso cria uma nova entrada em cada folha de estilo, que é ineficiente. Em vez disso, podemos simplesmente anexar uma nova folha de estilo e simplesmente adicionar nossas regras CSS desejadas lá.

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

Observe que podemos substituir até mesmo os estilos embutidos definidos diretamente nos elementos adicionando "! Important" ao valor da propriedade, a menos que já existam declarações de estilo "! Important" mais específicas para essa propriedade.

user21820
fonte
1
Consulte developer.mozilla.org/en-US/docs/Web/API/CSSStyleSheet/… para uma versão mais complicada.
user21820
1
Muito verdadeiro. Certifique-se de usar .addRule (seletor, propriedade + ':' + valor) se .insertRule falhar (para suporte anterior ao IE9).
Leonard Pauli
3

Não tenho representante suficiente para comentar, então formarei uma resposta, mas é apenas uma demonstração do problema em questão.

Parece que, quando os estilos de elemento são definidos em folhas de estilo, eles não são visíveis para getElementById ("someElement"). Style

Este código ilustra o problema ... Código abaixo em jsFiddle .

No Teste 2, na primeira chamada, o valor dos itens deixados é indefinido, e assim, o que deveria ser uma simples alternância fica confuso. Para meu uso, definirei meus valores de estilo importantes inline, mas isso parece anular parcialmente o propósito da folha de estilo.

Aqui está o código da 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 isso ajude a esclarecer o problema.

Pular

BentFX
fonte
2

Você pode obter os estilos "calculados" de qualquer elemento.

O IE usa algo chamado "currentStyle", o Firefox (e presumo que outros navegadores "compatíveis com o padrão") usa "defaultView.getComputedStyle".

Você precisará escrever uma função de navegador cruzado para fazer isso ou usar uma boa estrutura Javascript como prototype ou jQuery (pesquise "getStyle" no arquivo javascript prototype e "curCss" no arquivo jquery javascript).

Dito isso, se você precisa da altura ou largura, provavelmente deve usar element.offsetHeight e element.offsetWidth.

O valor retornado é Nulo, então se eu tiver Javascript que precisa saber a largura de algo para fazer alguma lógica (eu aumento a largura em 1%, não para um valor específico)

Lembre-se, se você adicionar um estilo embutido ao elemento em questão, ele pode atuar como o valor "padrão" e será legível por Javascript no carregamento da página, uma vez que é a propriedade de estilo embutido do elemento:

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

fonte
0

Esta essência simples de 32 linhas permite que você identifique uma determinada folha de estilo e altere seus estilos com muita facilidade:

var styleSheet = StyleChanger("my_custom_identifier");
styleSheet.change("darkolivegreen", "blue");
Solendil
fonte
0

Nunca vi nenhum uso prático disso, mas você provavelmente deve considerar as folhas de estilo DOM . No entanto, eu honestamente acho que é um exagero.

Se você simplesmente deseja obter a largura e a altura de um elemento, independentemente de onde as dimensões estão sendo aplicadas, basta usar element.offsetWidthe element.offsetHeight.

Rakesh Pai
fonte
Meu uso: <style> #tid {width: 10%; } </style> <div id = 'tid' onclick = "boost ('tid')"> </div> o aumento irá verificar se a largura é <100%, se assim for, aumentará 1%. document.getElementById.style.width retorna nulo porque não há valor embutido. Existe uma maneira mais simples do que as folhas de estilo DOM?
Coltin
0

Talvez tente isto:

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
fonte