Henry: CSS Sytle direkt ändern

Hallo,

wenn man global das Style ändern möchte gäbs zwar verschiedene Möglichkeiten mit append oder Queryselectorall+schleife. Ich hatte irgendwann auchmal eine Option genutzt die mir sinnvoll schien. Find edie im Moment aber leider nicht und hab daher mal neu gebastelt, bin nicht sicher ob die Grundidee aber die Gleiche ist.

<style id="stl1">
.xy{color:teal;}
</style>

<p class="xy">Hello World!</p>
<p id="p2">Hello World!</p>
<p class="xy">Hello World!</p>

<button onclick="alert(document.documentElement.outerHTML);">source</button>
<button onclick="stl1.innerHTML = '.xy{color:red;}'">change CSS</button>

Mir gehts darum, dass sich alle Elemente einer bestimmten Klasse ohne Anhänge des Doms oder Schleifen, ändern. Ist mein Ansatz OK, oder gibts ne sinnvollere/einfachere Möglichkeit?

Gruss
Henry

--
Meine Meinung zu DSGVO & Co:
„Principiis obsta. Sero medicina parata, cum mala per longas convaluere moras.“

akzeptierte Antworten

  1. Hallo Henry,

    das ist im gezeigten Spezialfall sicherlich einfacher, als über document.styleSheets und darin über die cssRules zu laufen und sich eine Regel herauszusuchen.

    Und es funktioniert auch in Browsern, die das CSS API nicht implementieren. Es setzt nur voraus, dass Du für jede Regel, die Du so patchen willst, ein eigenes style-Element vorhältst, und Du kannst keine Werte in extern geladenen Stylesheets überschreiben.

    Aber, äh, solche Browser sind aus den 90er Jahren. Das CSSStyleSheet Objekt wird schon vom IE4 unterstützt. Insofern könnte man das auch so tun:

    findRule sucht eine CSS Style Rule mit einem bestimmten Selektor in einem style-Element mit einer bestimmten ID (bei externen Sheets könnte man auch über href gehen), und setzt darin dann das gewünschte Property auf den gewünschten Wert.

    function findRule(styleId, selector) {
       let styleElem = document.getElementById("stl1");
       for (let rule of styleElem.sheet.cssRules) {
          if (rule.type != 1) continue;
          let selectors = rule.selectorText.split(", ");
          if (rule.selectorText == ".xy")
          
       }
    }
    
    function changeStyle(id, selector, property, value) {
       let rule = findRule(id, selector);
       if (rule)
          rule.style[property] = value;
    }
    
    <button onclick="changeStyle('stl1', '.xy', 'color', 'red')">Red Alert</button>
    

    Das ist alles unpräzise, CSS erlaubt ja mehr als eine Rule mit einem bestimmten Selektor. Für einen produktiven Einsatz müsste man da genauere Selektion einbauen. Oder man pfeift auf den IE und macht es modern, mit custom propeties:

    .xy {
       color: var(--xy-color);
    }
    
    body {
       --xy-color: teal;
    }
    
    <body>
    <button onclick="document.body.style.setProperty('--xy-color', 'red')">Red Alert</button>
    

    Das hängt den Internet Explorer ab, aber die Evergreen-Browser können das alle.

    Rolf

    --
    sumpsi - posui - obstruxi
    1. Hi,

      Oder:

      im Stylesheet:

      .xy {
         color: teal;
      }
      
      .special .xy {
         color: red;
      }
      

      und im Javascript einfach dem document.body die Klasse 'special' je nach Bedarf hinzufügen/wegnehmen.

      cu,
      Andreas a/k/a MudGuard

      1. Hallo MudGuard,

        im Stylesheet:

        .xy {
           color: teal;
        }
        
        .special .xy {
           color: red;
        }
        

        und im Javascript einfach dem document.body die Klasse 'special' je nach Bedarf hinzufügen/wegnehmen.

        glaube nicht oder? Das war ja die Eingangsfrage, will ich damit mehrere Elemente gleichzeitig ändern, müsste ich ja doch wieder eine Schleife durchlaufen oder nicht?

        --
        Meine Meinung zu DSGVO & Co:
        „Principiis obsta. Sero medicina parata, cum mala per longas convaluere moras.“
        1. Hallo Henry,

          Mir gehts darum, dass sich alle Elemente einer bestimmten Klasse ohne Anhänge des Doms oder Schleifen, ändern

          Ja, das hab ich überlesen.

          In dem Moment, wo Du an einem Element eine Klasse oder ein Attribut veränderst, wird die Anwendbarkeit sämtlicher CSS Regeln neu bewertet. Je näher das geänderte Element dem Root-Element im DOM ist, desto mehr Elemente können davon betroffen sein. Wie die Browser das performant hinbekommen, ist auf größeren Seiten eine Herausforderung. Hatten wir nicht neulich einen Thread zum "Performancekiller CSS"? Das kann durchaus passieren.

          Das Hinzufügen der Klasse special an den body macht die .special .xy Regel wirksam und aktiviert in dem Moment, wo die Klasse am body erscheint, die Farbe Rot für alle Nachfahren-Elemente des Body, die die Klasse xy tragen.

          Außer für die Elemente, die durch andere Regeln mit höherer Spezifizät eine andere Farbe bekommen.

          Man müsste das mal genauer betrachten; ich weiß nur nicht, wie man das messbar hinbekommen kann. Das Ändern eines custom property, wie ich vorschlug, betrifft nur die angewendeten Regeln und verändert nicht die Anwendbarkeit des ganzen Regelwerks. Was ist performanter: Custom Property ändern oder eine Klasse setzen und eine Regel aktivieren?

          Rolf

          --
          sumpsi - posui - obstruxi
          1. Hallo Rolf,

            Man müsste das mal genauer betrachten; ich weiß nur nicht, wie man das messbar hinbekommen kann. Das Ändern eines custom property, wie ich vorschlug, betrifft nur die angewendeten Regeln und verändert nicht die Anwendbarkeit des ganzen Regelwerks. Was ist performanter: Custom Property ändern oder eine Klasse setzen und eine Regel aktivieren?

            ich denke dein Vorschlag mit den Variabeln ist ganz gut. Habs mal getestet, nur eines wundert mich, warum initial nicht greift.

            Gruss
            Henry

            --
            Meine Meinung zu DSGVO & Co:
            „Principiis obsta. Sero medicina parata, cum mala per longas convaluere moras.“
            1. Hallo Henry,

              warum initial nicht greift.

              Tjaaaa.

              CSS 1 sagt: Der initial-Wert für display ist block.

              CSS 2 und 3 sagen: Der initial-Wert für display ist inline.

              Alles andere ist Sache des Browser-Stylesheets.

              Das SelfWiki sagt: Der Default hängt vom Element ab. Was de facto eine Lüge für Kinder ist - es ist nicht falsch, aber auch nicht die vollständige Wahrheit.

              TAPP TAPP tapp ... ... tippeditippeditapp, klick ... ... tapp TAPP TAPP

              So, jetzt nicht mehr.

              Da muss ich aber im Wiki nochmal genau gucken und Specs studieren. Die Darstellung von unset und revert bedarf genauerer Erklärung.

              done

              Danke für den Stups, Henry 😀

              Rolf

              --
              sumpsi - posui - obstruxi