Zmiana wartości CSS za pomocą JavaScript

105

Za pomocą javascript łatwo jest ustawić wbudowane wartości CSS. Jeśli chcę zmienić szerokość i mam html tak:

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

Wystarczy, że:

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

Zmieni to wbudowane wartości arkusza stylów. Zwykle nie stanowi to problemu, ponieważ styl wbudowany zastępuje arkusz stylów. Przykład:

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

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

Używając tego JavaScript:

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

Otrzymuję następujące informacje:

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

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

To jest problem, bo nie tylko nie chcę zmieniać wartości inline, jeśli szukam szerokości przed jej ustawieniem, kiedy mam:

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

Zwracana wartość to Null, więc jeśli mam JavaScript, który musi znać szerokość czegoś, aby wykonać jakąś logikę (zwiększam szerokość o 1%, a nie do określonej wartości), zwracając Null, gdy oczekuję ciągu "50% „tak naprawdę nie działa.

Więc moje pytanie: mam wartości w stylu CSS, które nie są umieszczone w tekście, jak mogę uzyskać te wartości? Jak mogę zmienić styl zamiast wartości wbudowanych, mając identyfikator?

Coltin
źródło
czy możesz edytować swój post? na początku są niekompletne zdania, nie jestem pewien, czego szukasz ...
Jason S
Nadal jestem trochę zdezorientowany, o co pytasz. Czy prosisz 1) o zmianę samego CSS, który zmieni wszystkie elementy naraz? lub 2) zmienić CSS dla pojedynczego elementu na raz?
Mike,
Jestem również zdezorientowany, jeśli chodzi o faktyczne pytanie. Aktualny styl obiektu niekoniecznie będzie taki sam, jak atrybut „style” tagu.
MattJ,
Przepraszam, że poprawię to, aby było bardziej przejrzyste Nie chcę ustawiać wbudowanego CSS. Chciałbym móc zwiększyć / zmniejszyć szerokość stylu. Edytuję z pełnym przykładem tego, czego szukam.
Coltin,

Odpowiedzi:

90

Ok, wygląda na to, że chcesz zmienić globalny CSS, który skutecznie zmieni jednocześnie wszystkie elementy stylu petikularnego. Niedawno nauczyłem się, jak to zrobić sam z samouczka Shawna Olsona . Możesz bezpośrednio odwołać się do jego kodu tutaj .

Oto podsumowanie:

Możesz pobrać arkusze stylów przez document.styleSheets. To faktycznie zwróci tablicę wszystkich arkuszy stylów na twojej stronie, ale możesz stwierdzić, na którym jesteś za pośrednictwem document.styleSheets[styleIndex].hrefwłaściwości. Po znalezieniu arkusza stylów, który chcesz edytować, musisz uzyskać zestaw reguł. Nazywa się to „regułami” w IE i „cssRules” w większości innych przeglądarek. Sposobem na stwierdzenie, na jakim CSSRule jesteś, jest selectorTextwłasność. Działający kod wygląda mniej więcej tak:

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.

Daj mi znać, jak to działa w Twoim przypadku i proszę o komentarz, jeśli zauważysz jakieś błędy.

Mikrofon
źródło
1
Zmiana CSS w ten sposób jest znacznie szybsza, jeśli masz ponad 100 elementów. Powiedz na przykład, zmieniając jednocześnie wszystkie komórki w określonej części tabeli.
EdH
5
Nie mogę znaleźć rule.valuew FF 20. Jest rule.stylejednak to , co można ustawić i zachowuje się jak element.style. Por. https://developer.mozilla.org/en-US/docs/DOM/CSSStyleRule . rule.type == rule.STYLE_RULEPrzed uzyskaniem dostępu dobrym pomysłem może być również sprawdzenie rule.selectorText.
Christian Aichinger
1
TO BYŁO NIESAMOWITE! Pracowałem nad przejściami obrazów, a CSS naprawdę zwalnia, gdy zaczynasz umieszczać duży obraz w 36 osobnych identyfikatorach URI do cięcia na plasterki. To tylko spowodowało, że mój scenariusz zajął mnóstwo czasu. Dzięki!
Jason Maggard,
document.styleSheets[styleIndex].cssRules.[ruleIndex].style = {'color':'red', 'background-color':'green'};pracował dla mnie, dzięki!
Pavel
43

Proszę! Po prostu zapytaj w3 ( http://www.quirksmode.org/dom/w3c_css.html )! A właściwie zajęło mi to pięć godzin ... ale oto jest!

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

Funkcja jest naprawdę łatwa w użyciu ... przykład:

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

O..


EDYCJA: jak @ user21820 opisał w swojej odpowiedzi, zmiana wszystkich arkuszy stylów na stronie może być trochę niepotrzebna. Poniższy skrypt współpracuje z IE5.5 oraz najnowszą przeglądarką Google Chrome i dodaje tylko opisaną powyżej funkcję css ().

(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
źródło
Poważnie łatwa implementacja. Dzięki
Kaleb Anderson
1
Czy istnieje powód, aby modyfikować każdy arkusz stylów, a nie tylko jeden nowo utworzony, jak w mojej odpowiedzi?
user21820
Bardzo fajna realizacja. Uznanie dla pana.
Jason Maggard
1
@ user21820, prawdopodobnie nie. Chyba naprawdę chciałem być po bezpiecznej stronie .. Odpowiedź w końcu zaktualizowana, chwała wam :)
Leonard Pauli
10

Zbierając kod w odpowiedziach, napisałem tę funkcję, która wydaje się działać dobrze na moim 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
}

