Menu with sub and subsub where subsub is shown at the same time as sub

hello there!

I am trying to build a menu with three levels, but the second level is like a ‘fake’ level because it won’t have any content, it shall just be for the organization. I am not a good (or even) a programmer but I try my best.

this is a screenshot of the menu how it should look like:
oi60. tinypic. com/ 3013wao. jpg

‘Projekte’ is level 1 in the menu
’Film’, ‘Fotografie’ and ‘Unterwegs’ are level 2
’Dokumentation’, ‘Musikvideo’, ‘Imagefilm’ and so on are level 3 and the first three ones are a child from ‘Film’ (I guess the layout explains it good)

my problem is, that I do not understand how to show level 2 and level 3 at the same time. I tried the treemenu and nested menu from the kirby wiki but I was not able to make it work.

this is my html/php:

<?php

// main menu items
$items = $pages->visible();

// only show the menu if items are available
if($items->count()):

?>
	<nav>
		<ul>
			<?php foreach($items as $item): ?>
				<li>
					<a<?php e($item->isOpen(), ' class="active"') ?> href="<?php echo $item->url() ?>">
						<?php echo $item->title()->html() ?>
					</a>
				</li>
			<?php endforeach ?>
		</ul>
	</nav>
<?php endif ?>


<?php

$items = false;

// get the open item on the first level
if($root = $pages->findOpen()) {

// get visible children for the root item
$items = $root->children()->visible();
}

// only show the menu if items are available
if($items and $items->count()):

?>

	<nav class="submenu">
		<ul>
			
			<?php foreach($items as $item): ?>
									
				<li>
											
					<a<?php e($item->isOpen(), ' class="active"') ?> href="<?php echo $item->url() ?>">
						<?php echo $item->title()->html() ?>
					</a>
									
				</li>
				
			<?php endforeach ?>
							
		</ul>
	</nav>
<?php endif ?>

<?php

// independent sub sub menu
$items = false;

// get the open item on the first level
if($root1 = $pages->findOpen()) {

// get the open item on the second level
if($root2 = $root1->children()->findOpen()) {

// get visible children of the second level item
$items = $root2->children()->visible();
}
}

// only show the menu if items are available
if($items and $items->count()):

?>

	<nav class="subsubmenu">
		<ul>
			<?php foreach($items as $item): ?>
				<li>
					<a<?php e($item->isOpen(), ' class="active"') ?> href="<?php echo $item->url() ?>">
						<?php echo $item->title()->html() ?>
					</a>
				</li>
			<?php endforeach ?>
		</ul>
	</nav>
<?php endif ?>

this is my css:

        .menuleiste			{   position: absolute;
						width: 400px;
						height: 50px;
						left: 50%;
						top: 20px; 
						margin-left: -185px; 
						padding-left: 15px;
						background-color: #C2C2CE;
						text-align: left; }

.menuleiste li		{   display: inline;
	 					margin-right: 50px; }
						
.menuleiste li a 	{ 	text-decoration: none; 
						font-family: TradeGothicLTPro;
						font-size: 20px;
						color: white; }	
						
.submenu			{   position: relative;
						top: -45px; 
						left: -15px;
						background-color: yellow;
						padding-top: 70px;
						padding-left: 15px;
						margin-right: -15px;
						padding-bottom: 1px;
						z-index: -1;}					

.submenu li			{   display: block;
	 					margin-right: 50px; 
						margin-bottom: 15px;}

.submenu li a 		{ 	text-decoration: none; 
						font-family: TradeGothicLTPro;
						font-size: 16px;
						color: red; }	
						
.subsubmenu			{   position: inherit;
						top: 50px; 
						left: 142px;}
						
.subsubmenu li		{ 	display: block; }

.subsubmenu li a 	{ 	text-decoration: none; 
						font-family: TradeGothicLTPro;
						font-size: 16px;
						color: blue; }

I know a real programmer will get eyecancer because of my code but yeha, I am trying my best.

can anyhone help me with my problem?

any help would be much appreciated, thank you!

How are you structuring your content folder?

