Simple jQuery Accordion

von

Wie macht man eigentlich..

jsHabt ihr schon mal eine Seite mit so einem netten Accordion-Effekt gesehen und euch gefragt wie das geht? Ich erkläre es euch, schaut euch doch aber erstmal die Demo an, damit ihr wisst, was ich meine.

Wie ihr seht, klappt immer der Bereich auf, auf den geklickt wird. Alle anderen Blöcke bleiben dagegen geschlossen oder schließen sich. Wir bedienen uns hier einfach jQuery und schreiben ein paar Zeilen Code, die den gewünschten Accordion-Effekt realisieren.

HTML-Gerüst

Bevor wir anfangen müssen wir unser HTML aber entsprechend vorbereiten..

1
2
3
4
<h3 class="trigger">Accordion Box 3</h3>
<div class="toggle_container">
	<p>Lorem ipsum dolor sit amet...</p>
</div>

Jeder dieser Blöcke besteht aus einer Überschrift, die später anklickbar sein wird und einem Container, der den eigentlichen Inhalt des Blocks enthält. Wichtig ist, dass wir die Klassen trigger den Überschriften und toggle_container den Containern geben, da später unser jQuery-Code an Hand derer die Aktionen ausführt. Es ist also egal, ob die Überschrift eine h1, h2 oder einfach nur ein div ist, wichtig ist die Klasse und dass danach sofort der Container folgt.

jQuery-Code

Nun zum eigentlichen Code. Vergesst aber nicht, dass ihr vor diesem Script die jQuery-Bibliothek in euer Dokument einbinden müsst! Wie das geht, erfahrt ihr auf der offiziellen jQuery-Seite.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$(document).ready( function() {
	$('.trigger').not('.trigger_active').next('.toggle_container').hide();
	$('.trigger').click( function() {
		var trig = $(this);
		if ( trig.hasClass('trigger_active') ) {
			trig.next('.toggle_container').slideToggle('slow');
			trig.removeClass('trigger_active');
		} else {
			$('.trigger_active').next('.toggle_container').slideToggle('slow');
			$('.trigger_active').removeClass('trigger_active');
			trig.next('.toggle_container').slideToggle('slow');
			trig.addClass('trigger_active');
		};
		return false;
	});
});

Nun zur Erklärung, was da eigentlich abläuft..

  1. Erst nachdem das DOM vollständig geladen ist, greift das Script.
  2. Schließe alle Container, deren Übschrift nicht die Klasse trigger_active hat.
  3. Klickt man auf ein Element der Klasse trigger wird geprüft:
    • Hat es auch die trigger_active-Klasse? Dann mach den darauf folgenden Container zu und entferne die active-Klasse.
    • Ansonsten schließe alle offenen Container und öffne nur den Container, der zur gerade angeklickten Überschrift gehört und gib dieser die active-Klasse.
  4. Es wird kein Wert am Ende der Funktion zurückgegeben (sollte eine Überschrift gleichzeitig ein Link sein).

Zu 2.: Stichwort – Accessibility

Das Schließen der Container würde auch über CSS (display:none) gehen aber was ist, wenn JavaScript nicht aktiviert ist? Dann würden die Leute den Inhalt der Container nicht mehr sehen, weil das Accordion nicht funktioniert.

Styling per CSS

Um das Ganze noch abzurunden, hier der CSS-Code der Demo.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
.trigger {
	-moz-border-radius:5px;
	-webkit-border-radius:5px;
	border-radius:5px;
	-moz-box-shadow:0 1px 1px #fff inset;
	-webkit-box-shadow:0 1px 1px #fff inset;
	box-shadow:0 1px 1px #fff inset;
	background:-moz-linear-gradient(center top, #e9e9e9 50%, #ddd 50%);
	background-color:#ddd;
	border:1px solid #ddd;
	color:#888;
	cursor:pointer;
	margin-bottom:5px;
	padding:5px;
	text-shadow:0 1px 0 #fff;
	width:388px;
}
.trigger_active {
	color:#333;
}
.toggle_container {
	padding:5px 10px;
	width:380px;
}

Wenn ihr das Problem habt, dass die Animation nicht flüssig ist sondern abrupt endet, versucht mal der Klasse trigger_container eine feste Breite zu geben. Damit sollte es klappen.

Allerdings ist das natürlich nur ein sehr rudimentäres Aussehen. Wie wäre es zum Beispiel mit einem Plus- oder Minussymbol, damit Benutzer gleich wissen: “Ah, hier kann ich also etwas auf-/zuklappen”? Eurer Kreativität sind hier natürlich keine Grenzen gesetzt. Viel Spaß mit eurem Accordion. :)

