Zum Inhalt springen

Simple drop-down Menu plus Mobile Menu using TYPO3-Fluid + HTML5 + CSS – without JavaScript

Last updated on 12. März 2019

Let’s quote the German singer Wolfgang Petri: „Das ist Wahnsinn, warum schickst Du mich in die Hölle – Hölle, Hölle, Hölle …?“ („This is crazy, why are you sending me to hell – hell, hell, hell …?“)

Yes, we like TYPO3 for it’s flexibility and it’s uniqueness, but then we have to go through an IDE (in my case Visual Studio Code), since things get piled up, so we have to be prepared. Next step is TypoScript – my feeling is, no person ever has really mastered it completely. Now we have this new kid on the block, „fluid“ which brings some nice more methods and frameworks – fluid templates and viewhelpers – and finally we come to HTML5 – basically the only thing that really matters –, write a lot, a lot of CSS and thank god skip JavaScript and JQuery. Buff! There are damn many trees in this forest!

Simple?
The intention was to create a simple menu and mobile menu without using JavaScript and JQuery.

Preposition

After gifting us with the additional markup language YAML, another blog commented to the TYPO3 core developers with a quote from the German singer Tony Marshall: „Einer geht noch, einer geht noch rein …“ („Let’s have one more, there is still space for one more …“, The song text refers to a drink in the beginning of the song and some sexual innuendo at the end.)

If someone wants to make things simpler and more easy with another nice framework, be careful, usually things get much more error-prone and more complicated anyway. If you save some code-writing on one side, you will have to add three times the amount of code on the other side. But while customers out there are not ready for my radical kind of zen approach, using pure HTML5 („PHTML5“), we have to flow with the ignoble crowd and add another level of abstraction, to another level of abstraction, hoping for the hardware to get faster and faster with the same amount of velocity.

PHTML5

is a concept „developed“ at zazu.berlin by Thomas Hezel, by just using pure HTML5 – And that’s it!

It is fast, super extra fast, mobile friendly and shows up in the worst wireless lan conditions you can imagine. You will experience 100% cross browser compatibility. It is perfect readable and the code to content ratio is on the highest score.

So, why not going back to a pure simple approach and let the browser do the styling while we give all our passion and thoughts to the content? You will experience the beauty of simplicity!

Try it, it is fun and super easy!

Thomas Hezel – https://www.thomas-hezel.de

Back to Work

