Responsive menu in pure CSS
Having menus that gracefully adapt to the size of your screen can be troublesome. Inspired by the collapsible menu of Bootstrap, here is a pure CSS implementation using the checkbox trick to toggle visibility.
The example attached features a smaller menu when the screen is narrower than 900px and is collapsed then narrower than 650px. I encourage you to test whatever suits you best.
On collapse toggle, the height and visibility are animated for a smooth transition. height: auto; is not directly supported, so we instead animate the max-height property. The downside is that you need to specify the max-height your menu will ever have. If you set this too high, you will experience a slight graphic glitch.
The toggle handle is also inspired from Bootstrap, but with minimal markup.
* the :checked selector is not supported prior to IE9, you may use a polyfill like http://selectivizr.com/ if you need to.
Happy coding !
To test it, resize your browser.
1
2
3
4
5
6
7
8
9
10
11
12
13
<!-- responsive-menu.html -->
<input type="checkbox" id="navbar-checkbox" class="navbar-checkbox">
<nav class="menu">
<ul>
<li>Home</li>
<li>About us</li>
<li>Our company</li>
<li>Our team</li>
<li>Contact us</li>
</ul>
<label for="navbar-checkbox" class="navbar-handle"></label>
</nav>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
// responsive-menu.less
// Smaller menu when on small screen
// All padding and margin are in em, so they will scale as well
@media (min-width : 900px) {
.menu {
font-size: 1.2em;
}
}
.menu {
padding: 0.5em;
background: #eee;
min-height: 2em;
line-height: 1em;
ul {
transition: max-height .25s linear;
margin: 0;
padding: 0;
text-align: center;
}
li {
// visibility transition is on li because multiple transition selectors is not well supported
transition: visibility .25s linear;
display: inline-block;
border: 1px solid;
padding: .45em 1.1em;
margin: 0 .3em;
}
}
@media (max-width : 650px) {
.menu {
ul {
max-height: 0;
overflow: hidden;
margin: 0 3.5em 0 1em;
}
li {
visibility: hidden;
display: block;
padding: 0.5em 0.6em;
border: none;
}
.navbar-handle {
display: block;
}
}
#navbar-checkbox:checked + .menu {
ul {
max-height: 300px; // Set this to the maximum height your menu will ever have.
}
li {
visibility: visible;
}
.navbar-handle {
&, &:after, &:before {
border-color: #aaa;
}
}
}
}
.navbar-checkbox {
display: none;
}
// Will scale based on font-size
// Appears as 3 parallel horizontal bars
.navbar-handle {
@height: 45px; // just a reference to compute em values on the fly
display: none;
cursor: pointer;
position: relative;
font-size: @height;
padding: .5em 0;
height: 0;
width: 1em * 75px / @height;
border-top: (1em * 6px / @height) solid;
&:before, &:after {
position: absolute;
left: 0;
right: 0;
content: ' ';
border-top: (1em * 6px / @height) solid;
}
&:before {
top: 1em * 17px / @height;
}
&:after {
top: 1em * 40px / @height;
}
}
///////////
.menu {
position: absolute;
top: 0;
left: 0;
right: 0;
.navbar-handle {
position: absolute;
font-size: 1.2em;
top: 0.7em;
right: 12px;
z-index: 10;
}
}