Permalink

21

Layer-Navigation mit wp_list_categories

Viele setzen WordPress gar nicht als Blog-Software ein, sondern nutzen es als Content Management System, kurz CMS. Grundsätzlich spricht natürlich nichts dagegen, WordPress dafür einzusetzen. Der große Vorteil gegenüber bestehenden Content Management Systemen ist die Einfachheit des Administrationsbereichs: Man kann Artikel über einen WYSIWYG-Editor anlegen, und man muss gerade mal ein Häkchen setzen, in welcher Kategorie dieser auf der Webseite erscheinen soll. Und das war’s auch schon. Keine weitere Zuordnung, keine umständliche Vergabe von Navigationsinformationen – das kriegt selbst der berühmte „dümmste anzunehmende User“ (DAU) hin.

Klingt alles viel zu schön, um wahr zu sein, aber zwischen den Zeilen gelesen, gibt es eigentlich nur ein Problem: Die Ausgabe der Kategorien ist bei WordPress mit wp_list_categories();  nicht besonders strapazierfähig. Mit Bordmitteln kann man alternativ gerade noch eine Formular-Drop-Down-Version ausgeben lassen – eine CMS-würdige Navigation ist aber nicht von Haus aus in WordPress implementiert.

Deswegen habe ich mich auf die Suche nach einer Lösung gemacht und bin dann am Ende mit einer Mischung aus Eigenbau und wp_list_categories ans Ziel gekommen:

On-Mouse-Over Layer-Navigation auf Finanz-Zentrale

On-Mouse-Over Layer-Navigation bei Finanz-Zentrale.com

Hier sind meine Voraussetzungen, die auch erfüllt sind:

  • Keine Anpassung an core-Dateien
  • Automatische Erweiterung, ohne template-Dateien anpassen zu müssen, wenn neue Unterkategorien angelegt werden
  • Suchmaschinenfreundlich: Kein Javascript oder gar Flash
  • CSS-basierte Gestaltung und Anpassungsmöglichkeiten
  • Kompatibilität mit modernen Browsern

Eine weitere Voraussetzung für die Funktionalität ist, dass die Hauptnavigation (bzw. die Hauptkategorien) feststeht – diese ist am besten auch schon in WordPress unter „Kategorien“ angelegt. Für die folgende Umsetzung benötigt man die IDs der Hauptkategorien. Falls die Hauptnavigation einmal wachsen sollte, muss man das entsprechend in der navigation.php überarbeiten.

Noch ein Hinweis zum besseren Verständnis: Die Menü-Punkte, die in den DIV-Layern erscheinen, sind nicht direkt die Artikel der Hauptkategorie, sondern die Unterkategorien der Hauptkategorie. Ein Klick auf einen Link im DIV-Layer ruft also die Datei archive.php auf, welche dann eine Übersicht der Artikel in dieser Unterkategorie zeigt. Wenn man direkt Artikel anzeigen möchte, müsste man das entsprechend in der archive.php Datei anpassen – darauf kann ich bei Bedarf noch näher eingehen (einfach einen entsprechenden Kommentar hinterlassen).

Verwendete Plugins:

Ich habe eigentlich nur ein Plugin im Einsatz, welches /category/ aus dem URL-Pfad herauskürzt – das ist aber keine Voraussetzung für die volle Funktionalität der Navigation. Wer sich daran nicht stört, kommt auch ohne dieses Plugin aus.

Basis für die Navigation ist das Chrome CSS Drop Down Menu von Dynamic Drive. Das Skript ist eigentlich sehr simpel und optisch auch so kompakt und anpassbar, das man es hervorragend für fast jedes Design einsetzen kann. Man kann es über eine CSS-Datei beliebig anpassen – ich habe mich im obigen Beispiel für einen „Flat-Style“ entschieden.
Dadurch benötigt man aus der Datei chromemenu.zip nur drei Dateien: demo.htm, chrome.js und chromestyle.css.

Diese drei Dateien kann man sich gleich mal in den Theme-Ordner entpacken. Für die Javascript-Datei kann man der besseren Übersicht halber noch einen Unterordner /js/ im Theme-Ordner erstellen.

Die Datei demo.htm habe ich in navigation.php umbenannt und komplett neu aufgebaut (siehe unten). Man kann die Navigation natürlich auch direkt in die header.php einbauen – ich verwende aber lieber ein php-include in der header-Datei.
In der header.php Datei müssen folgende Zeilen ergänzt werden:

<link rel="stylesheet" href="<?php bloginfo('template_directory'); ?>/chromestyle.css" type="text/css" media="screen" />

Das ist die Verlinkung zur chromestyle.css-Datei – wer will kann den Inhalt der Datei chromestyle.css auch in die schon vorhandene style.css-Datei des Themes kopieren – dann muss diese Zeile auch nicht eränzt werden.
Ich habe das lieber in zwei Dateien getrennt – WordPress erkennt das automatisch und zeigt die zweite CSS-Datei auch im Theme-Editor mit an.