What do we need?

  • We want to be up to date, so we use TYPO3 sitepackages (The attempt to give the ordinary integrator a little uplift to a level we could call „developer light“. Creates also a big wall for people who want to start with TYPO3).
  • TYPO3 version 9.x (we are now in the year 2019). No other extension needed, we create our own one.
  • Backend Layouts, corresponding to our optional different Templates for the page setup. (you need: Backend Layouts, TypoScript)
  • Normal Menu that converts into a Mobile Menu without JavaScript and without JQuery, just HTML5 and CSS. (You need: TypoScript, Fluid-Layout, Fluid-Template, Fluid-Parital, HTML5, CSS)
  • no SVG, no png for the Mobile Menu button, just HTML5 and CSS
  • Write a Readme.txt file for yourself. In one year you will have no idea what this nice code you have written in a ingenious flow does. (If you want to add another framework („Einer geht noch …“), you can put up a Documentation folder with .reST-files. -> (information about restructured text reST is available online)

TYPO3 Sitepackages

The core team of TYPO3 has decided, that the „fileadmin“, where we stored so nicely our stuff for years, is now a folder just for the user of the system (editor). All setup and configuration files from the TYPO3 integrator should go into a individual simple TYPO3 extension (without PHP classes etc.). It separates the userspace from the creatorspace and makes it possible to do version control (git) and an easy to deploy system for new web pages.

If you are a reading person, you should try the following link:
From Michael Schams (Well written and good to understand! Great work!):
https://docs.typo3.org/typo3cms/SitePackageTutorial/

If you like an instant solution and a lot of additional systematic basic settings:
Use the Kickstarter from Benjamin Kott:
https://sitepackagebuilder.com/

If you are more visual receptive, try the videos on the TYPO3 video channel. Unfortunately on youtube and not on a dedicated TYPO3.org host:
https://www.youtube.com/watch?v=HtBmim7pc0o

My approach was to read the documentation, then tried to put my own thing together. In the next step, I compared my solution with the kickstarter and made changes, so my solution has the same naming as the official kickstarter.

To stay with the same naming and folder structure for all setups is important, so we can share things and will be familar with every installation whoever has created it.

This are roughly the changes to the old workflow:

  • you need at least two php-files to register your extension (ext_emconf.php, sys_template.php)
  • you must add a static template from your extension, as you do with most other extensions in your backend (Templates -> root page -> include static). Don’t forget this step! This integrates your „page=page“ TypoScript.
  • you can use locallang.xlf files to translate phrases in your templates for the frontend output and for the backend (e.g. backend layouts)
  • instead of „/fileadmin/Resources/Public/Icons/favicon.ico“ you will write: „EXT: zazupackage/Resources/Public/Icons/favicon.ico“, whereas „zazupackage“ is the name of your extension
  • you will locate your files and folders in typo3.conf/ext/yourpackage
  • to make your work not too complicated you should use an IDE (Visual Studio Code is free, phpStorm is affordable for a freelancer, both are fine). Install all the helpers for TYPO3!
  • the rest is more or less the same, with or without a sitepackage

The destination of the TYPO3 journey – HTML

The basic idea for the menu you can checkout here:

https://codepen.io/andornagy/pen/RNeydj
But we still have to do some adjustments, since this code is not really working for the different mobile menu levels.


principles:

  • HTML input fields are connected with their labels through a unique „id“ (#drop-1, #drop-2, #drop-3)
  • for the drop-down of the normal menu we use CSS „:hover“ for the mobile menu, with different levels, we use the „checked status“ of the input field „#id_xyz:checked“ (JQuery it would be the „.click()-handler“)
  • hide the input field – The click will still be registered and works on the status of the label-field! No standard input field check-box will be visible.
  • for the mobile menu we use the label-field for the drop-down (accordion) and the link <a> for the link
  • our navigation list element <li> has the following fields: <input>, <label> and <a>. -> note: input has display:none;
  • the drop-down elements gets a „+“ symbol with CSS „after-content“ and for the mobile menu a „-“ when status is „:checked“ for the accordion to close again.
<nav>
        <div id="logo">Your Logo here</div>

        <label for="drop" class="toggle">Menu</label>
        <input type="checkbox" id="drop" />
            <ul class="menu">
                <li><a href="#">Home</a></li>
                <li>
                    <!-- First Level Drop Down -->
                    <label for="drop-1" class="toggle">WordPress +</label>
                    <a href="#">TYPO3</a>
                    <input type="checkbox" id="drop-1"/>
                    <ul>
                        <li><a href="#">Themes and stuff</a></li>
                        <li><a href="#">Plugins</a></li>
                        <li><a href="#">Tutorials</a></li>
                    </ul> 

                </li>
                <li>

                <!-- First Level Drop Down -->
                <label for="drop-2" class="toggle">Web Design +</label>
                <a href="#">Web Design</a>
                <input type="checkbox" id="drop-2"/>
                <ul>
                    <li><a href="#">Resources</a></li>
                    <li><a href="#">Links</a></li>
                    <li>
                       
                    <!-- Second Level Drop Down -->        
                    <label for="drop-3" class="toggle">Tutorials +</label>
                    <a href="#">Tutorials</a>         
                    <input type="checkbox" id="drop-3"/>

                    <ul>
                        <li><a href="#">HTML/CSS</a></li>
                        <li><a href="#">jQuery</a></li>
                        <li><a href="#">Other</a></li>
                    </ul>
                    </li>
                </ul>
                </li>
                <li><a href="#">Graphic Design</a></li>
                <li><a href="#">Inspiration</a></li>
                <li><a href="#">Contact</a></li>
                <li><a href="#">About</a></li>
            </ul>
        </nav>


        <p> A simple dropdown navigation menu made with CSS Only. Dropdowns are marked with a plus sign ( + )</p>
<!--This basic layout is from from Andor Nagy-->

The hamburger menu we will create with a HTML-box and three lines made out of <span>-tags

The basic idea is from here:

https://www.mediaevent.de/tutorial/css-transform.html

The trick is to use a <label> box and fill it with three lines made out of <span>s, then animate the lines with CSS „transform“ on the status of „:checked“ (same principle as above):

CSS for top and bottom hamburger menu line after the click:

transform: 0.5s;
transform-origin: center;
transform: translateY(12px) rotate(-45deg);
transform: translateY(12px) rotate(45deg);

for the second line of the hamburger menu after the click:
opacity: 0;

This gives us a nice X in the end.

mobile menu closed
HTML mobile menu button closed
mobile menu partly open


STEP 1: A word about Backend Layouts

All information on how to register backend layouts, you will find in the documentation of TYPO3 for sitepackages: https://docs.typo3.org/typo3cms/SitePackageTutorial/

Not well described in the documentation is the function of the object „pagets__yourNameOfTheBackendLayout
The expression „pagets__“ is set in TYPO3 and comes automatically. The „yourNameOfTheBackendLayout“ is from the name you put in front of the parentheses in your BackendLayout setup; here „zazupackage_default“:

mod.web_layout.BackendLayouts {
  zazupackage_default {
    title = LLL:EXT:zazupackage/Resources/Private/Language/locallang.xlf:backendLayout.zazupackage_default.title
    icon = EXT:zazupackage/Resources/Public/Images/BackendLayouts/bel-1-col.png
    config {
      backend_layout {
        colCount = 1
        rowCount = 1
        rows {
          1 {
            columns {
              1 {
                name = LLL:EXT:zazupackage/Resources/Private/Language/locallang.xlf:backendLayout.zazupackage_default.columnName.colPos_0
                colPos = 0
              }
            }
          }
        }
      }
    }
  }
}

Then in your TypoScript fluid setup you connect it to a template name that TYPO3 will search for in EXT:yourExtensionName/Resources/Templates/Page/…

// Part 1: Fluid template section
    10 = FLUIDTEMPLATE
    10 {
        templateName = TEXT
        templateName.stdWrap.cObject = CASE
        templateName.stdWrap.cObject {
            key.data = pagelayout
//pagelayout is Backend Layout, pagets is PageTSConf
            pagets__zazupackage_default = TEXT
            pagets__zazupackage_default.value = Default

            pagets__2_column = TEXT
            pagets__2_column.value = Two-Column

            default = TEXT
            default.value = Default
        }

„zazupackage_default“ is the name of the backend layout setup
this is directed to a template file with the name
„Default.html“
or
„Two-Column.html“
(No need to write the „.html“-Extension of the file names in your fluid setup!)
Depending what you choose in the backend of the page-settings, a different Template.html file will be rendered.

If you are not using backend layouts and different template files for your different pages of your website, just make it simple:

10 = FLUIDTEMPLATE
   10 {
   template = FILE
   template.file = EXT:yourExtensionName/Resources/Private/Templates/mainTemplate.html

If you use the DCE-extension (from Armin Vieweg), you don’t need the whole mess, just go for one template.html file and be happy. In the backend you just use one content column. Straight – simple – nice.

STEP 2: TypoScript – FLUIDTEMPLATE setup for the Menu

page = PAGE
page {
    typeNum = 0
    shortcutIcon = EXT:zazupackage/Resources/Public/Icons/favicon.ico

    // Part 1: Fluid template section
    10 = FLUIDTEMPLATE
    10 {
        templateName = TEXT
        templateName.stdWrap.cObject = CASE
        templateName.stdWrap.cObject {
            key.data = pagelayout
                    //pagelayout is Backend Layout, pagets is PageTSConf
            pagets__zazupackage_default = TEXT
            pagets__zazupackage_default.value = Default

            pagets__2_column = TEXT
            pagets__2_column.value = Two-Column

            default = TEXT
            default.value = Default
        }

        //second line is constants $page the "page-object-variable"
        templateRootPaths {
            0 = EXT:zazupackage/Resources/Private/Templates/Page/
            1 = {$page.fluidtemplate.templateRootPath}
        }

        partialRootPaths {
            0 = EXT:zazupackage/Resources/Private/Partials/Page/
            1 = {$page.fluidtemplate.partialRootPath}
        }

        layoutRootPaths {
            0 = EXT:zazupackage/Resources/Private/Layouts/Page/
            1 = {$page.fluidtemplate.layoutRootPath}
        }

        dataProcessing {
            10 = TYPO3\CMS\Frontend\DataProcessing\MenuProcessor
            10 {
              levels = 3
              expandAll = 1
              includeSpacer = 1
              as = menuMain
            }
            20 = TYPO3\CMS\Frontend\DataProcessing\MenuProcessor
            20 {
                special = list
                special.value = 1
                levels = 1
                as = justHome
            }
            30 = TYPO3\CMS\Frontend\DataProcessing\MenuProcessor
            30 {
                special = rootline
                special.range = 0|-1
                includeNotInMenu = 1
                as = menuBreadcrumb
            }
            40 = TYPO3\CMS\Frontend\DataProcessing\MenuProcessor
            40 {
                special = directory
                special.value = 1
                levels = 3
                expandAll = 1
                includeSpacer = 1
                titleField = nav_title // title
                as = menuFooter
            }
            50 = TYPO3\CMS\Frontend\DataProcessing\MenuProcessor
            50 {
                special = directory
                special.value = 12
                levels = 1
                titleField = nav_title // title
                as = menuMeta
            }
        }

    }
} 

Information about the „templateRootPath“, „layoutRootPath“ and „partialRootPath“ you will find again in the documentation: https://docs.typo3.org/typo3cms/SitePackageTutorial/

What we are now looking for is the data processing section:

dataProcessing {
            10 = TYPO3\CMS\Frontend\DataProcessing\MenuProcessor
            10 {
              levels = 3
              expandAll = 1
              includeSpacer = 1
              as = menuMain
            }
}

This will render in an object called „menuMain“ as 3 level menu, including spacers. It will be our main menu that we now can use in the fluid layout file:

EXT:zazupackage/Resources/Layouts/Page/Default.html

For more and different menus – you give them a new number (e.g. 20) and a new „as= anotherMenu“ – you will find a good overview here: https://www.thomaskieslich.de/blog/132-typo3-8-menues-mit-fluid-und-menuprocessor-erstellen/

Why in the layout file Default.html?

The rule is:

  • everything that is on every page of your website is in Layouts/YourName.html
  • everything that is on a special type of page is in Templates/YourName.html (you can choose different Templates in the page backend -> see above)
  • small things that can be on any page and even more then once are in Partial/YourName.html

Since the main menu will not change on different pages inside the website, the fluid template code will go in my case in the /Layouts/Default.html file.

STEP3: The place where finally HTML is created – the fluid layout Default.html file

<header id="mainHeader" class="wrapper clearfix">
    <div class="center">
        <figure id="logoContainer">
            <a href="index.php?id=1" title="Hier kommen Sie zur Startseite.">
                    <svg id="logo" >
               </svg>
            </a>
        </figure>
        <div id="mainMenuBox">
            <div id="headerContact">
                <a href="tel:+49307859279">+49 30 785 9279</a><br />
                <a href="mailto:info@zazu.berlin">info@zazu.berlin</a>
            </div>

            <nav id="mainMenu">
                <input type="checkbox" id="hamburger" />
                <label for="hamburger" class="hamburger">
                    <span class="hamburgerLine"></span>
                    <span class="hamburgerLine"></span>
                    <span class="hamburgerLine"></span>
                </label>

                <f:comment>Menu for 3 Levels plus Home on Top as separate dataProcessor jsutHome</f:comment>
                <ul id="mainMenuList">
                    <f:for each="{justHome}" as="itemH">
                        <li class="level1{f:if(condition: itemH.current, then:' current')}">
                            <a href="{itemH.link}" target="_top" title="{itemH.title}">
                                {itemH.title}
                            </a>
                        </li>
                    </f:for>

                    <f:comment>assign label to input with unique numbers</f:comment>
                    <f:variable name="counter" value="0" />

                    <f:for each="{menuMain}" as="mainnavigationItem">
                        <li class="level1{f:if(condition: mainnavigationItem.current, then:' current')}{f:if(condition: mainnavigationItem.active, then:' active')}{f:if(condition: mainnavigationItem.children, then:' plus')}">
                            <f:if condition="{mainnavigationItem.children}">
                                <f:then>
                                    <f:comment>level-1-children-yes</f:comment>

                                    <f:variable name="counter" value="{counter+1}" />
                                    <input type="checkbox" id="drop-{counter}" />
                                    <label for="drop-{counter}" class="toggle"></label>
                                    <a href="{mainnavigationItem.link}" target="_top"
                                        title="{mainnavigationItem.title}">
                                        {mainnavigationItem.title}
                                    </a>

                          <ul>
                              <f:for each="{mainnavigationItem.children}" as="child">
                                  <li class="level2{f:if(condition: child.current, then:' current')}{f:if(condition: child.active, then:' active')}{f:if(condition: child.children, then:' plus')}">
                                      <f:if condition="{child.children}">
                                          <f:then>
                                              <f:comment>level-2-children-yes</f:comment>

                                              <f:variable name="counter" value="{counter+1}" />
                                              <input type="checkbox" id="drop-{counter}" />
                                              <label for="drop-{counter}" class="toggle"></label>
                                              <a href="{child.link}" target="_top" title="{child.title}">
                                                  {child.title}
                                              </a>

                                              <f:comment>level-3 is just-children of level-2 - - no level 4
                                              </f:comment>
                                              <ul>
                                                  <f:for each="{child.children}" as="childOf2">
                                                      <li class="level3{f:if(condition: childOf2.current, then:' current')}">
                                                          <a href="{childOf2.link}" target="_top" title="{childOf2.title}">
                                                              {childOf2.title}
                                                          </a>
                                                      </li>
                                                  </f:for>
                                              </ul>

                                          </f:then>
                                          <f:else>
                                              <f:comment>level-2-children-no</f:comment>

                                              <a href="{child.link}" target="_top" title="{child.title}">
                                                  {child.title}
                                              </a>

                                          </f:else>
                                      </f:if>
                                  </li>
                              </f:for>
                          </ul>

                      </f:then>
                      <f:else>
                          <f:comment>level-1-children-no</f:comment>

                          <a href="{mainnavigationItem.link}" target="_top" title="{mainnavigationItem.title}">
                              {mainnavigationItem.title}
                          </a>

                      </f:else>
                  </f:if>
              </li>
          </f:for>
      </ul>
  </nav>
</div>
</div></header>

<f:render section="Main" />

For the hamburger menu button it should be now clear and straight

We hide the <input>-field with „display:none“ and use the label as our button. The look is created with some CSS like: „border: solid 1px #ccc;“ and „display:block;“ The same for the <span class=“hamburgerLinie“> with a „height:2px;“. Since the <span>s are inside of <label> we can use the status of the label as „:checked“ to open up all our <li>s and <ul>s on click with the mobile menu.

<nav id="mainMenu">
                <input type="checkbox" id="hamburger" />
                <label for="hamburger" class="hamburger">
                    <span class="hamburgerLine"></span>
                    <span class="hamburgerLine"></span>
                    <span class="hamburgerLine"></span>
                </label>

Always trouble with the page „HOME“

In the old days („just after the 68th revolution“) we made a TYPO3 shortcut page in the page tree from „HOME“ as root-page to „Home“ as a page that will be shown, just to have the page „Home“ in the menu. This will create a server redirect from the straight domain name to www.domain.de/home.

Since redirects are not very search engine friendly, I nowadays just create the menu <li>link</li> as a separate menu. Some people just skip the whole home menu element and assume that people know they have to click on the logo to come to the starting point. Do all people know it? I don’t know!

 <f:for each="{justHome}" as="itemH">
    <li class="level1{f:if(condition: itemH.current, then:' current')}">
       <a href="{itemH.link}" target="_top" title="{itemH.title}">
          {itemH.title}
       </a>
    </li>
</f:for>

What is going on here?
We loop over all items in the object „justHome“. If you scroll up to the TypoSript section, you will see in our TypoScript setup, that we created in fluid a MenuProcessor with the number 20 and said it should take from a „special=list“ the „special.value=1“ and put it in an object with the name „as=justHome“. The number 1 is, in my case, the home page in the TYPO3 backend. You get the number if you hover over the name in the backend page tree. The <f:for each= …> is a viewhelper (a system inside the fluid system, inside TYPO3 …). The viewhelper takes the menu object {justHome} and iterates through it giving each item (in this case it is just one) the new variable „itemH“. This „itemH“ is indeed an object that holds things like the link, the title of the link and more.

You can check what is in the object by placing inside the loop the code: <f:debug>{justHome}</f:debug> (Of course you must use the objects name you have chosen.)


That’s how we create a nice link to the page „Home“, just wrapped by <li></li>. We assume (make sure) that Home doesn’t have sup-pages-children.

The first level and the second level of the menu

 <f:if condition="{mainnavigationItem.children}">
      <f:then>
 <f:comment>level-1-children-yes</f:comment>

      <f:variable name="counter" value="{counter+1}" />
      <input type="checkbox" id="drop-{counter}" />
      <label for="drop-{counter}" class="toggle"></label>
      <a href="{mainnavigationItem.link}" target="_top" title="{mainnavigationItem.title}">
        {mainnavigationItem.title}
      </a>

           <ul>
           <f:for each="{mainnavigationItem.children}" as="child">

Now we have a little challenge for TYPO3:

The <input>-tag and the <label>-tag need a unique id to connect with each other. So with each round of the loop we have to assign a unique number. This is done by using the variable viewhelper:
<f:variable name=“counter“ value={counter+1}“ />
We let it add 1 after each round. The variable is accessible in the entire document, so we can use it in different loops and get a unique number for each menu element’s id.
id=“drop-{counter}“

BUT:
We want to hide all these input buttons with CSS, how can we do this without a unique name? The answer ist here:

[id^=drop] {
display: none;
}

For me this CSS-selector was new. „Select all id’s starting with the phrase ‚drop‘ –.“

A lot of loops

<f:for each="{menuMain}" as="mainnavigationItem">
                        <li class=" … ">
                            <f:if condition="{mainnavigationItem.children}">
                                <f:then>
                                    <f:comment>level-1-children-yes</f:comment>

                                    <f:variable name="counter" value="{counter+1}" />
                                    <input type="checkbox" id="drop-{counter}" />
                                    <label for="drop-{counter}" class="toggle"></label>
                                    <a href="{mainnavigationItem.link}" target="_top"
                                        title="{mainnavigationItem.title}">
                                        {mainnavigationItem.title}
                                    </a>

                          <ul>
                              <f:for each="{mainnavigationItem.children}" as="child">
                                  <li class=" … ">
                                      <f:if condition="{child.children}">
                                          <f:then>
                                              <f:comment>level-2-children-yes</f:comment>


In the fist line, we check whether the element has children (take a look inside the object with <f:debug>, as shown above, for the available object elements), – if this is true – the menu element has subpages – we start creating the link and add the class=“toggle“ to the <label>. This will allow us to add with CSS and label:after {content:“+“} the plus sign and after this the click effect for the mobile menu to open up.

It is important, that the sequence is <counter>, <input>, <label>, <a>.
<label> must be on top of <a> because in the mobile menu we use both, <label> and <a>. In the mobile menu both is visible, but <label> is just holding the plus sign (or minus sign), is floated to the right, with some 10% of width and gets a negative margin to come on top of (over) the <a>-menu link. If you click right on + or – CSS („:checked“) will make the subpages visible or hide them. If you click on the left side you will hit the link.

For the hover-effect of the normal menu we can just use :hover on the <li>-element that surrounds the link <a>.


The second level of the menu – more loops

 <ul>
    <f:for each="{mainnavigationItem.children}" as="child">
       <li class="level2{f:if(condition: child.current, then:' current')}{f:if(condition: child.active, then:' active')}{f:if(condition: child.children, then:' plus')}">
         <f:if condition="{child.children}">
           <f:then>                                                        
             <f:comment>level-2-children-yes</f:comment>
             <f:variable name="counter" value="{counter+1}" />
             <input type="checkbox" id="drop-{counter}" />
             <label for="drop-{counter}" class="toggle"></label>
             <a href="{child.link}" target="_top" title="{child.title}">
               {child.title}
             </a>
                                                      
           <f:comment>level-3 is just-children of level-2 - - no level 4</f:comment>
           <ul>                               
             <f:for each="{child.children}" as="childOf2">                                                                 
               <li class="level3{f:if(condition: childOf2.current, then:' current')}">
                 <a href="{childOf2.link}" target="_top" title="{childOf2.title}">
                   {childOf2.title}                                                                    
                 </a>                                                           
             </li>                                                            
            </f:for>
           </ul>

For the second level we create a loop for the „children“ as „child“ and do the same thing. For the third level we take the „child“ from „children“ and do a loop for „child.children“ as children of the second level „childOf2“.

For the <li>-element we always check the status whether it is a page that is active, so it get’s the class=“active“ or it is the link of the page the user is right on, then it get’s the class=“current“.

active = the line of pages where you find the page that the user is on at the end
current = the current page the user is on

CSS

My CSS, you should change it according to your styling!

/**
*
* mainMenu – zazu.berlin
* final setup and TYPO3
* by Thomas Hezel 2019
*
* basic setup
* https://codepen.io/andornagy/pen/RNeydj
* by Andor Nagy
*
**/

/*mobile Menu Hamburger*/

label.hamburger {
    display: none;
    border: solid 1px #95de11;
    width: 71px;
    height: 46px;
    position: relative;
    margin-left: auto;
    margin-right: auto;
    float: left;
    cursor: pointer;
    margin-top: 0.4em;
}

input#hamburger {
    display: none
}

.hamburgerLine {
    position: absolute;
    left: 10px;
    height: 4px;
    width: 51px;
    border-radius: 4px;
    background: #5c2466;
    display: block;
    transition: 0.5s;
    transform-origin: center;
}

.hamburgerLine:nth-child(1) {
    top: 8px;
}

.hamburgerLine:nth-child(2) {
    top: 20px;
}

.hamburgerLine:nth-child(3) {
    top: 32px;
}

#hamburger:checked+.hamburger .hamburgerLine:nth-child(1) {
    transform: translateY(12px) rotate(-45deg);
}

#hamburger:checked+.hamburger .hamburgerLine:nth-child(2) {
    opacity: 0;
}

#hamburger:checked+.hamburger .hamburgerLine:nth-child(3) {
    transform: translateY(-12px) rotate(45deg);
}

