TYPO3 - CSS-Flyout Menü
Flyout oder Dropdown Menüs
Todo kleine Einführung und Links
Flyout wie auf hfwu.de
TypoScript
allgemeine Liste
Zuerst wird eine normale Liste (accessible) benötigt. Dies binden wir sowieso für alle Menüs ein (benötigt Extension cronaccessiblemenus)
temp.listMenu (V 1.0)
Constants:
Setup
temp.listMenu = HMENU
# Falls das Menü nicht bei der obersten Ebene anfangen soll
#temp.listMenu.entryLevel = 1
# Bei Bedarf einzelne Seiten aus dem Menü ausschließen
#temp.listMenu.excludeUidList = 1,2,3
temp.listMenu.1 = TMENU
temp.listMenu.1 {
wrap = <ul>|</ul>
noBlur = 1
IProcFunc = user_cronaccessiblemenus->makeAccessible
//NO.after = xyz
# Access Keys einschalten
IProcFunc.accessKeys = 1
# Hierarchische Nummerierung der Menüpunkte einschalten
IProcFunc.dfn = 1
IProcFunc.accessKeyWrap = <span class="accessKey">|</span>
IProcFunc.appendWrap = <span class="invisible"> (ALT-|)</span>
# Die folgenden Accesskeys nicht verwenden (bereits belegt)
IProcFunc.forbiddenKeys = 0,D,B,A,F,X,m,p
# Einstellungen für nicht-aktive Seiten
NO {
wrapItemAndSub = |*| <li class="NO"> | <span class="invisible">.</span></li>|*|<li class="NO last"> | <span class="invisible">.</span></li>
stdWrap.htmlSpecialChars = 1
# stdWrap.wrap = |abc
ATagTitle.field = abstract // description
}
# Einstellungen für Seiten, die sich in der Rootline befinden
ACT = 1
ACT {
wrapItemAndSub = |*| <li class="ACT"> | <span class="invisible">.</span></li> |*| <li class="ACT last"> | <span class="invisible">.</span></li>
stdWrap.htmlSpecialChars = 1
ATagTitle.field = abstract // description
}
# Einstellungen für die aktuelle Seite
CUR = 1
CUR {
wrapItemAndSub = |*| <li class="CUR"> | <span class="invisible">.</span></li> |*| <li class="CUR last"> | <span class="invisible">.</span></li>
stdWrap.htmlSpecialChars = 1
doNotLinkIt = 0
}
}
# Gleiche Einstellungen für die nächsten Ebenen
temp.listMenu.2 = TMENU
temp.listMenu.2 < temp.listMenu.1
temp.listMenu.3 = TMENU
temp.listMenu.3 < temp.listMenu.2
temp.listMenu.4 = TMENU
temp.listMenu.4 < temp.listMenu.2
Dieses binden wir im Haupttemplate ein. Die Values entryLevel etc. können dann später überschrieben werden.
Als nächstes bauen wir das dropDown Menu und nutzen dazu das vorbereitete listMenu im wesentlichen kommt hier nur noch eine id ins wrap:
temp.dropDown < temp.listMenu
temp.dropDown {
#maxItems = 3
special = directory
special.value = 3
1.wrap = <ul id="dropDown">|</ul>
1.noBlur = 1
}
Der Rest ist css. Einmal für die Formatierung der Liste und zusätzlich für das Zubehör der accessibility
Flyout / Dropdown Menü nach Sons of Suckerfish
Enthält wenig JS (für alte IEs)
aus: http://www.htmldog.com/articles/suckerfish/dropdowns/ (Datum des Zugriffs 5.4.2007)
Single-level Dropdowns
Right. Let's not beat around the bush. The initial HTML we're dealing with will look something like this:
<ul id="nav"> <li><a href="#">Percoidei</a> <ul> <li><a href="#">Remoras</a></li> <li><a href="#">Tilefishes</a></li> <li><a href="#">Bluefishes</a></li> <li><a href="#">Tigerfishes</a></li> </ul> </li> <li><a href="#">Anabantoidei</a> <ul> <li><a href="#">Climbing perches</a></li> <li><a href="#">Labyrinthfishes</a></li> <li><a href="#">Kissing gouramis</a></li> <li><a href="#">Pike-heads</a></li> <li><a href="#">Giant gouramis</a></li> </ul> </li> <!-- etc. --> </ul>
A good wholesome structured unordered list.
To set things up we need some basic styling:
#nav, #nav ul {
padding: 0;
margin: 0;
list-style: none;
}
#nav a {
display: block;
width: 10em;
}
#nav li {
float: left;
width: 10em;
}
Note that you need to specify a width in the #nav li selector or else Opera will chuck a wobbly. Also remember that because we're floating things, the content underneath the dropdowns also needs to be cleared (clear: left).
We obviously need to hide the lists that we want to 'drop down' but to make things as accessible as possible we need to avoid using display: none, which, as is commonly mentioned in image replacement write-ups, hides elements from some screen readers. You might think that there are a multitude of ways to deal with this, but having exhaustedly experimented with widths, heights, margins, top and clip across a large number of browsers, the best solution (accommodating multiple level lists anyway) lies in manipulating the left property.
The CSS specs say that top, right, bottom and left values should offset an absolutely positioned box from its containing block. But unfortunately Opera decides to offset absolutely positioned boxes in relation to the page and that's why the original Suckerfish Dropdowns didn't work on Opera - because they relied on the top and left properties with explicit lengths.
So instead of display: none we use left: -999em to propel the dropdown list out of view and then left: auto (rather than left: 0) to bring it back:
<pre>
#nav li ul {
position: absolute;
width: 10em;
left: -999em;
}
#nav li:hover ul {
left: auto;
}
And that will sort out everything for those browsers that fully support the :hover pseudo class, but for Internet Explorer we need to set the Suckerfish JavaScript loose:
sfHover = function() {
var sfEls = document.getElementById("nav").getElementsByTagName("LI");
for (var i=0; i<sfEls.length; i++) {
sfEls[i].onmouseover=function() {
this.className+=" sfhover";
}
sfEls[i].onmouseout=function() {
this.className=this.className.replace(new RegExp(" sfhover\\b"), "");
}
}
}
if (window.attachEvent) window.attachEvent("onload", sfHover);
Basically, this applies the 'sfhover' class to li elements in the 'nav' id'd ul element when they are 'moused over' and removes it, using a regular expression, when 'moused out'.
So now we've got the Suckerfish pumping out new classes, the next step is to simply duplicate the :hover selector with 'sfhover' class selectors:
#nav li:hover ul, #nav li.sfhover ul {
left: auto;
}
And there you go. Your standard single-level dropdown menu.
Multi-level Dropdowns
The original Suckerfish Dropdowns article covered only single-level dropdown menus, but with a bit of an extension of the cascading logic, it is quite possible to create multi-level dropdowns with CSS too. And, unlike the original Suckerfish JavaScript code, the 'sfHover' function now applies the behaviour to all of the descendent li elements of 'nav' rather than just the direct children so now multi-level dropdown menus are quite possible in Internet Explorer too.
So, to get started, let's say we're dealing with a list structure with more levels like this:
<ul id="nav"> <li><a href="#">Percoidei</a> <ul> <li><a href="#">Remoras</a> <ul> <li><a href="#">Echeneis</a></li> <li><a href="#">Phtheirichthys</a></li> <li><a href="#">Remora</a></li> <li><a href="#">Remorina</a></li> <li><a href="#">Rhombochirus</a></li> </ul> </li> <li><a href="#">Tilefishes</a></li> <li><a href="#">Bluefishes</a></li> <li><a href="#">Tigerfishes</a></li> </ul> </li> <li><a href="#">Anabantoidei</a> <!-- etc. --> </li> <!-- etc. --> </ul>
There are a few things we need to add to the single-level method. Firstly, the third-level list (in this example 'Echeneis, 'Phtheirichthys' etc.) needs to drop down to the side of the corresponding list item (in this case 'Remoras'), so we need to add this rule, which will apply to all dropdowns after the first one:
#nav li ul ul {
margin: -1em 0 0 10em;
}
Because we can't explicitly specify the top of the absolutely positioned boxes, they will sit below the line of the hovered list item, which is why the top margin of the next level of lists needs to be set to -1em. But this won't pull the menus up far enough the be in line with the corresponding list item because by default line heights are greater than 1em (usually 1.2em), so we need to add a little something to the initial ul rule set:
#nav, #nav ul {
padding: 0;
margin: 0;
list-style: none;
line-height: 1;
}
Due to the cascading effect whereby upon the second level list being displayed, the third level list would also be revealed, we also need to explicitly hide that third level list (remember that we need to duplicate the :hover pseudo class with the .sfhover class):
#nav li:hover ul ul, #nav li.sfhover ul ul {
left: -999em;
}
Now, this rule can be contradicted so that it is displayed when the corresponding list item is hovered over by expanding on the displaying of the dropdown (which with the single level dropdown was #nav li:hover ul, #nav li.sfhover ul { left: auto; }):
#nav li:hover ul, #nav li li:hover ul, #nav li.sfhover ul, #nav li li.sfhover ul {
left: auto;
}
And that will establish a solid two level dropdown menu.
Following the same logic you can accommodate as many levels of dropdown menus as you want:
For three levels of dropdowns:
#nav li:hover ul ul, #nav li:hover ul ul ul, #nav li.sfhover ul ul, #nav li.sfhover ul ul ul {
left: -999em;
}
#nav li:hover ul, #nav li li:hover ul, #nav li li li:hover ul, #nav li.sfhover ul, #nav li li.sfhover ul, #nav li li li.sfhover ul {
left: auto;
}
And in the crazy event you need four levels:
#nav li:hover ul ul, #nav li:hover ul ul ul, #nav li:hover ul ul ul ul, #nav li.sfhover ul ul, #nav li.sfhover ul ul ul, #nav li.sfhover ul ul ul ul {
left: -999em;
}
#nav li:hover ul, #nav li li:hover ul, #nav li li li:hover ul, #nav li li li li:hover ul, #nav li.sfhover ul, #nav li li.sfhover ul, #nav li li li.sfhover ul, #nav li li li li.sfhover ul {
left: auto;
}
Examples
So you might have already looked at the one level, two level and three level bare-bones examples, which are probably the best places to take a look at the uncluttered source code in action, but, of course, you can make things look a bit prettier. You could even turn it into a vertical menu rather than a horizontal one.
© Patrick Griffiths, 2003-2007.
Das JavaScript einbauen
Horizontales Flyout Menü nach Marlies Cohen
Läßt sich relativ gut anpassen und ist deshalb oft besser geeignet als das TLayer Menü von Typo3
HTML-Code
- Im Header Bereich der Seite sollte folgender Code stehen: -
-
- <!-- Multimenu js needed for it to work start-->
- <script type="text/javascript" >
- function init(){
- activateMenu('nav');
- activateMenu('vertnav');
- }
- </script>
-
- <script src="/fileadmin/examples/multimenu.js"
- type="text/javascript">
- </script>
- <!-- Multimenu js end -->
-
- - Mit Automaketemplate einfach ins Template schreiben. Klassisch z.B. mit -
-
- ### Header-Data ###
- # Todo-> auslagern
- page.headerData{
- 90 = COA
- 90{
- #wrap = |
- 50 = TEXT
- 50.value (
- <!-- Multimenu js needed for it to work start-->
- <script type="text/javascript" >
- function init(){
- activateMenu('nav');
- activateMenu('vertnav');
- }
- </script>
-
- <script src="/fileadmin/examples/multimenu.js"
- type="text/javascripts">
- </script>
- <!-- Multimenu js end -->
-
- )
- }
- }
-
- - === CSS === - Wieder im Headerbereich wird das Stylesheet verlinkt: - - <style type="text/css" media="all"> - @import "/fileadmin/mcu05_all.css"; - </style> - - So sieht das CSS aus: -
-
- /* List TopNav Multimenu start*/
-
- /* Colors used:
- bottom border mainmenu div and
- partial border around horizontal links buttons and
- #AFB6D0 = light blue grey
-
- bottom border of dropdown
- #707586 = dark blue grey
-
- background of horizontal links buttons
- #888C99 = medium blue grey
-
- background of hover and selected horizontal links buttons
- #d6ecb9 = light green
-
- partial border around horizontal links buttons and
- font color of selected horizontal links
- #333333 = dark grey
-
- level 1 & 2 dropdown background color
- #e6f0d2 = lighter light green
-
- level 1 & 2 dropdown link color
- #364061 = medium blue
-
- Level 1 dropdown hover and selected link color
- #ff6600 = orange
-
- level 1 & 2 dropdown background color
- #BFE699 darker light green
-
- level 2 dropdown hover & selected background color
- #dadde9 = lighter light blue
-
- */
-
-
- div#mainmenu {
- /* needed to give a margin above and below the buttons */
- height: 3em;
- border-bottom: 3px solid #AFB6D0;
- }
-
-
- .mainmenu {
- }
- #nav {
- list-style: none;
- position: relative;
- width: 750px !important;
- width: 700px;
- margin: 0px 30px 0px 0px !important;
- margin: 0px 0px 0px 20px;
- font-size: 1em;
- }
-
-
- #nav ul {
- list-style: none;
- display: none;
- position: absolute;
- overflow: visible;
- border-bottom: 3px solid #707586;
- }
-
-
- #nav li {
- display: block;
- width: 90px;
- position: relative;
- margin: 7px 3px 2px 3px !important;
- margin: 5px 2px 0px 2px;
- padding-bottom: 4px !important;
- padding: 0;
- float: left;
- }
- #nav li a {
- display: block;
- background-color: #888C99;
- color: #D6EFB5;
- font-weight: bold;
- text-decoration: none;
- border: solid 2px;
- border-color: #AFB6D0 #333333 #333333 #AFB6D0;
- }
- #nav li a:hover {
- background-color: #d6ecb9;
- color: #333333;
- border: solid 2px;
- border-color: #333333 #AFB6D0 #AFB6D0 #333333;
- }
- #nav li.sel A {
- background-color: #d6ecb9;
- color: #333333;
- }
- #nav li.sel A:hover {
- background-color: #d6ecb9;
- color: #ff6600;
- }
-
-
- /* 1st dropdown level */
- #level1 {
- display: block;
- left: -39px;
- }
- #level1 UL {
- position: absolute;
- overflow: visible;
- border-bottom: 3px solid #707586;
- }
- #level1 li {
- display: block;
- margin: 0 !important;
- margin: 0;
- padding: -0 0 !important;
- font-size: 1em;
- }
- #level1 li A {
- display: block;
- width: 150px;
- background: #e6f0d2;
- padding: 1px 3px;
- font-weight: normal;
- text-align: left;
- text-decoration: none;
- color: #364061;
- margin: 0;
- border: 0;
- }
- #level1 li A:hover {
- display: block;
- color: #ff6600;
- background-color: #BFE699;
- border: 0;
- }
- #level1 li.sel A {
- background-color: #BFE699;
- color: #364061;
- }
- #level1 li.sel A:hover {
- background-color: #BFE699;
- color: #ff6600;
- }
-
-
- /* 2nd dropdown level */
- #level2 {
- display: block;
- left: 116px !important;
- left: 110px;
- top: 0; !important;
- }
- #level2 UL {
- display: block;
- position: relative;
- overflow: visible;
- }
- #level2 LI {
- display: block;
- }
- #level2 li A {
- display: block;
- background: #afb6d0;
- }
- #level2 li A:hover {
- display: block;
- background: #dadde9;
- }
- #level2 li.sel A {
- background-color: #dadde9;
- color: #364061;
- }
- #level2 li.sel A:hover {
- background-color: #dadde9;
- color: #ff6600;
- }
-
-
- /* all see this */
- #nav ul ul, #nav ul ul ul {
- display: none;
- position: absolute;
- width: 150px;
- top: 0;
- }
- /* non-IE bowsers see this */
- #nav ul li>ul, #nav ul ul li>ul {
- margin-top: 0;
- }
- #nav LI:hover UL UL, #nav LI:hover UL UL UL{
- display: none;
- }
- #nav LI:hover UL {
- display: block;
- }
- #nav li:hover ul, #nav ul li:hover ul, #nav ul ul li:hover ul {
- display: block;
- }
- li>ul {
- top: auto:
- }
- UNKNOWN {
- margin-top: 0;
- left: auto;
- top: auto;
- }
-
- /* List TopNav Multimenu end*/
-
- - ==== CSShover.htc For IE ==== - - For the hover function to work in IE I had to add this line of code to the body tag of the main stylesheet. -
-
- body {
- /* This path has to be correct! If nothing hovers in IE,
- this is probably not found */
- behavior:url("fileadmin/csshover.htc");
- }
-
- - - - - === html template to activate the menu === -
-
- - === JavaScript ===
-
- activateMenu = function(nav) {
- /* currentStyle restricts the Javascript to IE only */
- if (document.all && document.getElementById(nav).currentStyle) {
- var navroot = document.getElementById(nav);
- /* Get all the list items within the menu */
- var lis=navroot.getElementsByTagName("LI");
- for (i=0; i<lis.length; i++) {
- /* If the LI has another menu level */
- if(lis[i].lastChild.tagName=="UL"){
- /* assign the function to the LI */
- lis[i].onmouseover=function() {
- /* display the inner menu */
- this.lastChild.style.display="block";
- }
- lis[i].onmouseout=function() {
- this.lastChild.style.display="none";
- }
- }
- }
- }
- }
- /* I do this differently on the test page to fix a problem float container problem in IE5 Mac*/
- /*Uncomment the function below*/
- /* <-- delete this whole line.
- window.onload= function(){
-
- activateMenu('nav'); //you only need one of these for each menu
- activateMenu('vertnav');
- }
- delete this whole line.--> */
-
- - === TypoScript === - - # Body Tag - page.bodyTag = <body onload="init();"> -
-
- # Top Navigation
- temp.mainmenu = HMENU
- temp.mainmenu.special = directory
- temp.mainmenu.special.value = 45
- temp.mainmenu.1 = TMENU
- temp.mainmenu.1 {
- expAll = 1
- NO.ATagTitle.field = title
- wrap = <UL id=nav> | </UL>
- NO.wrapItemAndSub = <LI> | </LI>
- ACT = 1
- ACT.wrapItemAndSub = <LI class=sel> | </LI>
- ACT.ATagTitle.field = title
- }
-
- temp.mainmenu.2 = TMENU
- temp.mainmenu.2 {
- expAll = 1
- NO.ATagTitle.field = title
- wrap = <UL id=level1> | </UL>
- NO.wrapItemAndSub = <LI> | </LI>
- ACT = 1
- ACT.wrapItemAndSub = <LI class=sel> | </LI>
- ACT.ATagTitle.field = title
- }
-
- temp.mainmenu.3 = TMENU
- temp.mainmenu.3 {
- expAll = 1
- NO.ATagTitle.field = title
- wrap = <UL id=level2> | </UL>
- NO.wrapItemAndSub = <LI> | </LI>
- ACT = 1
- ACT.wrapItemAndSub = <LI class=sel> | </LI>
- ACT.ATagTitle.field = title
- }
-
- - ==== Activate the navigation in the TYPO3 template ==== - subparts.hzmenu < temp.hzmenu