Probably like this?

content/
   projects/
      01-film/
         01-dokumentation/
         02-musikvideo/
         03-imagefilm/
     02-fotografie/
         01-portrait/
         02-dokumentation/
     03-unterwegs/    

There’s a lot going on in your code, so I’m not sure what your exact intentions are, but this should work on a basic level:

<div id="menu">
<?php foreach ($pages->find('work')->children()->visible() as $section): ?>
	<div class="work-section">
		<div class="section-title">
			<h3><?= $section->title() ?></h3>
		</div>
		<div class="section-projects">
			<?php foreach ($section->children()->visible() as $project): ?>
			<h3><a href="<?= $project->url() ?>"><?= $project->title() ?></a></h3>
			<?php endforeach ?>
		</div>
	</div>
<?php endforeach ?>
</div>

CSS: (untested but should be close)

#menu {
	width:50rem;
	background-color:red;
	padding:4rem;
}

.work-section {
	width:100%;
}
.section-title {
	width:30%;
	display:inline-block;
}
.section-projects {
	width:70%;
	display:inline-block;
}

thank you very much!
I tried that and played around with your code as a basis but it did not work either.
so I managed it right now with a ‘static’ menu, sadly it will not be customizable after the website will be online.

Provided that the above structure is correct, this should work (at least if I haven’t forgotten to close any tags etc.):

<?php
  //get the projects page on first level
  $page = page('projects');
