Gibt es eine Möglichkeit, mit classList mehrere Klassen in einer einzigen Anweisung hinzuzufügen / zu entfernen?

164

Bisher muss ich das machen:

elem.classList.add("first");
elem.classList.add("second");
elem.classList.add("third");

Dies ist zwar in jQuery möglich, aber so

$(elem).addClass("first second third");

Ich würde gerne wissen, ob es eine native Möglichkeit zum Hinzufügen oder Entfernen gibt.

Enrique Moreno Zelt
quelle

Antworten:

313
elem.classList.add("first");
elem.classList.add("second");
elem.classList.add("third");

ist gleich

elem.classList.add("first","second","third");
iwege
quelle
15
Und wenn Sie ein Array mit mehreren Klassennamen anwenden möchten, müssen Sie Folgendes aufrufen: DOMTokenList.prototype.add.apply (elem.classList, ['first', 'second', 'Third']);
Emanuel Kluge
8
Firefox unterstützt es zum Zeitpunkt des Schreibens ebenfalls nicht. Meine Antwort liefert eine Polyfüllung.
Andy E
Ich wechsle zu dieser als die richtige Antwort, da dies eine native API ist, auch wenn die Unterstützung nicht großartig ist.
Enrique Moreno Zelt
1
Haben Sie el.className + = "meine Klassen hier"
Michael Tontchev
1
Gibt
71

Der neue Spread-Operator macht es noch einfacher, mehrere CSS-Klassen als Array anzuwenden:

const list = ['first', 'second', 'third'];
element.classList.add(...list);
morkro
quelle
1
Die akzeptierte Antwort funktioniert mit einer direkten Liste von Werten, aber diese funktioniert mit Arrays ... beide scheinen ausgezeichnete Antworten zu sein!
Enrique Moreno Zelt
Kann ich ein DOMTokenListanstelle eines Arrays verwenden? Ich weiß, dass eine DOMTokenList ein Array-ähnliches Objekt ist. Es ist also möglich, es mit der classList.add()Methode zu verwenden, oder muss die DOMTokenList in ein reales Array konvertiert werden?
xela84
19

Die classListEigenschaft stellt sicher, dass dem Element nicht unnötig doppelte Klassen hinzugefügt werden. Um diese Funktionalität zu halten, wenn Sie die Langschrift Versionen oder jQuery - Version nicht mögen, würde ich vorschlagen , eine addManyAdditionsfunktion und removeManyzu DOMTokenList(die Art der classList):

DOMTokenList.prototype.addMany = function(classes) {
    var array = classes.split(' ');
    for (var i = 0, length = array.length; i < length; i++) {
      this.add(array[i]);
    }
}

DOMTokenList.prototype.removeMany = function(classes) {
    var array = classes.split(' ');
    for (var i = 0, length = array.length; i < length; i++) {
      this.remove(array[i]);
    }
}

Diese wären dann wie folgt verwendbar:

elem.classList.addMany("first second third");
elem.classList.removeMany("first third");

Aktualisieren

Wenn Sie gemäß Ihren Kommentaren nur dann eine benutzerdefinierte Methode für diese schreiben möchten, wenn sie nicht definiert sind, versuchen Sie Folgendes:

DOMTokenList.prototype.addMany = DOMTokenList.prototype.addMany || function(classes) {...}
DOMTokenList.prototype.removeMany = DOMTokenList.prototype.removeMany || function(classes) {...}
Rich O'Kelly
quelle
Immer noch eine gute Antwort. Und ich konnte es nicht für Sie bearbeiten, da es nur 2 Zeichen waren.
Pete
18

Da die add()Methode von classListjust nur die Übergabe separater Argumente und nicht eines einzelnen Arrays zulässt, müssen Sie add()mit apply aufrufen . Für das erste Argument müssen Sie die classListReferenz vom selben DOM-Knoten übergeben und als zweites Argument das Array von Klassen, die Sie hinzufügen möchten:

element.classList.add.apply(
  element.classList,
  ['class-0', 'class-1', 'class-2']
);
Andrés Carreño
quelle
Es handelt sich um eine ES5-Version der Lösung mit dem Spread Operator (siehe Antwort von @morkro ). Überprüfen Sie es einfach bei Babel Repl .
Nickensoul
7