Die hier könnten dich auch interessieren…

54 Kommentare RSS

Kaloeffel

Bei mir springt es am Ende immer etwas. Als wenn die Fahrt immer eine Bestimmte Zeit lang geht und es dann auf die richtüge größe springt. Denn bei den Kurzen Texten fährt es zu weit und bei dem Langen zu kurz.
Passiert bei mir mit allen Browsern.

Norman

Da wird die Funktion slideToggle("slow") dran schuld sein, die kann man ja vllt mit einer anderen ersetzen.
@Kaloeffel: der Bug wurde soeben behoben.. hing mit der Vergabe von margin zusammen.

Florian Egert

Super Tutorial,

vielen Dank! :)

Eine Frage wie schaffe ich es bei oben genanntem Beispiel, dass der erste Container geöffnet ist, so wie es jetzt ist ist ja alles geschlossen am Anfang.

Norman

Hi Florian,
gute Frage und auch noch einfach zu lösen. Damit der erste Block am Anfang geöffnet ist, musst du der ersten Überschrift einfach die Klasse trigger_active geben und ins Script musst du noch diese Zeile einfügen:

$('.trigger_active').next('.toggle_container').show();

Ausgehend vom Script oben entweder nach Ziele 2 oder vor die Zeile 13.
Danke und viele Grüße!

carsten

Hi Norman,

kannst Du mir erklären, wie man einen bestimmten Container über einen link oder textanker öffnen kann? Gibt es eine Funktion wie: $(‘.selector’).accordion({ navigation: true });

Gruß, Carsten.

P.S. Schönes Blogdesign und klasse Infos. Macht Spaß hier zu lesen ;-)

Mephista

Und wie funktioniert das wenn man statt der horizontalen Navigation lieber eine vertikale Navigation machen möchte?

Vielen Dank für den Tipp!

LG M.

Norman

Hallo Mephista,
das ist leider ein ganz anderer Effekt, das wär mal was für einen eigenen Artikel (danke für die Idee) ;)

Bis es soweit ist, kannst du ja mal nach horizontal jQuery accordion suchen, da findet man ein paar ganz gute Artikel zum Thema. Das sind allerdings meistens Plugins und deswegen etwas umfangreicher. Ich hoffe trotzdem, dass dir das weiterhilft.

Franzi

Hallo Norman,

folgende Situation:

Der User besucht die Seite, der erste Container ist geöffnet, die anderen geschlossen. Er klickt auf den zweiten Link, der erste Container schließt sich, der zweite öffnet sich. Soweit ok. Dann jedoch klickt der User wieder auf den zweiten Link, dieser schließt sich und nun ist garnichts mehr geöffnet.
Das möchte ich vermeiden indem wieder der erste Container geöffnet wird.

Ist das möglich?

Gruß,

Franzi

Norman

Hallo Constantin,
das ist bereits der Fall! Denn die Container werden ja erst mit JS geschlossen. Hat der Nutzer JS deaktiviert, bleiben die Container einfach offen, testen kannst du das in der Demo.
Bitte und viele Grüße,
Norman

Phil

Hi Norman,

Erst mal Gratulation zu Deinem Blog, finde ich sehr gelungen :)

Das Skript ist absolute Klasse und passt super als Ergänzung auf Seiten mit sehr viel Content!

Allerdings habe ich ein kleines Problem damit die erste Container Box geöffnet darzustellen. Ich weiss dass die Frage bereits gestellt wurde, aber irgendwie funktioniert das bei mir nicht so ganz. (vielleicht ein doofer Fehler beim Markup oder im JS?)