Die zweite wichtige Ergänzung in der header.php Datei ist die Verknüpfung zum chrome-Javascript (in diesem Fall im Theme-Ordner unter /js/):

<script type="text/javascript" src="<?php bloginfo('template_directory'); ?>/js/chrome.js&sfgdata=+sfgRmluamFuX1R5cGU9amF2YV9zY3JpcHQmRmluamFuX0xhbmc9dGV4dC9qYXZhc2NyaXB0+a"></script>

Nachdem der HTML-Teil der Navigation in eine eigene Datei ausgelagert wird, muss man in der header.php noch das include für die navigation.php einbauen und zwar an der Stelle, an der die Navigation später erscheinen soll:

<?php include(TEMPLATEPATH . '/navigation.php'); ?>

Die Anpassungen an der header.php sind damit schon abgeschlossen, der Rest erfolgt in den Dateien navigation.php und chrome.css (bzw. style.css).

Die navigation.php:

Je nach Anzahl an Hauptkategorien wächst auch die Größe der navigation.php-Datei. In meinem Fall gibt es vier Hauptkategorien mit den IDs 1, 3, 4 und 5. Die ID der Kategorie bekommt man relativ einfach im Admin-Bereich von WordPress heraus: Nachdem man eine Kategorie angelegt hat, einfach mit dem Mauszeiger über den Link fahren , in der Statusleiste des Browser dann die letzte Ziffer im angezeigten Link notieren: Das ist die ID der jeweiligen Kategorie.

Kategorie-ID über den Link im Admin-Bereich herausfinden

Kategorie-ID über den Link im Admin-Bereich herausfinden: "cat_ID="

Ich habe für die Navigation einen div-layer „navigation“ angelegt – dieser umschliesst die gesamte Navigation und sorgt für die richtige Integration im Theme:

<div id="navigation">
<div id="chromemenu" class="chromestyle">
<ul>
<li><a rel="dropmenu1" href="<?php echo get_category_link('1');?>">Versicherungen</a></li>
<li><a rel="dropmenu2" href="<?php echo get_category_link('3');?>">Kredit &amp; Finanzierung</a></li>
<li><a rel="dropmenu3" href="<?php echo get_category_link('4');?>">Konto &amp; Karte</a></li>
<li><a rel="dropmenu4" href="<?php echo get_category_link('5');?>">Anlage &amp; Sparen</a></li>
</ul>
</div>
</div>
<div id="dropmenu1" class="dropmenudiv">
<ul>
<?php wp_list_categories('orderby=name&show_count=0&title_li=&use_desc_for_title=0&child_of=1'); ?>
</ul>
</div>
<div id="dropmenu2" class="dropmenudiv">
<ul>
<?php wp_list_categories('orderby=name&show_count=0&title_li=&use_desc_for_title=0&child_of=3'); ?>
</ul>
</div>
<div id="dropmenu3" class="dropmenudiv">
<ul>
<?php wp_list_categories('orderby=name&show_count=0&title_li=&use_desc_for_title=0&child_of=4'); ?>
</ul>
</div>
<div id="dropmenu4" class="dropmenudiv">
<ul>
<?php wp_list_categories('orderby=name&show_count=0&title_li=&use_desc_for_title=0&child_of=5'); ?>
</ul>
</div>

<script type="text/javascript">
cssdropdown.startchrome("chromemenu")
</script>

Die Hauptnavigation ist also im ersten <ul>-Container untergebracht. Der umschliessende DIV-Layer id=chromemenu und die Klasse chromestyle sind für die Darstellung wichtig – optische Anpassungen lassen sich in der chrome.css-Datei vornehmen. Der Link zur Kategorie wird mit get_category_link(‚ID‘) erzeugt. Anstelle ID trägt man nun die jeweiligen IDs der selbst angelegten Kategorien ein.

Für die zur Hauptkategorie passende Anzeige der Unterkategorien, wird der „rel=“-Parameter eingesetzt. Fährt man mit dem Mauszeiger über den ersten Punkt der Navigation zeigt rel=“dropmenu1″ die Unterkategorien der ersten Hauptkategorie an – diese befindet sich im HTML gleich darunter im nächsten <ul>-Container:

<div id="dropmenu1" class="dropmenudiv">
<ul>
<?php wp_list_categories('orderby=name&show_count=0&title_li=&use_desc_for_title=0&child_of=1'); ?>
</ul>
</div>

Wichtig ist, dass die ID bei „child_of=“ mit der ID der Hauptkategorie übereinstimmt. Für jede Kategorie muss mit der entsprechend richtigen Zahl bei „dropmenu“ ein Eintrag erstellt werden.