/*NAVIGATION main NAV*/

#mainMenuBox .toggle,
[id^=drop] {
    display: none;
}

/* Since we'll have the "ul li" "float:left"
we need to add a clear after the container. */

#mainMenuBox nav:after {
    content: "";
    display: table;
    clear: both;
}

/* Removing padding, margin and "list-style" from the "ul",
 * and adding "position:reltive" */

#mainMenuBox nav ul {
    float: right;
    padding: 0;
    margin: 0;
    list-style: none;
    position: relative;
}

/* Positioning the navigation items inline, no inline float left instead*/

#mainMenuBox nav ul li {
    margin: 0px;
    float: left;
    border-bottom: solid 1px #95de11;
}

/* Styling the links */

#mainMenuBox nav a {
    display: block;
    padding: 17px 20px;
    /*padding top corresponds to font-size*/
    font-size: 17px;
    text-decoration: none;
}

/*from second level onwards background color*/
#mainMenuBox nav ul li ul li {
    background-color:rgba(240,240,240,0.6);
}

/*level 2 when hover over level 3*/
#mainMenuBox nav ul li ul li:hover {
    background: #a8b7c7;
}

/* Background color change on hover same as mobile nav!*/
#mainMenuBox nav a:hover {
    background-color: #e8f6d4;
}