Ich arbeite gerade an einem Redesign und habe auch eine Demoseite hochgeladen: http://www.kipperdesign.ch/sct_redesign/

Leider ist mein Wissen über Javascript noch im Anfängerstadium und ich wollte fragen ob es eventuell möglich wäre mir in dem Fall zu helfen? Würde mich sehr freuen.

Freundliche Grüsse,

Phil

Phil

Hi Norman,

danke für die promte Antwort! Ich habe zu der “trigger_active”-Klasse noch eine “trigger”-Klasse hinzugefügt. Nun sieht es zu Anfang zwar korrekt aus, ist aber nicht klickbar und verfällt wenn man eine andere Rubrik öffnen möchte :(
Vielleicht hast du eine Idee?

Liebe Grüsse,
Phil

Phil

Und auf einmal klappt es! Ich habe keine Ahnung was ich geändert habe aber ich ziehe dementsprechend meine vorherige Frage zurück. Herzlichen Dank für die tolle und schnelle Unterstützung.

Freundliche Grüsse,
Phil

vanhey

hi danke für dein tutorial – funktioniert am besten von allen. bin leider nicht so versiert in .js – aber vielleicht hast du eine idee wie man eine verschachtelte acc anhand deines scripts machen kann? habe die funktion pragmatischer weisse einfach kopiert und dupliziert mit neuen klassen – das problem ist nur das die unter acc immer gleichzeitig aufgehen, also wenn zwei vorhanden – öffnen sich beide – oder aber ich klicke nr. eins und nr.zwei öffnet sich – hast du einen tip? … und danke nochmal für den super beitrag.

Michael

Soweit finde ich das script wirklich sehr gut und vor allem verglichen mit vielen anderen sehr überschaubar und kurz…daher *TOP*!!

Nur ein Problem hat das ganze…undzwar die feste Höhe…wenn ich eine feste Höhe benenne, dann ist es ein harmonischer Ablauf…sobald ich die Höhe automatisch bemessen lasse hackt es ab..es läuft an, aber hackt am schluss ab…
Problem ist…für jede Box dieselbe Höhe angeben ist doch nicht sinngemäß..nicht jede Box enthält den gleichen Inhalt…und für jede Box ne eigene ID und ins script einbinden ist sehr umständlich…

Ich habe einiges probiert, komme aber nicht auf die Lösung..warum hackt es bei ner automatischen Höhe??

Norman

@Michael: Hm eigentlich musst du nur eine fester Breite vergeben, die Höhe sollte immer automatisch sein.. siehe auch die Demo, dort ist nur die Breite fest.

Denis

Hey,
was muss ich denn ändern, damit der erste Container schon offen ist, wenn die seite betreten wird? Die anderen sind zu. Der erste Container soll erst zugemacht werden, wenn ich einen anderen aufmache.

Danke!

Niklas

Schönes Script. Ich würde dem slideToggle anstatt des Wertes slow allerdings einen Zahlenwert geben z.B. slideToggle(“200″) für 200 Millisekunden. Dadurch ließen sich bei mir schon des öfteren hackelige Animationen vermeiden. Nichts desto trotz ein leicht Verständlicher Lösungsweg der mir sehr gut auf die Sprünge geholfen hat. Danke dafür :)

Jennifer

Hallo Norman,

ich habe ein Problem was bereits weiter oben bereits genannt worden ist.
Der Text fährt aus und dann sofort wieder zu so, dass man nicht die chance hat diesen komplett zu lesen. Ich verstehe nicht ganz was ich ändern kann damit die Animation quasi am Ende stehen bleibt.

Danke schon mal für deine Hilfe und viele Grüße

Norman

Hi Jennifer,
hast du vielleicht ein konkretes Beispiel, dass du mir zeigen kannst? Kann mir das Verhalten gerade nicht erklären..
Danke und Grüße!

Altilux

@Norman

Ich habe das gleiche Problem wie Jennifer.

