Nik: Regulärer Ausdruck

Hallo,

Kann ich alle DIVs unsichtbar machen, deren ID nach einer Konstante eine beliebige Zahl haben?

Ich habe meine DIVs nun so aufgebaut, daß sie ID='konstante_123' oder ID='konstante_1345' heißen.

Und ich würde gerne per onclick-Eventhandler alle Layer auf display:none setzen, die mit konstante_ beginnen.

Nik

  1. Hi,

    onclick dem body eine klasse "foo" geben. Folgendes CSS hinzufügen:

    .foo [id^="konstante_"] {  
        display: none;  
    }
    

    Blendet dann allerdings auch elemente mit IDs wie "konstante_bar" aus. Also nicht nur ziffern.
    Falls das ein Problem darstellt würde ich dazu raten allen Elementen die ausgeblendet werden sollen eine gemeinsame class zu geben.

    ~dave

    1. Falls das ein Problem darstellt würde ich dazu raten allen Elementen die ausgeblendet werden sollen eine gemeinsame class zu geben.

      Dazu würde ich sowieso raten. Mit Klassen kann man die Semantik von html-Dokumenten weiter anreichern und die div-Elemente in diesem Beispiel scheinen so Bedeutungsschwanger zu sein, dass es gerade danach reicht.

      1. Dazu würde ich sowieso raten. Mit Klassen kann man die Semantik von html-Dokumenten weiter anreichern und die div-Elemente in diesem Beispiel scheinen so Bedeutungsschwanger zu sein, dass es gerade danach reicht.

        Ok, ich habe jetzt den Einträgen eine Klasse zugeordnet.

        Aber ich such nun schon seit etlicher Zeit danach, wie ich per Javascript allen Elementen einer Klasse eine andere Klasse zuordnen kann oder aber die Style-Eigenschaft einer Klasse verändern kann.

        Bei IDs ist es ja einfach, aber bei Klassen?

        Nik

        1. Aber ich such nun schon seit etlicher Zeit danach, wie ich per Javascript allen Elementen einer Klasse eine andere Klasse zuordnen kann

          var class1 = document.querySelectorAll('.class1');  
            
          for ( var i=0, l=class1.length; i<l; i += 1 ) {  
             class1[ i ].classList.add('class2');  
          }
          

          oder aber die Style-Eigenschaft einer Klasse verändern kann.

          Das lässt man besser bleiben. Man würde sowas mit CSSOM machen.

          Bei IDs ist es ja einfach, aber bei Klassen?

          Selbe Vorgehensweise, nur dass du Üblicherweise mit NodeLists zu tun hast und nicht mit einzelnen Elementen.

          1. @@1UnitedPower:

            nuqneH

            var class1 = document.querySelectorAll('.class1');

            for ( var i=0, l=class1.length; i<l; i += 1 ) {
               class1[ i ].classList.add('class2');
            }

              
            Auch das lässt man besser bleiben. Es dürfte in so ziemlich allen denkbaren Fällen unnötig sein.  
              
            Qapla'
            
            -- 
            „Talente finden Lösungen, Genies entdecken Probleme.“ (Hans Krailsheimer)
            
            1. Auch das lässt man besser bleiben. Es dürfte in so ziemlich allen denkbaren Fällen unnötig sein.

              Das sehe ich anders. Nehmen wir als Beispiel einen virtuellen Posteingang, dort habe ich eine Liste von eingegangen Nachrichten, jetzt möchte ich gerne eine Button haben, der alle ungelesenen Nachrichten markiert.

              Beispiel:

                
              <ul>  
                 <li class="read">...</li>  
                 <li class="read">...</li>  
                 <li class="unread">...</li>  
                 <li class="read">...</li>  
                 <li class="read">...</li>  
                 <li class="unread">...</li>  
                 <li class="unread">...</li>  
              </ul>  
              
              

              In dem Fall fände ich es natürlicher den ungelesenen Nachrichten eine Klasse "marked" hinzuzufügen. Laut deiner Methode würde ich dem ul-Element eine Klasse "mark-unread" oder ähnliches verpassen, das wäre auch zielführend, aber würde sich imho. unnatürlich anfühlen.

              Ansonsten gebe ich dir Recht, dass es in den _meisten_ Fällen mit Kanonen auf Spatzen geschossen ist.

              1. Das sehe ich anders. Nehmen wir als Beispiel einen virtuellen Posteingang, dort habe ich eine Liste von eingegangen Nachrichten, jetzt möchte ich gerne eine Button haben, der alle ungelesenen Nachrichten markiert.

                Beispiel:

                ... Das habe ich mal schnell nach der Idee von Dave und gemäß dem Hinweis von molily realisiert. (Was nicht heißt, dass ich von der einfachen Lösung als allgemeiner Präferenz abgehe)
                Die "Markierung" ist allerdings das "Verschwinden" aller gelesenen Nachrichten bzw. des Spams.

                <html>  
                <head>  
                <title>Test</title>  
                <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />  
                  
                <script type="text/javascript">
                
                function toggle_display(o,s) {  
                  if (o.checked) {  
                      remove_classname('liste',s)  
                  } else {  
                      add_classname('liste',s)  
                  }  
                }  
                  
                function add_classname(id,classname) {  
                    o=document.getElementById(id);  
                    o.className=o.className + ' ' + classname;  
                }  
                  
                function remove_classname(id,classname) {  
                    o=document.getElementById(id);  
                    s=o.className;  
                    s_new='';  
                    ar=s.split(" ");  
                    for (i=0; i<ar.length; i++) {  
                       if (ar[i] != classname) {  
                          s_new = s_new + ' ' + ar[i];  
                       }  
                    }  
                    o.className=s_new;  
                }
                
                </script>  
                  
                <style type="text/css">
                
                  ul.hide_read .read,  ul.hide_spam .spam {  
                      display:none;  
                  }
                
                </style>  
                  
                </head>  
                <body>  
                <ul id="liste">  
                   <li class="read">(gelesen)</li>  
                   <li class="read">(gelesen)</li>  
                   <li class="unread">(ungelesen)</li>  
                   <li class="spam">(spam)</li>  
                   <li class="read">(gelesen)</li>  
                   <li class="unread">(ungelesen)</li>  
                   <li class="unread">(ungelesen)</li>  
                </ul>  
                  
                <input id="show_read" type="checkbox" checked onchange="toggle_display(this, 'hide_read')"> gelesene anzeigen<br>  
                <input id="show_spam" type="checkbox" checked onchange="toggle_display(this, 'hide_spam')"> Spam anzeigen  
                </body>
                

                Ich sehe gerade, es ist noch nicht perfekt ('liste' sollte auch beim Aufruf übergeben werden), es funktioniert aber.

                Jörg Reinholz

                1. Hi,

                  Das sehe ich anders. Nehmen wir als Beispiel einen virtuellen Posteingang, dort habe ich eine Liste von eingegangen Nachrichten, jetzt möchte ich gerne eine Button haben, der alle ungelesenen Nachrichten markiert.

                  Beispiel:

                  Ich habe mir mal erlaubt, das Beispiel mit meinem derzeitigen Lieblingsframework (Angular.Js) nachzubauen:

                  <!doctype html>  
                  <html>  
                    <head>  
                      <meta charset="utf-8"/>  
                      <title></title>  
                    </head>  
                    <body ng-app="myApp">  
                    
                      <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.0.6/angular.min.js"></script>  
                    
                      <script>  
                      'use strict';  
                    
                      angular.module('myApp', [])  
                        .controller('InboxCtrl', function ($scope) {  
                    
                          $scope.currentMail = null;  
                          $scope.mails = [  
                            {  
                              title: "E-Mail 1",  
                              body: "This is e-mail 1",  
                              read: false  
                            },  
                            {  
                              title: "E-Mail 2",  
                              body: "This is e-mail 2",  
                              read: false  
                            },  
                            {  
                              title: "E-Mail 3",  
                              body: "This is e-mail 3",  
                              read: false  
                            },  
                            {  
                              title: "E-Mail 4",  
                              body: "This is e-mail 4",  
                              read: false  
                            },  
                            {  
                              title: "E-Mail 5",  
                              body: "This is e-mail 5",  
                              read: false  
                            }  
                          ];  
                    
                          function markEmailAsRead(email) {  
                            email.read = true;  
                          }  
                    
                          function markEmailAsUnRead(email) {  
                            email.read = false;  
                          }  
                    
                          $scope.markAllAsRead = function() {  
                            angular.forEach($scope.mails, markEmailAsRead);  
                          };  
                    
                          $scope.showMail = function(mail) {  
                            $scope.currentMail = mail;  
                            markEmailAsRead(mail);  
                          };  
                    
                          $scope.markAllAsUnRead = function() {  
                            angular.forEach($scope.mails, markEmailAsUnRead);  
                          }  
                        });  
                    
                      </script>  
                      <div ng-controller="InboxCtrl">  
                        <ul>  
                          <li ng-repeat="mail in mails" ng-click="showMail(mail)">  
                            {{ mail.title }}  
                            <span ng-hide="mail.read">(New)</span>  
                          </li>  
                        </ul>  
                        <button type="button" ng-click="markAllAsRead()">  
                          Alle als gelesen markieren  
                        </button>  
                        <button type="button" ng-click="markAllAsUnRead()">  
                          Alle als ungelesen markieren  
                        </button>  
                    
                        <section ng-show="currentMail">  
                          <h2>{{ currentMail.title }}</h2>  
                          <p>{{currentMail.body }}</p>  
                        </section>  
                      </div>  
                    
                    </body>  
                  </html>  
                  
                  

                  Wie du siehst, benutze ich hier überhaupt kein CSS mehr. Durch Direktiven (in diesem Falle ng-hide/ng-show) wird sofort ersichtlich, wann was ein- bzw. ausgeblendet wird.

                  Bis die Tage,
                  Matti

                  1. Ich habe mir mal erlaubt, das Beispiel mit meinem derzeitigen Lieblingsframework (Angular.Js) nachzubauen:

                    Vielen Dank für die Mühe. Du bist allerdings über das Ziel hinausgeschossen; mein Beispiel zielte bloß auf die Anreicherung von Semantik durch Class-Tokens ab.

                  2. Ich habe mir mal erlaubt, das Beispiel mit meinem derzeitigen Lieblingsframework (Angular.Js) nachzubauen:

                    Das sieht tatsächlich gut aus (ich meine nicht die Optik). Daten als JSON-Notation (die ich leicht auf dem Server erzeugen kann), das Template sieht fast wie smarty aus und es gibt sogar eine für mich(!) brauchbare Einstiegs-Dokumentation, aus der ich leicht ableiten kann, was ich zu tun habe.

                    Danke. Werde ich mal versuchen wenn ich auf ein "Nichttriviales Problem"(*) stoße.

                    Hast Du eine Linkliste zu Angular.Js? (Dokumentationen, Beispiele, Ebooks, Referenz(en))?

                    Jörg Reinholz

                    *) "Nichttriviales Problem": Das ist eigentlich eine Crux. Job eines "Programmierers" oder Softwaredesigners ist es doch, komplizierte (nicht triviale) Sachverhalte (Probleme) zu trivialen, geradezu atomaren Handlungsanweisungen (Befehlen) herunterzubrechen.

                    1. Hi,

                      Ich habe mir mal erlaubt, das Beispiel mit meinem derzeitigen Lieblingsframework (Angular.Js) nachzubauen:

                      Das sieht tatsächlich gut aus (ich meine nicht die Optik). Daten als JSON-Notation (die ich leicht auf dem Server erzeugen kann), das Template sieht fast wie smarty aus und es gibt sogar eine für mich(!) brauchbare Einstiegs-Dokumentation, aus der ich leicht ableiten kann, was ich zu tun habe.

                      Danke. Werde ich mal versuchen wenn ich auf ein "Nichttriviales Problem"(*) stoße.

                      Hast Du eine Linkliste zu Angular.Js? (Dokumentationen, Beispiele, Ebooks, Referenz(en))?

                      Die Webseite ist eigentlich ganz OK.

                      Ansonsten würde ich dir einen der vielen Screencasts und Vorträge auf youtube empfehlen, die von Brad Green oder Misko Hevery kommen. Vom letzteren sind auch die sehr guten Clean-Code-Vorträge, die z.B. Sven Rautenberg auch öfter erwähnt und empfiehlt.

                      Bis die Tage,
                      Matti

                2. Das sehe ich anders. Nehmen wir als Beispiel einen virtuellen Posteingang, dort habe ich eine Liste von eingegangen Nachrichten, jetzt möchte ich gerne eine Button haben, der alle ungelesenen Nachrichten markiert.

                  Die "Markierung" ist allerdings das "Verschwinden" aller gelesenen Nachrichten bzw. des Spams.

                  Ihr verwechselt da etwas: Änderungen am DOM und Änderungen auf Daten-Ebene.

                  Man neigt dazu, das DOM als Datenspeicher zu missbrauchen. Klassen regeln also nicht nur die Darstellung, sondern es sind quasi Felder gewisser Datensätze. Insbesondere jQuery regt einen mit jQuery.prototype.data() dazu an, Daten an DOM-Elementen zu speichern.

                  Das ist mittlerweile verpönt. Nicht-triviale JavaScript-Anwendungsfälle werden heutzutage mit einer MVC-artigen Architektur gelöst (oder MVVM, MVP…), bei der sämtliche Datenlogik in Model zu finden ist und es ferner Views zur Darstellung dieser Daten im DOM gibt. Mattis Beispiel mit Angular.js zeigt schön, wie man Model- und View-Logik hier trennen würde.

                  Die Information »Nachricht wurde gelesen«, »Nachricht wurde markiert« usw. wird dann nicht mehr direkt im DOM gespeichert. Das DOM repräsentiert die Daten nur, es wird nicht zum Speichern und Lesen dieses Nachrichtenstatus benutzt – das Model ist die einzige »Quelle der Wahrheit«.

                  Ein Posteingang ist dementsprechend eine Liste von Nachrichten-Models, und »wurde gelesen«, »wurde markiert« wird an den jeweiligen Models gespeichert. Die View erzeugt daraus eine Liste. Wie Klassen oder sonstige Angriffspunkte für Stylesheets gesetzt werden, ist der View überlassen. Wenn alle Nachrichten gelesen wurden, kann sie aus Performance-Gründen einfach zentral eine Klasse setzen, andernfalls jedem li-Element einzeln eine entsprechende Klasse geben.

                  Einen Überblick über MVC-Lösungen bietet TodoMVC. Interessierte können sich auch Chaplin ansehen (Link in der Signatur). ;)

                  Viele Grüße,
                  Mathias

                  1. Das sehe ich anders. Nehmen wir als Beispiel einen virtuellen Posteingang, dort habe ich eine Liste von eingegangen Nachrichten, jetzt möchte ich gerne eine Button haben, der alle ungelesenen Nachrichten markiert.

                    Die "Markierung" ist allerdings das "Verschwinden" aller gelesenen Nachrichten bzw. des Spams.

                    Ihr verwechselt da etwas: Änderungen am DOM und Änderungen auf Daten-Ebene.

                    Nein, ich denke du hast mich auch missverstanden. Das Beispiel war möglicherweise ungeeignet. Mir ging es lediglich um den Aspekt sprechende Class-Tokens an den geeigneten Stellen zu vergeben, die eine _beschreibende_, aber _nicht_ spezifizierende Rolle einnehmen.

                    Das Beispiel war dabei bewusst simpel gehalten, um den Fokus auf die Problemstellung zu lenken, weswegen ich auch absichtlich nicht auf die Darstellung eingangen bin. Klassennamen sind imho. auch über CSS-Direktiven hinaus nützlich. Ein komplexes Beispiel ala Angular.js oder Ember.js (mein Liebling) wäre imho. völliger overkill ( nichts desto trotz Danke Matti für dein Snippet).

        2. @@Nik:

          nuqneH

          Aber ich such nun schon seit etlicher Zeit danach, wie ich per Javascript allen Elementen einer Klasse eine andere Klasse zuordnen kann oder aber die Style-Eigenschaft einer Klasse verändern kann.

          Eben das solltest du nicht tun. Sondern per JavaScript Klassenzugehörigkeiten ändern – in dem Fall die Klasse eines übergeordneten Elements (bspw. body oder html), wie Dave schon sagte.

          Im CSS stehen dann zwei Regeln:

          .bar  
          {  
            /* Styles für Elemente der Klasse 'bar' */  
          }  
            
          .foo .bar  
          {  
            /* ergänzende Styles für Elemente der Klasse 'bar', wenn für body die Klasse 'foo' gesetzt ist */  
          }
          

          Qapla'

          --
          „Talente finden Lösungen, Genies entdecken Probleme.“ (Hans Krailsheimer)
          1. Sondern per JavaScript Klassenzugehörigkeiten ändern – in dem Fall die Klasse eines übergeordneten Elements (bspw. body oder html), wie Dave schon sagte.

            Wobei html und body die letzte Wahl wären. In einer größeren Website oder Webanwendung sollte man es tunlichst vermeiden, dass jedes Modul unkontrolliert auf html und body schreibt, wenn man eigentlich eine spezifische Menge von Elementen ansprechen will.

            Ich würde daher für »das nächstgelegene passende gemeinsame Elternelement« votieren. Meist gibt es ein solches: Bei Views und Widgets das Hauptelement, bei Tabellen table oder tbody, bei Listen ul/ol/dl, bei Abschnitten section/article/nav/aside.

            Grüße,
            Mathias

        3. Dazu würde ich sowieso raten. Mit Klassen kann man die Semantik von html-Dokumenten weiter anreichern und die div-Elemente in diesem Beispiel scheinen so Bedeutungsschwanger zu sein, dass es gerade danach reicht.

          Ok, ich habe jetzt den Einträgen eine Klasse zugeordnet.

          Dann hole die Elemente (Objekte) in ein Array, durchlaufe diesen und ordne den Objekten die gwünschten Eigenschaften zu. Beispiel:

          <html>  
          <head>  
          <title>Test</title>  
          <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />  
          <script type="text/javascript">  
          function display_class_elements (classname, display) {  
            var elements = document.getElementsByClassName(classname);  
            ex = elements.length;  
            for (var i = 0; i < ex; i++) {  
               elements[i].style.display = display;  
            }  
          }  
          </script>  
          </head>  
          <body>  
             <div class="test">Foo!</div>  
             <div class="test">Bar!</div>  
             <div>  
               <button onclick="display_class_elements('test', 'none')">verstecken</button>  
               <button onclick="display_class_elements('test', 'block')">anzeigen</button>  
             </div>  
          </body>
          

          Jörg Reinholz

          1. @@Jörg Reinholz:

            nuqneH

            Dann hole die Elemente (Objekte) in ein Array, durchlaufe diesen und ordne den Objekten die gwünschten Eigenschaften zu.

            Nei-en.

            elements[i].style.display = display;

            Mit JavaScript direkt Werte von CSS-Eigenschaften zu ändern ist sowieso in den allerwenigsten Fällen eine gute Idee.

            Qapla'

            --
            „Talente finden Lösungen, Genies entdecken Probleme.“ (Hans Krailsheimer)
            1. @@Jörg Reinholz:
              Mit JavaScript direkt Werte von CSS-Eigenschaften zu ändern ist sowieso in den allerwenigsten Fällen eine gute Idee.

              Hallo Gunnar!

              Definiere für mich und die anderen doch bitte das "in den allerwenigsten Fällen". Außer bei sehr vielen betroffenen Objekten (was für mich eher "in den allerwenigsten Fällen" zutrifft) sehe ich vordergründig zu dem Methode, einem übergeordneten Objekt (body) eine Klasse zuzuweisen und alles über Selektoren zu steuern, keinen Gewinn. Ich finde es sogar verwirrend, weil die Methode nicht gerade offensichtlich ist.

              Jörg Reinholz

              1. @@Jörg Reinholz:

                nuqneH

                … sehe ich vordergründig zu dem Methode, einem übergeordneten Objekt (body) eine Klasse zuzuweisen und alles über Selektoren zu steuern, keinen Gewinn. Ich finde es sogar verwirrend, weil die Methode nicht gerade offensichtlich ist.

                Ich finde es äußerst verwirrend, wenn Werte von CSS-Eigenschaften mit JavaScript geändert werden, weil eben dies nicht gerade offensichtlich ist.

                Qapla'

                --
                „Talente finden Lösungen, Genies entdecken Probleme.“ (Hans Krailsheimer)
                1. Hallo @@Gunnar

                  … sehe ich vordergründig zu dem Methode, einem übergeordneten Objekt (body) eine Klasse zuzuweisen und alles über Selektoren zu steuern, keinen Gewinn. Ich finde es sogar verwirrend, weil die Methode nicht gerade offensichtlich ist.

                  Ich finde es äußerst verwirrend, wenn Werte von CSS-Eigenschaften mit JavaScript geändert werden, weil eben dies nicht gerade offensichtlich ist.

                  Naja. Die Klassen-Bezeichnung war ja auch nicht richtig:

                  Lass dir das auf der Zunge zergehen: Elemente haben die Klasse "hidden", sind aber sichtbar.

                  (Aus deinem verlinktem Beitrag)

                  Nennt man die Klasse nicht "hidden" (was auch sonst nicht richtig ist, denn der Unterschied zwischen "visibility:hidden" und "display:none" ist ungefähr so groß wie der zwischen "Klo" und "Klos") sondern etwa "default_no_display" wird es logischer und derjenige, der die Eigenschaft display:none auf important gesetzt hat hätte sofort sehen können, dass das (sehr wahrscheinlich) unerwünschte Seiteneffekte hat.

                  Ich finde es äußerst verwirrend, wenn Werte von CSS-Eigenschaften mit JavaScript geändert werden, weil eben dies nicht gerade offensichtlich ist.

                  Du findest es offensichtlicher, wenn (wie Dave vorschlug - dem hast Du Dich ja angeschlossen) einem Element eine Klasse per Javascript hinzugefügt wird? Und was bitte passiert denn dann, wenn in einer der anderen (noch) zugeordneten Klassen just eine zu verändernde Eigenschaft das "!important" als Abzeichen auf der Brust hat?

                  Eben. Die Eigenschaft wird nicht überladen und Du hast das selbe Problem wie in Deinem Beispiel.

                  Freilich kann man das durch ein weiteres "!important" vielleicht beheben und sich über neue Seiteneffekte freuen.

                  Wenn man dann mal nachsucht, was, warum und wie funktioniert machen es die Klassen auch "nicht wirklich" einfacher. Erst ein Blick ins HTML, dann ins Javascript (bei der direkten Eigenschaftszuweisung ist hier Schluss) dann noch in den Stylesheet. Wenn man dann nochmal "die Runde drehen" darf, weil man nachschauen muss, welche Elemente denn Kindelemente von welchem Element sind wird es auch nicht besser - finde ich jedenfalls.

                  Also das "in den allermeisten Fällen" die direkte Lösung nicht sinnvoll wäre, dem vermag ich nicht zuzustimmen. In Einzelfällen (sehr viele Elemente) sehe ich das mit Blick auf Performance-Fragen ein.

                  Jörg Reinholz

                  1. Hi,

                    Ich finde es äußerst verwirrend, wenn Werte von CSS-Eigenschaften mit JavaScript geändert werden, weil eben dies nicht gerade offensichtlich ist.

                    Du findest es offensichtlicher, wenn (wie Dave vorschlug - dem hast Du Dich ja angeschlossen) einem Element eine Klasse per Javascript hinzugefügt wird?

                    Das macht es doch eigentlich recht einfach. Die Klassen, die im Dokument vorhanden sind, bestimmen das Design. Sowohl für die statischen als auch für die dynamischen Sachen. Eine einfache Regel, die man von vorne bis hinten durchziehen kann.

                    Andererseits: wenn ich wissen will, warum an irgendeiner Stelle etwas nicht so aussieht wie erwartet, öffne ich meine Dev-Tools, selektiere das entsprechende Element und sehe doch sofort, welche Eigenschaften es hat und welche Selektoren zutreffen.

                    Also das "in den allermeisten Fällen" die direkte Lösung nicht sinnvoll wäre, dem vermag ich nicht zuzustimmen. In Einzelfällen (sehr viele Elemente) sehe ich das mit Blick auf Performance-Fragen ein.

                    Performance sowohl im JavaScript-Teil, als auch bei der Anzahl der notwendigen Repaints. Und letzteres betrifft also nicht nur den Fall, dass du viele Elemente hast, sondern wenn jeder einzelne Repaint sehr teuer ist.

                    Bis die Tage,
                    Matti

                    1. sondern wenn jeder einzelne Repaint sehr teuer ist.

                      Das ist natürlich ein schlagendes Argument. Besonders bei langen oder "irre kompliziert" gebauten Seiten dürfte das zutreffen.

                      Jörg Reinholz

                      1. Hallo,

                        sondern wenn jeder einzelne Repaint sehr teuer ist.

                        Das ist natürlich ein schlagendes Argument. Besonders bei langen oder "irre kompliziert" gebauten Seiten dürfte das zutreffen.

                        Ganz so schlimm ist es nicht. Kein Browser zeichnet notwendig die gesamte Seite neu, wenn sich ein bestimmter Stil eines Elements ändert. Die Browser sind recht gut darin, das Zeichnen zu optimieren. Man kann in der Timeline des Web Inspectors sehen, welche Bereiche neu gezeichnet werden.

                        Und viele Pixel zeichnen muss der Browser letztlich ohnehin, wenn sich die Styles vieler Elemente ändern, auch beim Setzen einer Klasse

                        Allerdings sorgt eine Stiländerung dazu, dass Style-Caches invalidiert werden, Regeln erneut angewendet werden und ggf. ein Reflow ausgelöst wird. Ein Reflow passiert, wenn sich die Größe oder Positionierung von Elementen geändert hat, dann müssen große Teile der Site neu gelayoutet und also auch neu gezeichnet werden.

                        Übrigens muss eine Schleife, die den Stil von n Elementen anfasst, nicht notwendig n Reflows und Repaints auslösen:

                        var elements = document.querySelectorAll('.foo');  
                        for (var i = 0; l = elements.length; i < l; i++) {  
                          elements[i].style.color = 'red';  
                        }
                        

                        Das *kann* ein Browser so optimieren, dass nach Ablauf der Schleife alle betroffenen Bereiche neu gezeichnet werden. Beim Setzen von fontSize o.ä., was einen Reflow auslöst, könnte es der Browser ebenfalls optimieren. Auf der sichereren Seite ist man jedoch mit der Klassenlösung.

                        Siehe auch http://www.stubbornella.org/content/2009/03/27/reflows-repaints-css-performance-making-your-javascript-slow/.

                        Mathias

                        1. Siehe auch http://www.stubbornella.org/content/2009/03/27/reflows-repaints-css-performance-making-your-javascript-slow/.

                          Ja. Gerade das dort angegebene Beispiel mit einer nicht-fixen Tabelle hatte ich im Hinterkopf als ich von langen oder "irre kompliziert" gebauten Seiten schrieb. Das ist mir nämlich mal zu 486er-Zeiten (in den 90ern) aufgefallen, dass eine Webseite mit einer großen Tabelle zwar nach 5 Minuten (oder weniger) geladen war (14.400er Modem...) aber mehr als (ich glaube es waren) 12 Minuten brauchte um aufgebaut zu werden. Jedenfalls war das Modem mangels Datenverkehrs längst im timeout doch der Browser zeigte noch immer den Fortschrittsbalken.

                          Grund: Die Tabelle wird hinsichtlich der Spaltenbreiten mehrfach durchgerechnet und zumindest damals hat das der Browser (dürfte noch Netscape gewesen sein) nach jeder neu hinzukommenden Zeile gemacht.

                          Jörg Reinholz