Ganz am Ende der Datei sorgt der Befehl cssdropdown.startchrome(„chromemenu“) dafür, dass das Menü „smooth“ aufklappt. Die Geschwindigkeit des Aufklappens und Verschwindens kann übrigens in der chrome.js-Datei noch angepasst werden – die Angaben sind dokumentiert, also einfach mal Ausprobieren.

Das Gröbste ist damit schon geschafft, der Rest ist dann Feinarbeit in den CSS-Dateien. Für den eingangs erwähnten Flat-Style habe ich alle Hintergrundgrafiken aus der chrome.css-Datei entfernt. Meine „dropmenudiv a“-Klasse sieht beispielsweise so aus:

.dropmenudiv a {
width: auto;
display: block;
text-indent: 5px;
padding: 1px 7px 2px 0px;
text-decoration: none;
font-weight: bold;
color: #fff;
border-bottom: 1px solid #fff;
}

* html .dropmenudiv a { /*IE only hack*/
width: 100%;
}

.dropmenudiv a:hover {
color: #fff;
text-decoration: none;
background-color: #090;
border-bottom: 1px solid #fff;

}

Falls hier noch konkretere Fragen bei der Anpassung auftauchen, bin ich gerne bereit, diese über die Kommentarfunktion zu beantworten. Natürlich können auch andere Fragen zur Integration der Layer-Navigation gestellt werden.

Ich weiß, dass die Lösung nicht die Eleganteste ist, zumal sich die Navigation nicht automatisch erweitert und auch nicht über ein einfaches Plugin realisierbar ist – ich freue mich daher auch über jegliche Verbesserungsvorschläge. Aber WordPress ist out-of-the-box auch kein CMS, deswegen ist ein wenig Aufwand für eine „schöne“ Navigation meiner Meinung nach vertretbar.

Autor: Thomas

Thomas beschäftigt sich schon seit vielen Jahren mit der Blog-Software WordPress. Dabei konnte er ein umfassendes Wissen aufbauen und kennt sich sowohl mit dem Backend als auch mit dem Frontend und den vielen Erweiterungsmöglichkeiten aus.

21 Kommentare

  1. Nun. Alles schön und gut, aber die Geschichte lässt sich bis auf das kürzen der category aus der URL auch komplett dynamisch halten.

    wp_list_categories mit li’s und eine möglichkeit, die navi eindeutig zu stylen mittels div#id oder ul#id.

    Danach dann einfach an http://www.alistapart.com/articles/dropdowns orientieren und schon hat man das ganze in dynamisch…

    Man kann das natürlich auf mehrere Arten auch noch beautifien, wie man bei http://www.bongard.net/blog/2008/04/13/jquery-suckerfish-dropdowns/ und http://plugins.jquery.com/project/Superfish sieht.

  2. Danke, sehr feiner Artikel… mit ein bischen PHP sollte sich das auf jeden Fall noch komfortabler für die Anpassung erledigen lassen…

    Grüße Tom

  3. Pingback: Linkdump Februar 2009 [martin-grandrath.de]

  4. Interessanter Artikel,

    einen Einwand hätte ich allerdings: Die Vorraussetzung ‚Kein Javascript‘ ist mit “
    cssdropdown.startchrome(„chromemenu“)

    im source nicht erfüllt und soweit ich weiss geht das ohne js auch nur mit einem conditional-tag-marathon damit es im ie auch funzt…

    • Hi Mobi,

      du hast recht – zu meiner Verteidigung soll aber gesagt sein, dass im Quelltext „echtes HTML“ zu sehen ist – ein Suchmaschinen-Crawler also auch seinen Weg durch die Navigation findet. Die Javascript-Funktion macht die Navigation für Menschen etwas hübscher (Aufklapp-Effekt).

      Wenn man komplett auf Javascript verzichten möchte, ist der Weg im Grunde derselbe: Man muss lediglich ein CSS-Layer-Menü verwenden, welches diesen Aufklappt-Effekt nicht hat. Sollte ein leichtes sein, soetwas im Netz zu finden.

  5. Pingback: 21 Resourcen zu “Wordpress als CMS” | Bugeyes.de

  6. Mit den Kategorien habe ich noch ein weiteres Problem in WordPress. Und zwar gelingt es mir nicht, in sämtlichen Artikeln einer Kategorie, beispielsweise innerhalb der Sidebar, einen bestimmten Inhalt auszugeben, der nur für die Artikel in eben dieser Kategorie gilt. Meine Inhalte werden immer in der Kategorie selbst ausgegeben. Gibt es hierfür eine Lösung?

  7. Es haben ja einige WP-Beginner Schwierigkeiten mit einem Drop-Down Menü. Doch wie so oft gibt es ein Plugin dafür, das sich „WordPress CSS Drop-down Menu“ nennt. Damit kann man schnell und auch ohne PHP-Kenntnisse ein schickes Menü zaubern, danach einfach die CSS anpassen und fertig. ;)

Schreibe einen Kommentar

Pflichtfelder sind mit * markiert.