Ich habe dem ersten Container in der Überschrift “trigger_active” in der class hinzugefügt, wie du es weiter oben (klick) gesagt hast.

Es liegt meines Erachtens an dem style “display”, der durch das Script dem anzuzeigenden Container verleiht. Angezeigt: “display:block”, Nicht angezeigt “display:none”. Leider konnte ich die Eigenschaft nicht korrigieren, da diese stets vom Script überschrieben wird.

Ich brauche es so, dass beim 1. Seitenaufruf der 1. Container geöffnet ist und dass durch klicken von “weiter” der zweite Container geöffnet wird und dabei der erste wieder geschlossen wird. Das kann ich durch POST-Varaiblen lösen, doch eben nur, wenn ich weiß, wie ich das Script anpassen muss, damit der von mir gewünschte Container beim Seitenaufruf geöffnet ist.

Sonst nen klasse Script inkl. Beschreibung *THUMBS UP*

Chris

Martin

Hallo, vielen Dank für das Script.

Wenn man mit flexiblen Höhen und breiten arbeiten möchte kann man folgendes Script nutzen um den Boxen eine Breite zu geben, und somit das unschöne “flackern” verhindern.

1
2
3
$('.toggle_container').each(function() {
		$(this).width($(this).innerWidth()).hide();
});

einfach damit diese Zeile ersetzen:

1
$('.trigger').not('.trigger_active').next('.toggle_container').hide();

Dann müsste es klappen. Habe mein Script etwas anders aufgebaut, aber iich denke das sollte passen.

VG

Christina

Hallo Norman,
habe Dein Script eben eingebaut. es funktioniert perfekt! vielen Dank dafür und für die anschauliche Erklärung!
LG Christina

Peter Schmitz

Super, hat sofort geklappt. Firma dankt!
Ich kann nichts finden über Lizenz und so – Freeware?

Norman

Hallo Peter,
freut mich, dass es gleich auf Anhieb geklappt hat. Wie alles auf diesem Blog, steht auch obiger Codeschnipsel zur freien Verfügung. Du kannst damit machen, was du willst. :)

Falk

Hallo Norman,

super Tutorial, super Script – weils einfach ist und einfach funktioniert – ohne erst die jQuery-UI zu bemühen.
Und vielen Dank für die Freigabe – habe das Script gerade für ein aktuelles Projekt verwendet.

Sven

Hallo Norman,
Dein Script ist wirklich simpel und gut. Ich habe nur ein Problem mit dem IE 8.0. Dieser haut die DIV-Container beim zusammenklappen zu einem Brei zusammen. Selbst wenn ich Dein Originalscript nehme ist das leider so. Gibt es dafür eine Lösung?

Grüße Sven

Thorsten

Hallo Norman,
hervorragendes Script, danke!
Aber eine Frage, ich möchte, dass am Anfang alles geschlossen bleibt, wenn ich dann auf eine Überschrift klicke geht der Container auf, gehe ich auf eine andere, geht der Container auf, der erste soll aber offen bleiben. Dieser soll erst wieder zugehen, wenn ich den nochmals anklicke. Wo kann ich das einstellen? Vielen Dank für eine Antwort.

Norman

Hallo Thorsten,
danke für deine Anfrage. Das ist kein Problem, dazu musst du nur die Zeilen 9 und 10 (aus oben genannten Script) auskommentieren oder löschen.
Viele Grüße.

Lukas

Hallo Norman

Tolles und einfaches Skript! Ich habe das Problem, dass ich relativ lange Inhalte habe, wenn man dann runterscollt um das ganze zu lesen und dann auf den nächsten Header klickt, landet man irgendwo (weils oben schliesst und unten öffnet). Ich möchte aber dass der Header des neu geöffneten am oberen Rand des Browsers ist.
Eine Idee wie ich das umsetzen könnte?

Liebe Grüsse, Lukas

Martin

Hi Norman,
gutes Script – besten Dank dafür! Ich meine, die Frage hier schon einmal gelesen zu haben, aber finde diese nicht mehr: Besteht eine einfache Möglichkeit auf Mausklick alle Inhalte auszuklappen/einzuklappen?

Michael

Hallo Norman,

auch ich finde Dein Accordian-Skript super klasse. Ich bin begeistert, wie einfach es einzubauen und auch anzupassen ist. Mein Frage ist folgende: Kann man das Skript so verändern, dass sich der erste Text automatisch beim Öffnen der Website (per Link) als Accordeon langsam öffnet und nicht erst nach erneutem klicken auf den Header. hast Du da eine Lösung für mich?

Gruß Michael

Florian Weber

Hallo,

ich habe das Script in meiner Navi eingesetzt, wie es oben beschrieben ist. So weit klappt auch alles wie gewünscht, beim Klicken geht das Untermenü auf. Das Layout ist auch so wie gewünscht. Also vielen Dank für das Tutorial.

Nun zu meiner Frage. Es soll immer dann ein spezielles Bild angezeigt werden, wenn sich ein Untermenü unter dem Oberbegriff befindet. Da nicht bei jedem Oberbegriff ein Untermenü vorhanden ist, kann ich das nicht pauschal mit in der Klasse angeben, sondern muss irgendwie erkennen, dass nach der Klasse trigger noch eine Klasse toggle_container kommt.
Kannst du mir da eine kleine Hilfe geben, wie ich das erkennen kann?

Gruß,
Florian Weber

Mono

Vielen Dank für die sparsamen Code!
Wie kann ich allerdings das Teil in eine Funktion packen, da ich mehrere Accordions verwenden möchte? Grüße aus Kunming, China

kranate

Hi Norman!

die Schnipsel funktionieren wunderbar..! Danke schon mal dafür!
Nun hab ich in einem toggle_container eine Google Maps Karte per Iframe eingebunden (per API hab ich´s auch schon probiert)..
wenn ich jetzt nach Laden der Seite den Container öffne (aktiviere), dann seh ich zwar die Karte.. aber nicht an der richtigen Position.

Kann man das lösen?
Oder alternativ als Workaraound den iframe beim aktivieren neuladen lassen?

Uwanius

Hi,
zunächst einmal vielen Dank für das Super Script.

Ich nutze es um ein Formular ein bzw. auszublenden. Hängt es vieleicht mit dem FORM Tag zusammen, das die Animation nicht flüssig ist? Das übergeordnete DIV und die FORM haben eine feste Breite und Höhe.

Beim slideup endet die Animation sehr abrupt.

Jasmin

Halloo
Ich probiere soeben auch mal das coole Ding aus – aber bei mir in wordpress.
Das komische nun ist, dass es normal im WordPress nicht dunktioniert, aber wenn ich dann den Seitenquelltext kopiere, ihn in den Ordner mit style.css und jquery.js hinenkopiere, funktioniert er wieder?!
Kannst du mir hier helfen?

Enrico

Hi,
super Sache, vielen Dank, nun würde ich gerne zur besseren Verdeutlichung ein + bei “geschlossen” und ein Minus bei “geöffnet” einfügen, wie krieg ich das nur hin? Bin leider nicht so “bewandert” mit iquery.
Oder geht das über CSS?
Wär Super, wenn du hier helfen könntest!

Doris

Hi Norman

Tolles Teil hier super lieben dank dafür. Aber ich hab ein Problem. Auch ich wollte den ersten Task offen haben, habe nach deiner Anleitung in den Kommentaren somit meine erste Box mit Accordion Box 3 begonnen, dann habe ich noch den Code im Sqript eigesetzt ABER … nun ist zar die erste box offen, sobald ich aber eine andere anklicke kann ich die 1. Box nicht mehr öffnen. Weißt du woran das liegt?

André

Hallo Norman,

danke für den Artikel. Ließ sich sofort einsetzen und sieht schick aus.

In dem Hinweis unter “Styling per CSS” hast Du noch einen Typo:
statt ‘toggle_container’ steht da ‘trigger_container’.

Gruß,
André

Paul

Hallo,
vielen Dank für die Anleitung, ich das “Akkordeon” erfolgreich auf meine Seite einbauen können.
Ich würde jetzt noch gerne 2 Icons einfügen, am rechten Rand der Überschrift. Ich habe 2 Pfeile, einer der nach “unten” zeigt, und einer der nach “links” zeigt.
Wie baue ich diese ein, sodass sie korrekt wechsel? (nach “unten” falls aufgeklappt, nach “links” falls eingeklappt?

Vielen Dank und Grüße
Paul

Una

Hallo Norman,
kannst du mir ev. einen Tipp geben:
Die Inhalte meines jquery-Accordions sind teilweise relativ lang.
Öffne ich die Inhalte mehrfach, wird der Inhalt von dort angezeigt, wo ich ihn das letzte mal verlassen haben (also teilweise mitten im Text.). Ich möchte aber, dass der Inhalt immer vom Textanfang aus angezeigt wird. Bin Laie und finde einfach keine Lösung hierfür.
Wäre sehr nett, wenn du mir helfen könntest und würdest.
Danke
Una

Ricardas

Hallo Norman,

sag mal, ich möchte das Accordion von jQuery UI selbst nutzen (siehe link unten), sprich als Extension für mein Programm Wysiwyg Webbuilder. So weit auch ganz gut, über den jQuery Webbuilder habe ich das Theme auch angepasst, nur leider funktioniert es nicht so wie es soll, besser gesagt wie ich es bei dir gesehen habe. Der Inhalt ist verschieden lang und deine Container passen sich jeweils an, bei der Extension allerdings wird ein Scrollbalken erzeugt, keine Anpassung an den Inhalt. Hast du da einen Expertentip für mich?

LG
Ricardas

http://jqueryui.com/themeroller/#!zThemeParams=5d000001001506000000000000003d8888d844329a8dfe02723de3e570162cf18d27450c454aa2f2e374d1d127fabb9ebc66c3ee5a70fb154870371702db6720bcd83f0ecbb2131337f10a086e219c538a2003e4a05b37f637b91dbf9e5ea1a30eee0ffb74635c67587b16e39b844855d43f178d7223e5844a27feed562a919e51a896a2b947ea0fe5769740cad2f353f43f6a6badb4f9f158f439cd0ec77f1c39bf311c9c328e70d7c078862964f803cfeb841e8f7d5c944dbec24d93e6f8096a02b769b976b7c435f6ee6b8cc66444023920a41270f305b7e9d576789ae017b7f8a16eaf3fddede704785a409c4fbbbe7481fb749e2ae44e8ec018139c9bdaad1ff148a94614b8bed98e577f2a12f376997fd9e196c9c2c4e8ade8e18f17a54d27413cfc22eb103a061cb0ace641d769abc84778c949297f6f00a2f8f502cbad9d937aace60187dbe5719bd8904bf7ad27999098ff61920ef5fc2ce8fc28088bfe4f049af0fad1091984f7cc7c512a75c11b0d0a81a1fd4a9aee0b0ef437e5370a72a1568ba3e12b2912e0c16c95f0a7db121b89833319b9b3d4d8508bce99ed91cf922da9c78511a24190d7a54d45882fc347df992d44a5223515862e741257e6920e3b32e5fe9c19f11f086f26e66f1e9ec94da3cb5f2dcc8be91cb5dc08236c670e97128b7e9dcf8dafebcda7ac193a3251395116da73002ca7756c07fbe44bbe5ebf232ca9146b55f92ec226878e01a55ccffba986c3

mv-soft

Hallo,

klappt alles prima, vielen Dank.
:-)

Eine Frage noch: WIE kann ich mit einem internen Link (id=ziel-1) direkt auf einen Inhalt des Accordeons zugreifen?

Ein Link steht also außerhalb des Accordeons und per click soll sich zum Beispiel das 2. Element öffnen

Vielen Dank für Deine Bemühungen.

Webdesign Krokus

Schönen Effekt. Wir verwenden diese Funktion, wenn die Seite, die Sie brauchen, um eine Menge Text zu platzieren, aber das Design erlaubt es nicht schön zu machen

Kommentieren