?>
<nav>
  //show headline of project page
  <h3><a href="<?php echo $page->url()"><?= $page->title() ?></a></h3>
   // check if page has children (third level)
   <?php if($page->hasChildren() : ?>
    <ul>
    //fetch the children of the second level (fake menu, i.e. no clickable links)
    <?php foreach ($page->children()->visible() as $child): ?>
	<li><?php echo $child->title() ?></li>
          // check if child has children (third level)
           <?php if($child->hasChildren() : ?>
             <ul>
              //fetch all third level children and link to them
              <?php foreach($child->children()->visible() as $grandChild) : ?>
                <li><a href="<?php echo $grandChild->url() ?>"><?php echo $grandChild->title() ?></a></li>
              <?php endforeach ?>
            </ul>
           <?php endif ?>
     <?php endforeach ?>
    </ul>
 <?php endif ?>
</nav>

Hi @texnixe

I would need a main/sub/subsub structure as well on my page. Where do I have to place the code you’ve provided?

Best regards
sj7

I would put the menu in a snippet that you can reference wherever you need it, header, sidebar …

Note that this snippet only gets subpages of the projects’ page.

@saljut7:

You can add a new file “/site/snippets/treemenu.php” which can look like the code from the part “Tree menu” at https://getkirby.com/docs/cookbook/menus#tree-menu, which shows all visible pages of your website.

At the place you want to see the main menu (e.g. in the file “/site/snippets/header.php”), you add:

<nav class="mainmenu">
<?php snippet('treemenu'); ?>
</nav>

Now you should add some css in your css-file, but that is your job, because we don’t know your wanted design. And add needed parts in the code of the rendered page like or insite of class=" ... " in this code!

Good luck!

1 Like

Thanks a lot. “sub sub menu” was what I was looking for.

Tutorial for users like me:

  1. Create site/snippets/subsubmenu.php with following content:
<?php

// independent sub sub menu
$items = false;

// get the open item on the first level
if($root1 = $pages->findOpen()) {

  // get the open item on the second level
  if($root2 = $root1->children()->findOpen()) {

    // get visible children of the second level item
    $items = $root2->children()->visible();
  }
}

// only show the menu if items are available
if($items and $items->count()):

?>
<nav>
  <ul>
    <?php foreach($items as $item): ?>
    <li><a<?php e($item->isOpen(), ' class="active"') ?> href="<?php echo $item->url() ?>"><?php echo $item->title()->html() ?></a></li>
    <?php endforeach ?>
  </ul>
</nav>
<?php endif ?>
  1. In site/templates/default-php exchange:
<?php snippet('header') ?>
<?php snippet('menu') ?>
<?php snippet('submenu') ?>

with:

<?php snippet('header') ?>
<?php snippet('menu') ?>
<?php snippet('submenu') ?>
<?php snippet('subsubmenu') ?>
  1. In assets/styles/styles.css exchange:
nav.submenu {
  border-top: none;
  margin-bottom: 20px;
}
nav.submenu a {
  font-weight: normal;
}

with:

nav.submenu {
  border-top: none;
  margin-bottom: 20px;
}
nav.submenu a {
  font-weight: normal;
}
nav.subsubmenu {
  border-top: none;
  margin-bottom: 20px;
}
nav.subsubmenu a {
  font-weight: normal;
}
1 Like

Another question:

at the moment sub sub menu looks like this in my case:

-----
menu
-----
sub menu
-----
-----
sub sub menu
-----

How can I remove the double line so that it will look like this:

-----
menu
-----
sub menu
-----
sub sub menu
-----

?

What is that, borders? Than you have to modify your CSS. Use dev tools to inspect the code.

Sorry, forgot to enable notifications. Thanks for your reply.

Yes, borders. Maybe a picture is better to explain the problem:

Just to confirm: I’m using standard kirby template.

I would like that all nav bar is separated by its own frames on top and button or just one single line between each nav bar:

So either:

-----
menu
-----
-----
sub
-----
-----
subsub
-----

…or:

-----
menu
-----
sub
-----
subsub
-----

and not like now a mix of it:

-----
menu
-----
sub
-----
-----
subsub
-----

Are these lines defined in assets/styles/styles.css as well? I couldn’t find it.

Yes, this is a CSS issue. As @texnixe wrote above, you can use your browser’s dev tools to inspect the elements. You can then find out which CSS rule is responsible.

If the site is live and you tell us the URL we can check for you, but please note that CSS issues are normally not inside the scope of Kirby support.

I tried this (with Firefox/Tools/Web Developer/Inspector)
but I can not find the part which is generating the line. My css:

* {
  margin: 0px;
  padding: 0px;
}
html {
  height: 101%;
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
}
body {
  font-family: Helvetica, Arial, sans-serif;
  font-size: 16px;
  text-align:justify;
  line-height: 26px;
  background: #fff;
  color: #777;
  width: 700px;
  margin: 50px auto;
}
a {
  color: #222;
  text-decoration: none;
}
a,
a:hover,
a:active,
a:visited {
  outline: 0px;
}
a:hover {
  color: #777;
}
a.grey {
  color: #777;
  text-decoration: none;
}
a.grey,
a.grey:hover,
a.grey:active,
a.greya:visited {
  outline: 0px;
}
a.grey:hover {
  color: #222;
}
img {
  outline: 0;
  border: 0;
}
h1 {
  font-size: 28px;
  line-height: 40px;
  color: #222;
  margin-bottom: 20px;
}
h2 {
  font-size: 28px;
  font-weight: normal;
  color: #222;
  margin-bottom: 21px;
}
h3 {
  font-weight: normal;
  font-size: 20px;
  color: #222;
  margin-bottom: 21px;
}
h4 {
  color: #222;
  font-weight: normal;
}
p {
  margin-bottom: 20px;
}
nav {
  overflow: hidden;
  border-top: 1px solid black;
  border-bottom: 1px solid black;
  padding: 10px 0;
}
nav li {
  list-style: none;
  margin-right: 20px;
  font-weight: bold;
  float: left;
}
nav li a.active {
  color: #777;
}
nav.submenu {
  border-top: none;
  margin-bottom: 20px;
}
nav.submenu a {
  font-weight: normal;
}
nav.subsubmenu {
  border-top: none;
  margin-bottom: 20px;
}
nav.subsubmenu a {
  font-weight: normal;
}
nav.subsubsubmenu {
  border-top: none;
  margin-bottom: 20px;
}
nav.subsubsubmenu a {
  font-weight: normal;
}
section.content {
  margin-top: 40px;
}
footer {
  padding-top: 20px;
  margin-top: 20px;
  border-top: 1px solid black;
  font-size: 13px;
  color: #222;
}
footer a {
  color: #222;
}
footer a:hover {
  color: #777;
}

It is https://jahr1nachsnowden.de/initiativen/nachfolgeinitiativen/gnuni-linux.

Thank you for very much. I already wrote Bastian via mail to enable subsub[…]sub menus as a default feature so I hope my request is helping to improve the whole CMS.

If you add the following rule at the end of the file it should work:

nav.submenu {
  border-bottom: none;
  margin-bottom: 0;
}

Thank you for the idea, but unfortunately this isn’t really something that can become a Kirby feature. The CMS itself already supports it (so that you were able to integrate it into your site) and the Kirby starterkit has been completely improved since. The starterkit is also just an example, it can’t use every Kirby feature.

1 Like

Works perfect, thank you so much!

Maybe I mixed Kirby CMS with Kirby starter kit. For me this was the same (until now).

So if I need another navigation bar (“subsub_sub_” as 3rd level) I need a php developer if I’m not a programmer?

I tried to do the same as for sub_sub_menu and added in addition to site/snippets/subsubmenu.php a site/snippets/subsubsubmenu.php.

Without knowing what I’m doing I tried to upgrade subsubsubmenu.php from:

<?php

// independent sub sub menu
$items = false;

// get the open item on the first level
if($root1 = $pages->findOpen()) {

  // get the open item on the second level
  if($root2 = $root1->children()->findOpen()) {

    // get visible children of the second level item
    $items = $root2->children()->visible();
  }
}

// only show the menu if items are available
if($items and $items->count()):

?>
<nav>
  <ul>
    <?php foreach($items as $item): ?>
    <li><a<?php e($item->isOpen(), ' class="active"') ?> href="<?php echo $item->url() ?>"><?php echo $item->title()->html() ?></a></li>
    <?php endforeach ?>
  </ul>
</nav>
<?php endif ?>

to:

<?php

// independent sub sub sub menu
$items = false;

// get the open item on the first level
if($root1 = $pages->findOpen()) {

  // get the open item on the second level
  if($root2 = $root1->children()->findOpen()) {

    // get the open item of the third level item
    if($root3 = $root2->children()->findOpen()) {
    
      // get visible children of the third level item
      $items = $root3->children()->visible();
  }
}

// only show the menu if items are available
if($items and $items->count()):

?>
<nav>
  <ul>
    <?php foreach($items as $item): ?>
    <li><a<?php e($item->isOpen(), ' class="active"') ?> href="<?php echo $item->url() ?>"><?php echo $item->title()->html() ?></a></li>
    <?php endforeach ?>
  </ul>
</nav>
<?php endif ?>

…which unfortunately doesn’t work and ends up with breaking the whole page. If I did just a simple mistake I would be thankful for a explanation how to upgrade “subsub” to “subsubsub”. I would add a step by step tutorial for ppl like me here then. :wink:

Yes. Kirby is just providing the framework and the tools you need to build a site. It isn’t a site on its own.
You can see what developers have created with Kirby in our showcase.

Hmmm, do you really need three or even more navigation levels? Maybe there is a better way to get at the information in the deeper navigation levels.

Hmmm, do you really need three or even more navigation levels? Maybe there is a better way to get at the information in the deeper navigation levels.
[/quote]

I’m very open for any other solutions. I’ve chosen Kirby to set up a project page for a student project/movement in just one day.

So the initial page was just about one project and menu with sub menu was enough to get an intuitive structure.

Now I started another student project as a child project of the first. So I need a sub-sub menu to display the menu structure as:

projects
initial project | child projects
child project 1

For child project 1 I’m listing all content in just one page at the moment but this way there is too much information in one page because I have to list “short description”, “long description”, “support us”, “petition text”, “contact” and more (https://jahr1nachsnowden.de/initiativen/nachfolgeinitiativen/gnuhu-linux).

Using a of sub/sub/sub menu is very intuitiv in my opinion because you always know where you currently are on the page.

But as I said I’m very open to other structure methods: how do you would structure this?