/* Hide dropdowns by default
 * and giving it a position of absolute */

#mainMenuBox nav ul ul {
    display: none;
    position: absolute;
    /* has to be the same number as the "line-height" of "nav a" */
    top: 60px;
}

/*level 2 drop down*/

#mainMenuBox nav ul li:hover>ul {
    display: inherit;
}

/*first row drop down*/

#mainMenuBox nav ul ul li {
    float: none;
    display: list-item;
    position: relative;
    width: 170px;
}

/* second and other rows to the left
*  by the amount of the first row
*  left: - minus for menu items at the right border
*
*  avoid a second level for the very last item if your
*  menu floats right to the border of the screen
*  and the second level has a longer name then the first
*/
#mainMenuBox nav ul ul ul li {
    position: relative;
    top: -60px;
    /* same number as width nav ul ul li */
    left: 170px;
}

#mainMenuBox nav ul li:nth-child(7) ul ul li {
    left: -170px;
}


/* change '+' in order to change the dropdown symbol*/

#mainMenuBox li>a:after {
    content: '+';
}

#mainMenuBox li>a:only-child:after {
    content: '';
}

/*======= 760========= MEDIA QUERIES MAX WIDTH !!! only for Menu ======== Rand 16 = 728 ===*/

@media all and (max-width: 760px) {
    #mainMenuBox {
        position: static;
        /*back to normal for "absolute" telefon, mail back to Header*/
    }
    label.hamburger {
        display: block;
    }
    /* zazu: plus sign is now from label*/
    #mainMenuBox li>a:after {
        content: '';
    }
    /*hide the nav menu, not the LINK!*/
    /*.toggle+a,*/
    #mainMenuList {
        display: none;
    }
    /* Styling the toggle label
    * zazu:
    * label is no page link! only for drop down
    * floats right and with neg. margin down
    */
    #mainMenuBox .toggle {
        display: block;
        padding: 15px 20px 10px 20px;
        text-decoration: none;
        border: none;
        margin-bottom: -40px;
        width: 20%;
        float: right;
        cursor: pointer;
    }
    #mainMenuBox .toggle:hover {
        color: #5c2466;
    }
    #mainMenuBox .toggle:after {
        content: '+';
        font-size: 1.5em;
        color: #5c2466;
    }
    #mainMenuBox [id^=drop]:checked+.toggle:after {
        content: '–';
        color: #5c2466;
    }
    /*second level, different style*/
    #mainMenuBox nav ul li ul li .toggle {
        padding: 15px 20px 10px 20px;
    }
    /* Display Dropdown when clicked on Parent Label*/
    #hamburger:checked+label+ul,
    #mainMenuBox [id^=drop]:checked+label+a+ul {
        display: block;
    }
    /* Change menu item's width to 100% */
    #mainMenuBox nav ul li {
        display: block;
        width: 100%;
    }
    #mainMenuBox nav ul ul .toggle,
    #mainMenuBox nav ul ul a {
        padding: 0 40px;
    }
    #mainMenuBox nav ul ul ul a {
        padding: 0 80px;
    }
    #mainMenuBox nav a:hover {
        background-color: #7fcce0;
        border: none;
    }
    #mainMenuBox nav ul ul a,
    #mainMenuBox nav ul ul ul a {
        padding: 14px 20px;
        font-size: 17px;
    }
    /*second level color*/
    #mainMenuBox nav ul ul a {
        background-color: #e8fccd;
    }
    /*third level color*/
    #mainMenuBox nav ul ul ul a {
        background-color: #a9e954;
    }
    /* Hide Dropdowns by Default second level*/
    #mainMenuBox nav ul ul {
        float: none;
        position: static;
    }
    /* Hide menus on hover */
    #mainMenuBox nav ul ul li:hover>ul,
    #mainMenuBox nav ul li:hover>ul {
        display: none;
    }
    /* fisrt level Dropdown */
    #mainMenuBox nav ul ul li {
        display: block;
        width: 100%;
    }
    #mainMenuBox nav ul ul ul li {
        position: static;
        /* has to be the same number as the "width" of "nav ul ul li" */
    }
}

