Wie man eine Navigation mit Hilfe von TypoScript und Bootstrap aufbaut, hatte ich in den letzten Artikeln dieses Wikis bereits beschrieben. Mit den Versionen 11 und 12 von TYPO3 gibt es die Möglichkeit, den MenuProcessor zu nutzen, um eine Navigation zu erstellen. Ein Vorteil des MenuProcessors in TypoScipt ist, dass man ein Array geliefert bekommt, auf das man Logiken aus Fluid anwenden kann. Daraus ergibt sich, dass man auch bei dieser Anforderung auf die VHS Extension verzichten kann, die zwar eine sehr große Hilfe ist, aber nicht immer bei einem TYPO3 Upgrade zur Verfügung steht. Mit dem MenuProcessor ist nun eine weitere Fähigkeit aus der VHS Extension in den TYPO3 Core übergegangen.
Um die Daten für die Navigation aus dem System auszulesen, kommt weiterhin TypoScript zum Einsatz. Hier ein Code Beispiel:
page { 10 { dataProcessing { ## Header Navigation 10 = TYPO3\CMS\Frontend\DataProcessing\MenuProcessor 10 { levels = 3 as = headerMenu expandAll = 1 excludeUidList = 6, 74, 25 titleField = nav_title // title } } } }
Die einzelnen Variablen für das System können wir über TypoScript steuern:
Die oben definierte Variable für das Array können wir nun an unser Fluid Template bzw. Partial übergeben und auswerten. Hier als Beispiel die MegaMenu Navigation der Agentur IBK:
<div class="container-fluid"> <div class="row navigation-top"> <div class="col-12 nav-container"> <nav class="navbar navbar-expand-md navbar-light bg-light"> <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbar" aria-controls="navbar" aria-expanded="false" aria-label="Toggle navigation"> <span class="navbar-toggler-icon"></span> </button> <div class="collapse navbar-collapse" id="navbar"> <ul class="navbar-nav mr-auto"> [...hier der Code für die einzelnen Ebenen...] </ul> </div> </nav> </div> </div> </div>
Wir gehen hier in mehreren Schleifen durch die Variable HeaderMenu. Über das Objekt Children können wir per Condition abfragen, ob ein Menupunkt Unterpunkte hat. Diese können wir dann in einer weiteren Schleife durchgehen. Die Links zu den einzelnen Seiten können wir mit dem <f:link.page> Viewhelper erzeugen. Dies ist der Code für den Platzhalter des Code Snippets oben:
<f:for each="{headerMenu}" as="menuLevel1Item"> <li class="nav-item dropdown has-megamenu"> <!-- Erste Ebene der Navigation --> <a class="nav-link dropdown-toggle" title="{menuLevel1Item.data.subtitle}" href="#" id="dropdown{menuLevel1Item.data.uid}" data-bs-toggle="dropdown"> {menuLevel1Item.data.title} </a> <div class="dropdown-menu megamenu container-fluid" role="menu"> <div class="row"> <f:if condition="{menuLevel1Item.children}"> <f:for each="{menuLevel1Item.children}" as="menuLevel2Item"> <!-- Zweite Ebene der Navigation --> <div class="col-12 col-sm-6 col-md-4 col-lg-3 div-nav"> <div class="col-megamenu"> <f:link.page pageUid="{menuLevel2Item.data.uid}" title="{menuLevel2Item.data.seo_title}" class="link-level3 strong"> {menuLevel2Item.data.title} </f:link.page> <f:if condition="{menuLevel2Item.children}"> <f:for each="{menuLevel2Item.children}" as="menuLevel3Item"> <!-- Dritte Ebene der Navigation --> <div class="row"> <div class="col-12 nav-level3"> <f:link.page pageUid="{menuLevel3Item.data.uid}" class="link-level3" title="{menuLevel3Item.data.seo_title}"> {menuLevel3Item.data.title} </f:link.page> </div> </div> </f:for> </f:if> </div> </div> </f:for> </f:if> </div> </div> </li> </f:for>
Das CSS dazu findet sich hier:
.has-megamenu { position: static; } .megamenu, .dropdown-menu.megamenu { margin-top: 0px; } @media (max-width:767px) { .megamenu, .dropdown-menu.megamenu { width: calc(100% + 20px); margin-left: -10px; margin-right: -10px; } } .nav-container { padding: 0; } #navbar>ul>li.nav-item.dropdown.has-megamenu>div { border-radius: 0; background-color: #eee; border: 5px #729ebd solid; padding: 0; box-shadow: 0px 30px 30px -15px #333; } #navbar>ul>li.nav-item.dropdown.has-megamenu>div .row { margin: 0; } .div-nav { padding: 5px; color: #333; transition: all 0.5s; } .div-nav:hover { background-color: #729ebd; color: #111; transition: all 0.8s; } nav.navbar { background-color: #275ba4; border: none; margin-top: 0px; margin-bottom: 0; min-height: 40px; padding-left: 15px; padding-right: 15px; border-radius: 0 0 0 0; background: linear-gradient(#275ba4, #729ebd); } ul.nav.navbar-nav>li>a { color: #a4c2ed; padding: 12px 8px; } ul.nav.navbar-nav>li>a:hover { color: #ccc; background: linear-gradient(#275ba4, #a4c2ed); } ul.dropdown-menu { padding: 0; } #navbar.navbar-collapse.collapse>ul.nav.navbar-nav>li.dropdown>ul.dropdown-menu { background-color: #729ebd; } .dropdown-menu>.active>a:focus, .dropdown-menu>.active>a { background-color: #275ba4; } .dropdown-menu { border: none; }
#navbar.navbar-collapse.collapse>ul.nav.navbar-nav>li.active>a { background: linear-gradient(#275ba4, #729ebd); color: #ddd; } #navbar.navbar-collapse.collapse>ul.nav.navbar-nav>li.dropdown.open>a.dropdown-toggle { background-color: #729ebd; } .dropdown-menu>.active>a:hover { background-color: #a4c2ed; color: #275ba4; } .dropdown-menu>li>a:hover { color: #275ba4; background-color: #a4c2ed; } div#navbar.navbar-collapse.collapse>ul.nav.navbar-nav>li.dropdown.active>a.dropdown-toggle { color: #eee; } .nav-level3 { padding: 0px 1px 0px 1px; font-size: 14px; } .nav-level3-img { padding: 1px 1px 1px 1px; } a.link-level3 { color: #275ba4; font-size: 14px; line-height: 22px; transition: all ease 0.5s; } a.link-level3:hover { color: #e8eff9; transition: all ease 0.5s; text-decoration: none; }
Schließlich brauchen wir noch den JavaScript Code, um das MegaMenu zum Leben zu erwecken
document.addEventListener("DOMContentLoaded", function(){ document.querySelectorAll('.dropdown-menu').forEach(function(element){ element.addEventListener('click', function (e) { e.stopPropagation(); }); }) });