Jest to sposób na umieszczenie wartości w css, które będą używane w JS, nawet jeśli nie są zrozumiałe dla przeglądarki. np. maxHeight dla tbody w przewijanej tabeli.

Połączenie :

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

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

FrViPofm
źródło
1
Jeśli styl jest osadzony na stronie HTML, document.styleSheets[m].hrefbędzie miał wartość NULL i zakończy się niepowodzeniem.
JCM
4

Nie wiem, dlaczego inne rozwiązania przechodzą przez całą listę arkuszy stylów dla tego dokumentu. Spowoduje to utworzenie nowego wpisu w każdym arkuszu stylów, co jest nieefektywne. Zamiast tego możemy po prostu dołączyć nowy arkusz stylów i po prostu dodać tam nasze żądane reguły CSS.

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

Zauważ, że możemy nadpisać nawet style wbudowane ustawione bezpośrednio w elementach, dodając „! Important” do wartości właściwości, chyba że istnieją już bardziej szczegółowe deklaracje stylu „! Important” dla tej właściwości.

user21820
źródło
1
Zobacz developer.mozilla.org/en-US/docs/Web/API/CSSStyleSheet/…, aby uzyskać bardziej skomplikowaną wersję.
user21820
1
Bardzo prawdziwe. Pamiętaj, aby użyć .addRule (selektor, właściwość + ':' + wartość), jeśli .insertRule nie powiedzie się (dla obsługi starszych niż IE9).
Leonard Pauli
3

Nie mam wystarczającego przedstawiciela do komentowania, więc sformatuję odpowiedź, ale jest to tylko demonstracja problemu.

Wygląda na to, że kiedy style elementów są zdefiniowane w arkuszach stylów, nie są one widoczne dla metody getElementById ("someElement"). Style

Ten kod ilustruje problem ... Kod z dołu na jsFiddle .

W teście 2, przy pierwszym wywołaniu, pozostała wartość pozycji jest niezdefiniowana, więc to, co powinno być prostym przełącznikiem, zostaje pomieszane. Na mój użytek zdefiniuję moje ważne wartości stylu w tekście, ale wydaje się, że częściowo pokonuje to cel arkusza stylów.

Oto kod strony ...

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

Mam nadzieję, że pomoże to wyjaśnić tę kwestię.

Pominąć

BentFX
źródło
2

Możesz uzyskać „obliczone” style dowolnego elementu.

IE używa czegoś, co nazywa się „currentStyle”, Firefox (i zakładam, że inne przeglądarki „zgodne ze standardami”) używa „defaultView.getComputedStyle”.

Aby to zrobić, musisz napisać funkcję obsługującą przeglądarkę lub użyć dobrego frameworka Javascript, takiego jak prototype lub jQuery (wyszukaj „getStyle” w prototypowym pliku javascript i „curCss” w pliku javascript jquery).

To powiedziawszy, jeśli potrzebujesz wysokości lub szerokości, prawdopodobnie powinieneś użyć element.offsetHeight i element.offsetWidth.

Zwracana wartość to Null, więc jeśli mam JavaScript, który musi znać szerokość czegoś, aby wykonać jakąś logikę (zwiększam szerokość o 1%, a nie do określonej wartości)

Pamiętaj, że jeśli dodasz styl wbudowany do danego elementu, może on działać jako wartość „domyślna” i będzie czytelny dla JavaScript podczas ładowania strony, ponieważ jest to właściwość stylu wbudowanego elementu:

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

źródło
0

Ta prosta, 32-liniowa treść pozwala zidentyfikować dany arkusz stylów i bardzo łatwo zmienić jego style:

var styleSheet = StyleChanger("my_custom_identifier");
styleSheet.change("darkolivegreen", "blue");
solendil
źródło
0

Nigdy nie widziałem żadnego praktycznego zastosowania tego, ale prawdopodobnie powinieneś rozważyć arkusze stylów DOM . Jednak szczerze uważam, że to przesada.

Jeśli chcesz po prostu uzyskać szerokość i wysokość elementu, niezależnie od tego, skąd wymiary są stosowane, po prostu użyj element.offsetWidthi element.offsetHeight.

Rakesh Pai
źródło
Moje zastosowanie: <style> #tid {width: 10%; } </style> <div id = 'tid' onclick = "Increase ('tid')"> </div> zwiększenie sprawdza, czy szerokość wynosi <100%, jeśli tak, to zwiększy się o 1%. document.getElementById.style.width zwraca wartość null, ponieważ nie ma wartości wbudowanej. Czy istnieje prostszy sposób niż arkusze stylów DOM?
Coltin,
0

Może spróbuj tego:

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
źródło