@media all and (max-width: 330px) {
    #mainMenuBox nav ul li {
        display: block;
        width: 94%;
    }
}

/**
* header contact
**/

#headerContact {
    float: right;
    text-align: right;
}

#headerContact a {
    text-decoration: none;
    color: #2f383c;
}

/*======= 480 ========= MEDIA QUERIES ======= Rand 6 = 460 ===*/

@media only screen and (min-width: 480px) {
    #mainHeader #logoContainer {
        display: -webkit-box;
        display: -moz-box;
        display: -ms-flexbox;
        display: -webkit-flex;
        display: flex;
        justify-content: center;
    }
    #mainHeader #logo {
        width: 400px;
    }
}

/*======= 760========= MEDIA QUERIES ======== Rand 16 = 728 ===*/

/* @media now 761 not 760 since mixture of 'max' and 'min'*/

@media only screen and (min-width: 761px) {
    #mainHeader #logoContainer {
        padding: 1em 1em 1em 0;
        float: left;
        width: 40%;
        clear: right;
        justify-content: left;
    }
    #headerContact {
        margin-top: 0.95em;
    }
}

zazu.berlin normal menu
menu desktop screen size

For improvements of this manual, comments are very welcome!

Autor: Thomas Hezel

Ein Kommentar

  1. mtness mtness

    Hi there! Thanks for writing this down.
    There might be an easier way to achive your result –
    I have to look it up and will add another comment.
    Best regards, MT

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert