Die Idee ist, eine Frage-und-Antwort-Seite zu erstellen, deren Funktionalität durch JavaScript (jQuery) erweitert wird. Jede Frage wird in einem Feld mit einem Anhänger am unteren Rand angezeigt. Wenn man auf den Anhänger klickt, gleitet dieser heraus und enthüllt ein weiteres Feld mit der Antwort.

Demo anzeigen Dateien herunterladen
Überlegungen
Dies ist keineswegs eine schwierige Aufgabe, besonders mit jQuery. Aber dieses Beispiel ist hervorragend geeignet, um die Auswirkungen dessen, was wir tun werden, zu bedenken. Unsere Idee berücksichtigt die Mehrheit der Besucher der Website, die einen Standardbrowser mit aktiviertem JavaScript verwenden. Aber wir müssen auch diejenigen berücksichtigen, die einen nicht standardmäßigen Browser wie einen Screenreader verwenden oder die das Web mit deaktiviertem JavaScript durchsuchen.
Kein JavaScript
In unserem voll funktionsfähigen Beispiel sind die Antworten nicht sichtbar, bis auf den Antwort-Anhänger geklickt wird. Es gibt verschiedene Möglichkeiten, dies zu erreichen, aber wir sollten darauf achten, unser Verbergen mit JavaScript durchzuführen, sodass bei deaktiviertem JavaScript die Antworten nicht verborgen sind. Unser "Antwort"-Zug-Tab wird bei deaktiviertem JavaScript ebenfalls etwas irrelevant, also sollten wir auch darauf achten, diesen per JavaScript anzuwenden, damit er nur vorhanden ist, wenn er nutzbar ist.
Screenreader
Wir haben bereits festgelegt, dass wir das Verbergen unserer Antworten mit JavaScript durchführen werden, also keine Sorge um das Verbergen von Antworten. Unser einziges Anliegen ist nun, dass unser Markup sauber und semantisch ist. Mit anderen Worten, kein zusätzlicher Ballast, den Leute mit Screenreadern nicht sehen müssen, sowie eine klare Trennung zwischen „Frage“ und „Antwort“.
Der Markup
Beginnen wir mit dem Markup. Wir nutzen Definitionslisten, die meiner Meinung nach perfekt für FAQ-Inhalte geeignet sind.
<dl class="faq">
<dt>How much wood would a wood chuck chuck if a wood chuck could chuck wood?</dt>
<dd class="answer"><div>1,000,000</div></dd>
</dl>
Ziemlich sauber, aber es gibt ein schlechtes Zeichen in unserer Semantik-Bewertung: das zusätzliche div im Antwort-Element. Dies ist nicht unbedingt notwendig, aber es unterstützt die Geschmeidigkeit der Animation, die wir mit jQuery beabsichtigen. Lang und kurz: Wenn Sie eine Funktion wie .slideToggle verwenden, wird Ihre Animation viel reibungsloser sein, wenn das Element keine Polsterung verwendet. Wir erreichen die benötigte Polsterung durch dieses zusätzliche div. Mehr Infos dazu hier.
Das jQuery JavaScript
Als Erstes laden wir die Bibliothek und verknüpfen unsere externe JavaScript-Datei, um die Dinge sauber zu halten. Beachten Sie, dass wir jQuery von Google laden, was für die Produktion empfohlen wird. Mehr dazu wie und warum.
<script src="//www.google.com/jsapi"></script>
<script>
google.load("jquery", "1.2.6");
</script>
<script src="js/faq.js"></script>
Dann schreiben wir den eigentlichen Code.
- Antworten verstecken.
- Hänge-Tab „Antwort“ anfügen
- slideToggle-Funktionalität auf den Tab anwenden
$(function(){
$("dd.answer")
.hide();
$("dl.faq")
.append("<dd class='answer-tab-wrap'><a class='answer-tab'>Answer</a></dd>");
$(".answer-tab")
.click(function(){
$(this)
.parent()
.parent()
.find("dd.answer")
.slideToggle();
});
});
Das CSS
dl { clear: both; margin: 0 0 20px 0; }
dt { border: 8px solid #7ac0d0; padding: 10px; background: white;
position: relative; font-style: italic; }
dd.answer { background: white;
position: relative; width: 90%; margin: 0 auto; }
dd.answer div { padding: 10px; border-left: 8px solid #dedede;
border-right: 8px solid #dedede; border-bottom: 8px solid #dedede; }
dd.answer-tab-wrap { margin: 0 30px 0 0; }
.answer-tab { background: url(images/answer-tag.png); display: block; margin: 0 0 20px 0;
text-indent: -9999px; width: 105px; height: 50px; float: right; }
Ein paar interessante Punkte hier. Da wir den Antwort-Tab schweben lassen, werden wir den Float bei den Definitionslisten selbst löschen, um sicherzustellen, dass der Abstand zwischen ihnen stimmt. Wir verwenden auch CSS Image Replacement für die .answer-tab Ankerlinks, um die höchstmögliche Effizienz zu erzielen (Bild muss nur einmal geladen werden).
Erfolg
Oben auf der Seite sehen Sie die Ergebnisse der Demo mit Funktionalität. Hier sind die anderen Szenarien
JavaScript aus
Antworten sichtbar, Styling ergibt immer noch Sinn.

Screenreader
Als Webseite mit deaktiviertem CSS und JavaScript angezeigt.

Getestet und zugelassen in
Firefox 3, Safari 4, Internet Explorer 6 & 7, Opera 9
Das gibt’s doch nicht – ich habe einen exakt gleichen Artikel geschrieben („Fancyfying a FAQ page with jQuery). Tja, du warst mir wohl zuvorgekommen.
Jedenfalls war dein Artikel besser, ich mag diese Implementierung wirklich sehr. Mach weiter so, Chris!
Ach. Tut mir leid, Mann, aber du solltest ihn trotzdem veröffentlichen. Es gibt immer Platz für mehr Tutorials und Lehren im Web.
Kein Problem, Kumpel, du hast Recht damit, dass es gut ist, dem Web ein paar richtig gute Sachen beizubringen – wie deine. Ich werde meinen Artikel später fertigstellen; arbeite jetzt an anderen CSS/JavaScript-Sachen :)
Willst du was wirklich Gruseliges wissen? Sieh dir meinen Twitter-Status ein paar Stunden vor der Veröffentlichung deines Artikels an.
Zufall?
Verrückt.
Von Monty Python, lol!
Gute Arbeit.
Unobtrusive JavaScript ist etwas, das jeder im Hinterkopf behalten sollte. In gewisser Weise ist es wie das CSS-Layout (im Gegensatz zu Tabellen) der clientseitigen Funktionalität. Semantischer, besseres SEO/Barrierefreiheit und wenn man sich erst einmal daran gewöhnt hat, möchte man nicht mehr zum alten Weg zurückkehren.
Tolles Beispiel für die Verwendung von JQuery, um das Benutzererlebnis zu verbessern, ohne es zu beeinträchtigen, wenn JavaScript deaktiviert ist. Tolles Tutorial!
–Brenelz
Ich liebe deinen Ansatz mit diesem Tutorial. Du hast einen gut definierten Prozess, den ich gerne erreichen würde. Ich neige dazu, mit dem Programmieren einer Idee zu beginnen und am Ende im Kreis zu laufen, bis ich es richtig hinbekomme.
Ähm... die erste Antwort ist falsch.
Die wahre Antwort lautet: „Ein Holzkotzer würde so viel Holz kotzen, wie ein Holzkotzer kotzen könnte, wenn ein Holzkotzer Holz kotzen könnte, ABER ein Holzkotzer kann kein Holz kotzen, denn ein Holzkotzer ist ein Gopher.“
Mist, Tippfehler.
-Holzkotzer-
Hallo Chris,
Ausgezeichneter Beitrag! Ich wollte gerade etwas Ähnliches für einen Kunden mit jQuery erstellen. Ich glaube, du hast mir gerade mehrere Stunden erspart; ich werde dein Beispiel als Ausgangspunkt verwenden. Danke, du bist spitze!
Brian
Ich abonniere deinen Feed und sehe meine Feeds derzeit in einer externen Anwendung an (ich habe kein schnelles Firefox-Add-on gefunden) und ich musste hierher kommen und kommentieren, um zumindest meine Wertschätzung für die Zeit zu zeigen, die du in das Schreiben und Teilen von Inhalten wie diesem investierst.
Deine dynamische FAQ-Seite ist großartig.
Ich habe bereits begonnen, sie anzupassen, und die Möglichkeiten und potenziellen Verwendungen dafür sind zahlreich.
Vielen Dank. Mach weiter so mit den guten Sachen.
Was ist mit modernen Screenreadern wie JAWS, die JavaScript rendern? Wie bekommen sie die Antwort, wenn sie keine Maus haben? Du musst die Frage zu einem Link und die Antwort zu einem Lesezeichen machen.
Mit aktiviertem JavaScript, aber deaktiviertem CSS, sieht es fast so aus wie im Beispiel mit beiden deaktiviert, aber mit dem Text „Antwort“ unter der (sichtbaren) Antwort. Ich denke, das ist eine ziemlich elegante Degradation.
Gibt es Lösungen, um aus dem „Antwort“-Button ein Hand-Symbol statt eines Pfeil-Symbols zu machen? Einige unserer Kunden sind nicht sehr web-affin und würden sich umsehen und die Seite schließlich verlassen, weil sie nicht wissen, wo sie anfangen sollen zu klicken…
Gute Idee, ich habe sie dem Live-Beispiel hinzugefügt. Man braucht nur eincursor: pointer;in den.answer-tabim CSS.
Ich habe das schon früher gesehen und nichts gesagt... aber es führt mich zu einer interessanten Anfrage bezüglich CSS-Caching. Wenn wir Änderungen vornehmen, wie können wir als Frontend-Entwickler mit wenig Kenntnissen über Header/Caching/PHP sicherstellen, dass die neueste CSS-Datei für den Benutzer geladen wird.
Viele Leute machen den Fehler, denselben Dateinamen zu verwenden und die Formatierung sieht wegen dieses Versehen schrecklich aus – daher wäre es interessant, deine Gedanken dazu zu hören/sehen!
Ich verwende normalerweise einen Query-String-Parameter dafür. Zum Beispiel, wenn meine CSS-Datei styles.css ist, würde ich sie so referenzieren:
<link rel=”stylesheet” href=”/path/to/css/styles.css?v=1.0″ />
Wenn ich dann eine Änderung einführe, ändere ich den v-Parameter auf 1.1 oder 2.0. Das zwingt zu einem neuen Download in praktisch jedem Browser und Proxy-Cache, den ich je getestet habe.
Danke! Ich werde es vielleicht irgendwo einbauen!
Ausgezeichneter Beitrag – besonders, weil er progressive enhancement nutzt; obwohl, wenn CSS deaktiviert ist, alle Antworten sichtbar sind, bis man auf „Antwort“ klickt.
Ich weiß, es würde nur eine Zeile Code erfordern, aber aus Sicht der Benutzererfahrung wäre es vorteilhaft, wenn der Cursor zu einer Hand wird, besonders wenn man möchte, dass die Antwort versteckt wird.
Sehr schön, aber nimmt viel Platz für drei Fragen ein. Es wäre schön, wenn eine Akkordeon-Funktion hinzugefügt würde, damit man Fragen nach Themen ordnen kann.
Chris,
Vielen Dank für all die Informationen, die du (kostenlos) zur Verfügung stellst. css-tricks ist die erste Seite, die ich jedes Mal besuche, wenn ich einen Browser öffne (ja, sogar bevor ich meine E-Mails prüfe). Ich habe eine Frage. Ich arbeite an einer kleinen E-Commerce-Website und möchte jQuery verwenden, um das Einkaufserlebnis aufzupeppen. Was ich getan habe, ist, eine Liste von Artikeln innerhalb eines Divs mit Links zum Hinzufügen des Artikels zum Warenkorb auszudrucken. Ich möchte jQuery verwenden, um diese Liste in Seiten aufzuteilen und eine Art Schieberegister-Oberfläche zu erstellen. Das Problem, das ich habe, ist, dass die Liste kurz auf dem Bildschirm aufleuchtet, bevor jQuery sie ausblenden kann, da ich jQuery verwende, um die Liste anfangs auszublenden. Ich möchte sie nicht mit CSS ausblenden, denn wenn der Benutzer JavaScript deaktiviert hat, gibt es keine Möglichkeit, sie sichtbar zu machen. Hast du (oder irgendjemand anders) einen Tipp für mich? Nochmals vielen Dank für dein Wissen.
Anstatt es mit CSS überdisplay: none;auszublenden, könntest du es mit einer sehr großen negativen Oberen und linken Positionierung von der Seite schieben undposition: absolute;. Ich denke, das ist im Allgemeinen die Technik, die dort verwendet wird. Dann entferne einfach dieses CSS mit dem JS.
Ich kann dieses CSS nicht entfernen, da JavaScript deaktiviert sein wird... vermisse ich etwas?
Ich bemerke, dass mit meiner Demo der Antwortblock nicht sichtbar ist, bevor er mit jQuery ausgeblendet wird, aber es gibt eine kurze Pause, bevor der "Antwort"-Tab hinzugefügt wird.
Was soll ich sagen? Der Name meines Mannes ist, und ich mache keine Witze, Chuck Wood. Oh, und schönes Tutorial! Danke!
Das ist sehr cool. Ich werde das vielleicht in ein Projekt von mir einbauen und es ein wenig ändern, ich werde dich wissen lassen, wie es wird, wenn ich es benutze.
Das ist ziemlich nett, ich werde das für meine zukünftigen Projekte definitiv in Betracht ziehen~
Danke!
Ein Holzkotzer würde so viel Holz kotzen, wie ein Holzkotzer kotzen könnte.
Das ist nett und hübsch. Aber in Bezug auf die Benutzerfreundlichkeit sollte die Frage selbst klickbar sein, um die Antwort anzuzeigen.
Im Design („de-sign“) ist der „Antwort“-Button nicht notwendig. Das Standard- und erwartete Verhalten für FAQs ist „Benutzer klickt auf die Frage, auf die er/sie eine Antwort möchte“, und diese Implementierung bricht diese Erwartung.
Schöner sauberer Code. Ich habe vor ein oder zwei Jahren etwas Ähnliches gemacht, natürlich habe ich jQuery nicht integriert. Schönes Beispiel.
Schönes Tutorial, um den gewünschten Effekt zu erzielen, aber ich würde das nie für eine FAQ verwenden. Warum Informationen verstecken, wenn Leute eine FAQ normalerweise nach Informationen durchsuchen?
Ich denke auch, dass die Erstellung eines Buttons namens „Antwort“ einige Benutzer glauben lassen könnte, dass sie selbst Fragen beantworten können.
Toller Artikel, Chris. Ich beginne, JQuery wirklich zu verstehen, und es hat mir Ideen für meine eigene Website gegeben. Nochmals vielen Dank. Ein tolles neues Jahr 2009 für dich.
Ja, wirklich gutes Tutorial. Falls sich jemand anderes verrückt vorkommt oder es vielleicht nur mir so ging; ich habe ursprünglich versucht, das jQuery mit dem Codebeispiel zu verstehen, und es hat mich ewig gedauert, herauszufinden, woher der ‚answer-tab‘ kam!? Nachdem ich die Demo heruntergeladen hatte, erkannte ich, dass dies Teil des Anhängens mit einem Anker-Tag war. Mein Geist ist jetzt beruhigt :) Danke, Chris.
Schönes Beispiel, Chris.
Niemand hat es bisher erwähnt, aber wenn du (jemand) dich um die Semantik des zusätzlichen Divs sorgst – könntest du das nicht auch mit jQuery hinzufügen?
Ich stimme zu, dass das Hinzufügen des zusätzlichen Markups per jQuery für mich wie eine perfekte Lösung erscheint.
$$('dd.answer')
.wrapInner('<div></div>') // div-Tags hinzufügen
.hide(); // alle Antworten ausblenden
Ich habe vor ein paar Monaten etwas Ähnliches mit jQuery geschrieben. Ich mag dein Styling und deine Einfachheit. Schau dir meins an, wenn du vergleichen möchtest…
FAQ-Plugin
Hallo Chris. Eine Demo wäre hilfreich. Danke.
Ah, da ist sie, Neal. Ich meinte eine Demo auf der Seite. Ich habe versucht, dasselbe mit David Walshs Mootools-Akkordeon und Chris' Demo zu tun, aber die Skripte haben sich überschnitten. Ich werde dasselbe mit deinem versuchen.
Ich liebe wirklich das Aussehen davon, aber ich habe eine Frage.
Ich bin ziemlich neu bei jQuery, aber ich bin verwirrt, wie die Klasse „answer-tab“ überhaupt angeklickt werden kann, wenn sie nicht im Markup vorhanden ist und auch nicht angehängt wird. Wenn ich etwas komplett falsch verstanden habe, würde ich mich freuen, wenn mir jemand erklärt, was hier eigentlich passiert!
(Hinweis: Ich habe das ausprobiert, indem ich den obigen Code verwendet habe, und ich bekam statischen „Antwort“-Text unter der Frage, der nichts tut, wenn er angeklickt wird. Wenn ich .answer-tab-wrap in .answer-tab ändere, also die Klasse .answer-tab hinzufüge, damit sie tatsächlich im Markup existiert, dann funktionieren die Dinge, aber es sieht mehr als nur ein bisschen komisch aus. Bitte sag mir, wo ich falsch liege!)
Ich glaube, ich bin auch per Konvention verpflichtet, darauf hinzuweisen, dass ich ein langjähriger Fan der Seite bin, die Screencasts und Beiträge sind fantastisch und ich freue mich immer, wenn ein neuer Beitrag erscheint! Danke, dass du mich bildest :)
Nein, nein, nein.
Ein Holzkotzer könnte so viel Holz kotzen, wie er könnte, wenn du ihm einen Kotzer für jeden Kotzer geben würdest, den er könnte.
Oh, und du solltest MooTools oder sogar Prototype eine Chance geben. Ich habe mit Prototype angefangen und war zögerlich, MooTools auszuprobieren, aber ich bin froh, dass ich es getan habe. Es macht viel Spaß. JQuery bekommt viel Hype, weil John Resig den Namen pusht, während andere zurückhaltender sind.
Tolles Tutorial! Da ich neu bei jQuery bin, möchte ich lernen, wie man etwas Ähnliches wie Firefox macht. http://www.mozilla.com/en-US/firefox/3.0.5/releasenotes/ Obwohl es keine exakte FAQ-Seite ist, denke ich, dass es für eine funktionieren würde.
Hallo….
Ich habe dies mit meinem Screenreader (Supernova/HAL 8.0) ausprobiert und er hat die Antwort nicht vorgelesen. Er las die Frage gut vor und las „Antwort“, aber ich konnte den eigentlichen Antwort-„Button“ nicht mit der Tastatur anklicken.
Daher ist dies für blinde Benutzer mit Screenreadern oder mobilitätseingeschränkte Benutzer, die auf Tastaturzugriff angewiesen sind, nicht barrierefrei.
Ich dachte, ich sollte dich informieren.
DANKE, dass du darauf hingewiesen hast. Ziemlich peinlich, so etwas in einem Artikel zu vermasseln, der sich MIT Barrierefreiheit beschäftigt.
Ich glaube, ich habe das Problem behoben. Das Problem war, dass die Antwort-Tabs selbst Ankerlinks sind, aber kein href-Attribut enthielten. Daher konnten sie nicht mit der Tastatur "angesteuert" oder anderweitig einzeln ausgewählt werden.
Ich habe das behoben, sodass das Tabben dorthin und das Drücken von Enter den Link aktivieren und die Antwort anzeigen sollte.
Dies wäre der Fall bei Screenreadern, die mit JavaScript funktionieren. Wenn es ein Screenreader mit deaktiviertem JavaScript wäre, wären die Antworten gar nicht erst verborgen.
Hallo Chris, danke für die Lösung. Ich habe es noch einmal getestet und der Screenreader hat die Seite gut vorgelesen. Das einzige Problem bei solchen JavaScript/AJAX-Lösungen ist, dass blinde Benutzer keine Möglichkeit haben zu wissen, dass die Antwort tatsächlich erscheint. Nehmen wir also an, ich lese die Seite durch, klicke auf „Antwort“ und die Antwort erscheint oben. Die Lesereihenfolge des Screenreaders ist, von oben nach unten zu lesen. Um die Antwort zu finden, würde ich (logischerweise) TAB nach unten drücken, aber die Antwort erscheint darüber... was ein blinder Benutzer nicht weiß (da die Antwort "lautlos" erscheint) und normalerweise würde der blinde Benutzer nicht nach der Antwort über dem "Antwort"-Button suchen. Es wäre daher besser, wenn die tatsächliche Antwort unter dem "Antwort"-Button erscheint, damit sie in der logischen Lesereihenfolge für den Screenreader und für alle Benutzer perfekt zugänglich ist :)
JavaScript/AJAX kann die Barrierefreiheit für viele Benutzer verbessern, ist aber für blinde Benutzer knifflig. Man muss nur darauf achten, dass das „Verhalten“ des Skripts für einen Screenreader sinnvoll ist (da die Software ziemlich dumm ist) :)
Ich habe noch eine Änderung vorgenommen, die hoffentlich etwas verbessert. Ich habe das title-Attribut zu jedem Link hinzugefügt, der „Antwort anzeigen“ vorlesen sollte, was das Verhalten etwas besser erklären sollte.
Hallo nochmal... und entschuldige, dass ich so nerve.
Dasselbe Problem. Der blinde Benutzer wird nichts von der Antwort unten wissen. „Antwort“ als Name ist perfekt klar (und du brauchst kein „Anzeigen“ hinzuzufügen)... es ist nur, dass der Benutzer nicht wissen wird, dass sie *über* der Antwort platziert ist (und sie unter dem „Antwort“-Button erwarten wird), da dies die Tabulatorreihenfolge ist.
Auch bei LINK-TITELN... einige Screenreader ignorieren sie komplett (wie Supernova/HAL) :(
Na gut, weitere Änderungen =)
Ich habe einige Layout-Änderungen und Code-Platzierungsänderungen vorgenommen, von denen ich hoffe, dass sie dies lösen. Jetzt erscheint der Tab links und öffnet die Schublade, die die Antwort rechts enthält. Die Antwort kommt tatsächlich nach dem Code für den „Anzeigen“-Link, also hoffe ich, dass das deutlicher ist.
Lass mich wissen, wie es läuft.
Ok……
Erstens schätze ich, dass du es versuchst :)
Ich habe das mit meinem Screenreader (und Internet Explorer 6.0) noch einmal getestet. Das Layout war stark durcheinander (mit den "Antwort-Buttons" über die Seite verstreut darunter). Theoretisch sollte dein Denken aber funktionieren, und wenn CSS deaktiviert wird, sieht es so aus, als ob es perfekt sein sollte, mit der Antwort darunter.
Beim Deaktivieren von CSS... aus irgendeinem Grund vermischt der Screenreader den Satz und den "Antwort"-Link und liest den "Antwort"-Link nicht vor. Der Screenreader liest für den "Antwort"-Link "Antwort – Gemischter Link" und normalerweise funktioniert der Link selbst nicht (nicht anklickbar).
Es wäre vielleicht erwähnenswert, den Link zu "verschieben", sodass er in der nächsten Zeile erscheint, wenn CSS deaktiviert ist, damit er nicht als ein Satz gelesen wird? Und schau dir auch das Layout in IE 6.0 an :) Ich habe es nicht in IE 7.0 angeschaut. Firefox ist in Ordnung, funktioniert aber nicht mit dem Screenreader (keine Sorge, tut er nie).
Web-Barrierefreiheit kann ein Albtraum sein…!!!
Also gut, die nächste Runde ist bereit =)
Ich sehe, was du mit deaktiviertem CSS meinst, aber das würde davon ausgehen, dass du CSS deaktiviert und JavaScript aktiviert hast, was ziemlich selten wäre, oder? Jedenfalls glaube ich, ich habe es repariert, sodass es in der nächsten Zeile steht.
Hurra!!!
Das funktioniert perfekt... sowohl für Screenreader als auch für mobil eingeschränkte Benutzer.
Es ist gut zu bedenken, dass, wenn man CSS deaktiviert, das die „Lesereihenfolge“ von Screenreadern ist. Der Name „Screenreader“ ist tatsächlich nicht ganz korrekt, da die Software auch den HTML-Code ausliest, nicht nur den Bildschirm :)
Du kannst mir gerne zukünftig Sachen zum Testen schicken (ich bin Web-Barrierefreiheits-Berater) :)
Gute Arbeit.
Cool!
Ich glaube, das wird das Thema der dieswöchigen Screencast sein.