:checked
hackTo open the submenus we’ll use checkboxes. If you don’t know how the checkbox hack works, just google it, there are some really good posts that go into much detail. But basically we will depend the visibility of the submenu on the state of the checkbox placed before it.
So we change our markup to look like this:
1 <div class="menu">2 <ul class="nav level-one">3 <li>4 <a href="#">Item 1</a>5 </li>6 <li class="parent">7 <a href="#">Item 2 </a>8 <label for="toggle-level-2-01" class="toggle">toggle submenu</label>9 <input type="checkbox" id="toggle-level-2-01"/>10 <ul class="level-two">11 <li>12 <a href="#">Child 1</a>13 </li>14 <li>15 <a href="#">Child 2</a>16 </li>17 <li class="parent">18 <a href="#">Child 3</a>19 <label for="toggle-level-3-01" class="toggle">toggle submenu</label>20 <input type="checkbox" id="toggle-level-3-01"/>21 <ul class="level-three">22 <li>23 <a href="#">Grandchild 1</a>24 </li>25 <li class="parent">26 <a href="#">Grandchild 2</a>27 <label for="toggle-level-4-01" class="toggle">toggle submenu</label>28 <input type="checkbox" id="toggle-level-4-01"/>29 <ul class="level-four">30 <li>31 <a href="#">Grandgrandchild 1</a>32 </li>33 <li>34 <a href="#">Grandgrandchild 2</a>35 </li>36 <li>37 <a href="#">Grandgrandchild 3</a>38 </li>39 </ul>40 </li>41 </ul>42 </li>43 </ul>44 </li>45 <li class="parent">46 <a href="#">Item 3</a>47 <label for="toggle-level-2-02" class="toggle">toggle submenu</label>48 <input type="checkbox" id="toggle-level-2-02"/>49 <ul class="level-two">50 <li>51 <a href="#">Child 1</a>52 </li>53 <li>54 <a href="#">Child 2</a>55 </li>56 <li class="parent">57 <a href="#">Child 3</a>58 <label for="toggle-level-3-02" class="toggle">toggle submenu</label>59 <input type="checkbox" id="toggle-level-3-02"/>60 <ul class="level-three">61 <li>62 <a href="#">Grandchild 1</a>63 </li>64 <li>65 <a href="#">Grandchild 2</a>66 </li>67 <li>68 <a href="#">Grandchild 3</a>69 </li>70 </ul>71 </li>72 <li>73 <a href="#">Child 4</a>74 </li>75 </ul>76 </li>77 <li>78 <a href="#">Item 4</a>79 </li>80 <li>81 <a href="#">Item 5</a>82 </li>83 <li>84 <a href="#">Item 6</a>85 </li>86 </ul>87 </div>
The opening will be done using this CSS
1 .menu ul > li ul {2 display: none;3 }4 .menu ul > li input[type="checkbox"]:checked + ul {5 display: block;6 }
Now we’ll just have to style it. I went with a pretty standard bar.
1 .menu {2 font-size: 16px;3 font-family: Roboto Slab, serif;4 background-color: #C06574;5 color: white;6 position: fixed;7 top: 0;8 left: 0;9 width: 100%;10 padding: 10px 0;11 z-index: 10;12 }13 .menu input[type="checkbox"] {14 opacity: 0;15 position: absolute;16 left: -9999px;17 }18 .menu a {19 color: white;20 text-decoration: none;21 -webkit-transition: .3s all ease;22 transition: .3s all ease;23 }24 .menu a:hover {25 color: #E3DFE6;26 }27 .menu label.toggle {28 color: transparent;29 position: relative;30 }31 .menu label.toggle:hover {32 cursor: pointer;33 }34 .menu label.toggle:hover:before {35 width: 0;36 height: 0;37 border-style: solid;38 border-color: transparent transparent transparent #E3DFE6;39 border-width: 5.33333px;40 }41 .menu label.toggle:before {42 content: "";43 font-size: 16px;44 -webkit-transition: .3s all ease;45 transition: .3s all ease;46 position: absolute;47 top: 50%;48 left: 5px;49 -webkit-transform: translateY(0%) rotate(90deg);50 transform: translateY(0%) rotate(90deg);51 width: 0;52 height: 0;53 border-style: solid;54 border-color: transparent transparent transparent white;55 border-width: 5.33333px;56 }57 .menu ul {58 position: relative;59 }60 .menu ul,61 .menu ul li {62 list-style: none;63 padding: 0;64 margin: 0;65 }66 .menu ul > li {67 display: inline;68 padding: 0 10px;69 position: relative;70 }71 .menu ul > li > ul {72 position: absolute;73 top: calc(100% + 10px);74 left: 0;75 background: #C06574;76 display: none;77 }78 .menu ul > li > ul > li {79 display: block;80 white-space: nowrap;81 }82 .menu ul > li > ul > li label.toggle:before {83 -webkit-transform: translateY(-50%);84 transform: translateY(-50%);85 }86 .menu ul > li > ul ul {87 left: 100%;88 top: 0;89 }90 .menu ul > li input[type="checkbox"]:checked + ul {91 display: block;92 }
And that will look like this:
See the Pen Checkbox-Hack Dropdown (non-responsive) by Myri ( @mynimi) on CodePen.
For the responsive version we’ll have to adjust some more of the markup. We add another checkbox to toggle the whole navigation. And then we just adjust the CSS to create this off-canvas Menu
And that’s what it looks like:
1 <div class="menu">2 <label for="toggle-responsive" class="toggle-menu">Menu</label>3 <input type="checkbox" id="toggle-responsive"/>4 <ul class="nav level-one">5 <li><a href="#">Item 1</a></li>6 <li class="parent"><a href="#">Item 2 </a>7 <label for="toggle-level-2-01" class="toggle">o</label>8 <input type="checkbox" id="toggle-level-2-01"/>9 <ul class="level-two">10 <li><a href="#">Child 1</a></li>11 <li><a href="#">Child 2</a></li>12 <li class="parent"><a href="#">Child 3</a>13 <label for="toggle-level-3-01" class="toggle">o</label>14 <input type="checkbox" id="toggle-level-3-01"/>15 <ul class="level-three">16 <li><a href="#">Grandchild 1</a></li>17 <li class="parent"><a href="#">Grandchild 2</a>18 <label for="toggle-level-4-01" class="toggle">o</label>19 <input type="checkbox" id="toggle-level-4-01"/>20 <ul class="level-four">21 <li><a href="#">Grandgrandchild 1</a></li>22 <li><a href="#">Grandgrandchild 2</a></li>23 <li><a href="#">Grandgrandchild 3</a></li>24 </ul>25 </li>26 </ul>27 </li>28 </ul>29 </li>30 <li class="parent"><a href="#">Item 3</a>31 <label for="toggle-level-2-02" class="toggle">o</label>32 <input type="checkbox" id="toggle-level-2-02"/>33 <ul class="level-two">34 <li><a href="#">Child 1</a></li>35 <li><a href="#">Child 2</a></li>36 <li class="parent"><a href="#">Child 3</a>37 <label for="toggle-level-3-02" class="toggle">o</label>38 <input type="checkbox" id="toggle-level-3-02"/>39 <ul class="level-three">40 <li><a href="#">Grandchild 1</a></li>41 <li><a href="#">Grandchild 2</a></li>42 <li><a href="#">Grandchild 3</a></li>43 </ul>44 </li>45 <li><a href="#">Child 4</a></li>46 </ul>47 </li>48 <li><a href="#">Item 4</a></li>49 <li><a href="#">Item 5</a></li>50 <li><a href="#">Item 6</a></li>51 </ul>52 </div>
In the example I put the breakpoint at 2000px so that it shows up on all stanard displays. In real life you would have to adjust this, so that the non-responsive version will be shown first.
1 .menu {2 font-size: 16px;3 font-family: Roboto Slab, serif;4 background-color: #C06574;5 color: white;6 position: fixed;7 top: 0;8 left: 0;9 width: 100%;10 padding: 10px 0;11 z-index: 10;12 }13 .menu input[type="checkbox"] {14 opacity: 0;15 position: absolute;16 left: -9999px;17 }18 .menu a, .menu .toggle-menu {19 color: white;20 text-decoration: none;21 -webkit-transition: .3s all ease;22 transition: .3s all ease;23 }24 .menu a:hover, .menu .toggle-menu:hover {25 color: #E3DFE6;26 }27 .menu .toggle-menu {28 display: none;29 padding-left: 10px;30 }31 .menu .toggle-menu:hover {32 cursor: pointer;33 }34 @media screen and (max-width: 2000px) {35 .menu .toggle-menu {36 display: block;37 }38 }39 @media screen and (max-width: 2000px) {40 .menu .nav {41 background: #b95364;42 position: fixed;43 height: 100%;44 width: 320px;45 top: 41px;46 left: 0;47 -webkit-transition: .3s all ease;48 transition: .3s all ease;49 -webkit-transform: translateX(-320px);50 transform: translateX(-320px);51 overflow-y: auto;52 font-size: 18px;53 }54 .menu #toggle-responsive:checked ~ .nav {55 -webkit-transform: translateX(0);56 transform: translateX(0);57 }58 }59 .menu label.toggle {60 color: transparent;61 position: relative;62 }63 .menu label.toggle:hover {64 cursor: pointer;65 }66 .menu label.toggle:hover:before {67 width: 0;68 height: 0;69 border-style: solid;70 border-color: transparent transparent transparent #E3DFE6;71 border-width: 5.33333px;72 }73 .menu label.toggle:before {74 content: "";75 font-size: 16px;76 -webkit-transition: .3s all ease;77 transition: .3s all ease;78 position: absolute;79 top: 50%;80 left: 5px;81 -webkit-transform: translateY(0%) rotate(90deg);82 transform: translateY(0%) rotate(90deg);83 width: 0;84 height: 0;85 border-style: solid;86 border-color: transparent transparent transparent white;87 border-width: 5.33333px;88 }89 @media screen and (max-width: 2000px) {90 .menu label.toggle:before {91 left: 15px;92 }93 }94 .menu ul {95 position: relative;96 }97 .menu ul,98 .menu ul li {99 list-style: none;100 padding: 0;101 margin: 0;102 }103 .menu ul > li {104 position: relative;105 padding: 10px;106 }107 @media screen and (min-width: 2001px) {108 .menu ul > li {109 display: inline;110 padding: 0 10px;111 }112 }113 .menu ul > li > ul {114 position: absolute;115 top: calc(100% + 10px);116 left: 0;117 background: #C06574;118 display: none;119 }120 @media screen and (max-width: 2000px) {121 .menu ul > li > ul {122 position: relative;123 left: -10px;124 background: rgba(0, 0, 0, 0.1);125 width: calc(100% + 20px);126 }127 }128 @media screen and (min-width: 2001px) {129 .menu ul > li > ul > li {130 display: block;131 white-space: nowrap;132 }133 .menu ul > li > ul > li label.toggle:before {134 -webkit-transform: translateY(-50%);135 transform: translateY(-50%);136 }137 .menu ul > li > ul ul {138 left: 100%;139 top: 0;140 }141 }142 .menu ul > li input[type="checkbox"]:checked + ul {143 display: block;144 }
See the Pen Checkbox-Hack Dropdown (responsive) by Myri ( @mynimi) on CodePen.
And that’s it.
This is the question. If you should actually go with a solution like this. Well, in case you have to solve this problem without JavaScript - Go with this. In Reallife, though, the javascript solution is the one I would go with. Reason for that being the fact, that it is written faster and all-over support is a little better. Still, I like trying to tackle some problems without the use of JavaScript, just to see how far you can come with just HTML and CSS.