So fügen Sie einem Element eine Klasse hinzu

document.querySelector(elem).className+=' first second third';

AKTUALISIEREN:

Entfernen Sie eine Klasse

document.querySelector(elem).className=document.querySelector(elem).className.split(class_to_be_removed).join(" ");

quelle
Das ist interessant zu wissen, aber alles, was es tut, ist die Zeichenfolge der Klasse zu bearbeiten. Es würde nicht funktionieren, wenn ich mehrere Klassen entfernen wollte. Entschuldigung, ich habe vergessen, das im OP hinzuzufügen.
Enrique Moreno Zelt
4
Sie NICHT verwenden className. Es ist für die Leistung schrecklich (selbst das Abrufen seines Wertes führt zu einem Reflow).
Jacob
7

Neuere Versionen der DOMTokenList-Spezifikation ermöglichen mehrere Argumente für add()und remove()sowie ein zweites Argument toggle(), um den Status zu erzwingen.

Zum Zeitpunkt des Schreibens unterstützt Chrome mehrere Argumente für add()und remove(), jedoch keiner der anderen Browser. IE 10 und niedriger, Firefox 23 und niedriger, Chrome 23 und niedriger und andere Browser unterstützen das zweite Argument nicht toggle().

Ich habe die folgende kleine Polyfüllung geschrieben, um mich zu überraschen, bis sich die Unterstützung erweitert:

(function () {
    /*global DOMTokenList */
    var dummy  = document.createElement('div'),
        dtp    = DOMTokenList.prototype,
        toggle = dtp.toggle,
        add    = dtp.add,
        rem    = dtp.remove;

    dummy.classList.add('class1', 'class2');

    // Older versions of the HTMLElement.classList spec didn't allow multiple
    // arguments, easy to test for
    if (!dummy.classList.contains('class2')) {
        dtp.add    = function () {
            Array.prototype.forEach.call(arguments, add.bind(this));
        };
        dtp.remove = function () {
            Array.prototype.forEach.call(arguments, rem.bind(this));
        };
    }

    // Older versions of the spec didn't have a forcedState argument for
    // `toggle` either, test by checking the return value after forcing
    if (!dummy.classList.toggle('class1', true)) {
        dtp.toggle = function (cls, forcedState) {
            if (forcedState === undefined)
                return toggle.call(this, cls);

            (forcedState ? add : rem).call(this, cls);
            return !!forcedState;
        };
    }
})();

Ein moderner Browser mit ES5-Konformität DOMTokenListwird erwartet, aber ich verwende diese Polyfüllung in mehreren speziell auf sie zugeschnittenen Umgebungen. Daher funktioniert sie hervorragend für mich, muss jedoch möglicherweise für Skripts optimiert werden, die in älteren Browserumgebungen wie IE 8 und niedriger ausgeführt werden .

Andy E.
quelle
1
Niemand scheint zu erwähnen, dass IE10 das Hinzufügen mehrerer Klassen nicht zulässt. Das hat gut für mich funktioniert, also danke! Ich würde jedoch darauf hinweisen, dass in IE9 eine Fehlermeldung angezeigt wird, dass DomTokenList nicht definiert ist. Vielleicht möchten Sie das auch berücksichtigen. Oder führen Sie dies nur aus, wenn (Typ von DomTokenList! == 'undefined')
Ryan Ore
@ Ryan: Danke, ich dachte, DOMTokenList wird in IE 9 unterstützt, aber ich denke, es wurde übersehen. Ich werde versuchen, irgendwann eine Problemumgehung zu untersuchen.
Andy E
Sieht so aus, als müssten Sie auf einer fehlgeschlagenen DOMTokenList className mit Wortgrenzen-RegEx-Prüfungen verwenden
Greg
5

Hier ist eine Problemumgehung für IE 10- und 11-Benutzer, die ziemlich einfach zu sein schien.

var elem = document.getElementById('elem');

['first','second','third'].map(item => elem.classList.add(item));
<div id="elem">Hello World!</div>

Oder

var elem = document.getElementById('elem'),
    classes = ['first','second','third'];

classes.map(function(item) {
    return elem.classList.add(item);
});
<div id="elem">Hello World!</div>

colecmc
quelle
5
Gute Idee. Ich würde jedoch .forEach () anstelle von .map () verwenden - es ist sauberer / effizienter für Situationen wie diese, in denen Sie das zurückgegebene Array nicht verwenden.
Tenni
Ja das stimmt.
Colecmc
5

Sie können wie unten tun

Hinzufügen

elem.classList.add("first", "second", "third");

Entfernen

elem.classList.remove("first", "second", "third");

Referenz

TLDR;

Im einfachen Fall oben sollte das Entfernen funktionieren. Im Falle einer Entfernung sollten Sie jedoch sicherstellen, dass eine Klasse vorhanden ist, bevor Sie sie entfernen

const classes = ["first","second","third"];
classes.forEach(c => {
  if (elem.classList.contains(c)) {
     element.classList.remove(c);
  }
})
Pankaj Parkar
quelle
2

Die Standarddefinition erlaubt nur das Hinzufügen oder Löschen einer einzelnen Klasse. Ein paar kleine Wrapper-Funktionen können das tun, was Sie verlangen:

function addClasses (el, classes) {
  classes = Array.prototype.slice.call (arguments, 1);
  console.log (classes);
  for (var i = classes.length; i--;) {
    classes[i] = classes[i].trim ().split (/\s*,\s*|\s+/);
    for (var j = classes[i].length; j--;)
      el.classList.add (classes[i][j]);
  }
}

function removeClasses (el, classes) {
  classes = Array.prototype.slice.call (arguments, 1);
  for (var i = classes.length; i--;) {
    classes[i] = classes[i].trim ().split (/\s*,\s*|\s+/);
    for (var j = classes[i].length; j--;)
      el.classList.remove (classes[i][j]);
  }
}

Mit diesen Wrappern können Sie die Liste der Klassen als separate Argumente, als Zeichenfolgen mit durch Leerzeichen oder Kommas getrennten Elementen oder als Kombination angeben. Ein Beispiel finden Sie unter http://jsfiddle.net/jstoolsmith/eCqy7

HBP
quelle
2

Eine sehr einfache, nicht ausgefallene, aber funktionierende Lösung, von der ich glauben müsste, dass sie sehr browserübergreifend ist:

Erstellen Sie diese Funktion

function removeAddClasses(classList,removeCollection,addCollection){
    for (var i=0;i<removeCollection.length;i++){ 
        classList.remove(removeCollection[i]); 
    }
    for (var i=0;i<addCollection.length;i++){ 
        classList.add(addCollection[i]); 
    }
}

Nennen Sie es so: removeAddClasses (node.classList, arrayToRemove, arrayToAdd);

... wobei arrayToRemove ein Array von zu entfernenden Klassennamen ist: ['myClass1', 'myClass2'] etcetera

... und arrayToAdd ist ein Array von Klassennamen, die hinzugefügt werden müssen: ['myClass3', 'myClass4'] usw.

Soren
quelle
1

Angenommen, Sie müssen eine Reihe von Klassen hinzufügen, dann können Sie die ES6-Spread-Syntax verwenden:

let classes = ['first', 'second', 'third']; elem.classList.add(...classes);

Dong Nguyen
quelle
0

Ich mochte die Antwort von @ rich.kelly, aber ich wollte die gleiche Nomenklatur wie classList.add()(durch Kommas getrennte Zeichenfolgen) verwenden, also eine leichte Abweichung.

DOMTokenList.prototype.addMany = DOMTokenList.prototype.addMany || function() {
  for (var i = 0; i < arguments.length; i++) {
    this.add(arguments[i]);
  }
}
DOMTokenList.prototype.removeMany = DOMTokenList.prototype.removeMany || function() {
  for (var i = 0; i < arguments.length; i++) {
    this.remove(arguments[i]);
  }
}

So können Sie dann verwenden:

document.body.classList.addMany('class-one','class-two','class-three');

Ich muss alle Browser testen, aber das hat für Chrome funktioniert.
Sollten wir nach etwas Spezifischerem suchen als nach der Existenz von DOMTokenList.prototype.addMany? Was genau verursacht classList.add()einen Fehler in IE11?

Jason Lydon
quelle
0

Eine weitere Polyfüllung für element.classListist hier . Ich habe es über MDN gefunden .

Ich füge dieses Skript hinzu und verwende es element.classList.add("first","second","third")wie beabsichtigt.

Rafi
quelle