{"componentChunkName":"component---src-templates-post-jsx","path":"/blog/the-perfect-responsive-menu/","result":{"data":{"mdx":{"body":"function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }\n\nfunction _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }\n\nfunction _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }\n\n/* @jsxRuntime classic */\n\n/* @jsx mdx */\nconst _frontmatter = {\n  \"title\": \"The perfect responsive menu (2021)\",\n  \"slug\": \"the perfect responsive menu\",\n  \"cover\": \"/blogs/perfectmenu/cover.svg\",\n  \"date\": \"2019-09-20\",\n  \"updated\": \"2021-05-30\",\n  \"type\": [\"tutorial\"]\n};\nconst layoutProps = {\n  _frontmatter\n};\nconst MDXLayout = \"wrapper\";\nreturn function MDXContent(_ref) {\n  let {\n    components\n  } = _ref,\n      props = _objectWithoutProperties(_ref, [\"components\"]);\n\n  return mdx(MDXLayout, _extends({}, layoutProps, props, {\n    components: components,\n    mdxType: \"MDXLayout\"\n  }), mdx(\"p\", null, `On a desktop, websites have the space to show the full menu or navbar. On a mobile device that space isn't there and you want to hide the menu behind a toggle (like a hamburger icon), then show it when people click that toggle. How do you offer both in an accessible way that keeps your HTML simple, without duplicating your menu? That's what the perfect responsive menu does.`), mdx(\"p\", null, mdx(\"em\", {\n    parentName: \"p\"\n  }, `Though the hamburger icon is well known by now, to better help people that are not familiar with it you can show the icon alongside the word \"Menu\".`)), mdx(\"p\", null, `In this article, we'll show you how to create a responsive menu that uses the same HTML on all viewports, is responsive and looks great. The perfect responsive menu.`), mdx(\"h2\", {\n    \"id\": \"the-html\"\n  }, `The HTML`), mdx(\"p\", null, `We start with the HTML.`), mdx(\"div\", {\n    \"className\": \"gatsby-highlight\",\n    \"data-language\": \"html\"\n  }, mdx(\"pre\", _extends({\n    parentName: \"div\"\n  }, {\n    \"className\": \"language-html\"\n  }), mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-html\"\n  }), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token tag\"\n  }), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token tag\"\n  }), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `<`), `nav`), ` `, mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token attr-name\"\n  }), `class`), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token attr-value\"\n  }), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation attr-equals\"\n  }), `=`), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `\"`), `navigation`, mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `\"`)), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `>`)), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token tag\"\n  }), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token tag\"\n  }), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `<`), `button`), ` `, mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token attr-name\"\n  }), `aria-expanded`), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token attr-value\"\n  }), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation attr-equals\"\n  }), `=`), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `\"`), `false`, mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `\"`)), ` `, mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token attr-name\"\n  }), `aria-controls`), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token attr-value\"\n  }), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation attr-equals\"\n  }), `=`), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `\"`), `menu`, mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `\"`)), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `>`)), `Menu`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token tag\"\n  }), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token tag\"\n  }), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `</`), `button`), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `>`)), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token tag\"\n  }), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token tag\"\n  }), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `<`), `ul`), ` `, mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token attr-name\"\n  }), `id`), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token attr-value\"\n  }), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation attr-equals\"\n  }), `=`), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `\"`), `menu`, mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `\"`)), ` `, mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token attr-name\"\n  }), `hidden`), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `>`)), `\n    `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token tag\"\n  }), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token tag\"\n  }), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `<`), `li`), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `>`)), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token tag\"\n  }), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token tag\"\n  }), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `<`), `a`), ` `, mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token attr-name\"\n  }), `href`), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token attr-value\"\n  }), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation attr-equals\"\n  }), `=`), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `\"`), `/`, mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `\"`)), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `>`)), `Home`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token tag\"\n  }), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token tag\"\n  }), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `</`), `a`), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `>`)), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token tag\"\n  }), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token tag\"\n  }), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `</`), `li`), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `>`)), `\n    `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token tag\"\n  }), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token tag\"\n  }), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `<`), `li`), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `>`)), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token tag\"\n  }), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token tag\"\n  }), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `<`), `a`), ` `, mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token attr-name\"\n  }), `href`), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token attr-value\"\n  }), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation attr-equals\"\n  }), `=`), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `\"`), `/benefits`, mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `\"`)), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `>`)), `Benefits`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token tag\"\n  }), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token tag\"\n  }), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `</`), `a`), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `>`)), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token tag\"\n  }), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token tag\"\n  }), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `</`), `li`), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `>`)), `\n    `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token tag\"\n  }), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token tag\"\n  }), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `<`), `li`), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `>`)), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token tag\"\n  }), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token tag\"\n  }), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `<`), `a`), ` `, mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token attr-name\"\n  }), `href`), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token attr-value\"\n  }), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation attr-equals\"\n  }), `=`), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `\"`), `/pricing`, mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `\"`)), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `>`)), `Pricing`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token tag\"\n  }), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token tag\"\n  }), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `</`), `a`), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `>`)), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token tag\"\n  }), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token tag\"\n  }), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `</`), `li`), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `>`)), `\n    `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token tag\"\n  }), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token tag\"\n  }), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `<`), `li`), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `>`)), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token tag\"\n  }), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token tag\"\n  }), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `<`), `a`), ` `, mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token attr-name\"\n  }), `href`), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token attr-value\"\n  }), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation attr-equals\"\n  }), `=`), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `\"`), `/blog`, mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `\"`)), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `>`)), `Blog`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token tag\"\n  }), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token tag\"\n  }), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `</`), `a`), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `>`)), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token tag\"\n  }), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token tag\"\n  }), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `</`), `li`), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `>`)), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token tag\"\n  }), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token tag\"\n  }), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `</`), `ul`), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `>`)), `\n`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token tag\"\n  }), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token tag\"\n  }), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `</`), `nav`), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `>`))))), mdx(\"p\", null, `The basic menu is as you've probably written before. It's a list of links (an `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `ul`), `) wrapped in a `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `nav`), ` element. But two things are different.`), mdx(\"p\", null, `First, there's an extra button. The button has some attributes you might not be familiar with: Aria attributes. With these attributes we can help assistive tools like screen readers know the purpose of the button. In this case, the button `, mdx(\"em\", {\n    parentName: \"p\"\n  }, `controls`), ` the element with id \"menu\", and it's currently not expanded.`), mdx(\"p\", null, `Second, the menu is initially hidden, using the `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `hidden`), ` attribute. We hide it initially because we develop `, mdx(\"a\", _extends({\n    parentName: \"p\"\n  }, {\n    \"href\": \"https://polypane.app/blog/responsive-design-ground-rules/\"\n  }), `mobile first`), `, and on mobile we only show the button.`), mdx(\"h2\", {\n    \"id\": \"the-javascript\"\n  }, `The JavaScript`), mdx(\"p\", null, `The button by itself won't do anything. For that, we use JavaScript.`), mdx(\"div\", {\n    \"className\": \"gatsby-highlight\",\n    \"data-language\": \"javascript\"\n  }, mdx(\"pre\", _extends({\n    parentName: \"div\"\n  }, {\n    \"className\": \"language-javascript\"\n  }), mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-javascript\"\n  }), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token keyword\"\n  }), `const`), ` toggleMenu `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token operator\"\n  }), `=`), ` document`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `.`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token function\"\n  }), `querySelector`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `(`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token string\"\n  }), `'.navigation button'`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `)`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token keyword\"\n  }), `const`), ` menu `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token operator\"\n  }), `=`), ` document`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `.`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token function\"\n  }), `querySelector`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `(`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token string\"\n  }), `'.navigation ul'`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `)`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n\ntoggleMenu`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `.`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token function\"\n  }), `addEventListener`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `(`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token string\"\n  }), `'click'`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `,`), ` `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token keyword\"\n  }), `function`), ` `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `(`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `)`), ` `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `{`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token keyword\"\n  }), `const`), ` open `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token operator\"\n  }), `=`), ` `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token constant\"\n  }), `JSON`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `.`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token function\"\n  }), `parse`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `(`), `toggleMenu`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `.`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token function\"\n  }), `getAttribute`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `(`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token string\"\n  }), `'aria-expanded'`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `)`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `)`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n  toggleMenu`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `.`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token function\"\n  }), `setAttribute`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `(`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token string\"\n  }), `'aria-expanded'`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `,`), ` `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token operator\"\n  }), `!`), `open`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `)`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n  menu`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `.`), `hidden `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token operator\"\n  }), `=`), ` `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token operator\"\n  }), `!`), `menu`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `.`), `hidden`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token keyword\"\n  }), `if`), ` `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `(`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token operator\"\n  }), `!`), `menu`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `.`), `hidden`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `)`), ` `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `{`), `\n    menu`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `.`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token function\"\n  }), `querySelector`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `(`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token string\"\n  }), `'a'`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `)`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `.`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token function\"\n  }), `focus`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `(`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `)`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `}`), `\n`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `}`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `)`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`)))), mdx(\"p\", null, `When you click on the button, we call a function that will get the current value of the \"aria-expanded\" attribute, and invert it. It will do the same for the \"hidden\" attribute on the menu. When the menu is visible, we'll focus the first link so it gets properly announced.`), mdx(\"p\", null, mdx(\"em\", {\n    parentName: \"p\"\n  }, `The `, mdx(\"code\", _extends({\n    parentName: \"em\"\n  }, {\n    \"className\": \"language-text\"\n  }), `JSON.parse`), ` function helps us convert the attribute from a string to a real boolean.`)), mdx(\"p\", null, `At this point, the toggle is functional:`), mdx(\"div\", null, mdx(\"iframe\", {\n    height: \"265\",\n    style: {\n      \"width\": \"100%\"\n    },\n    scrolling: \"no\",\n    title: \"The perfect responsive menu (skeleton)\",\n    src: \"https://codepen.io/Kilian/embed/wvwQwgo?height=265&theme-id=0&default-tab=js,result\",\n    frameBorder: \"no\",\n    allowtransparency: \"true\",\n    allowFullScreen: \"true\"\n  }, \"See the Pen \", mdx(\"a\", {\n    href: \"https://codepen.io/Kilian/pen/wvwQwgo\"\n  }, \"The perfect responsive menu (skeleton)\"), \" by Kilian Valkhof (\", mdx(\"a\", {\n    href: \"https://codepen.io/Kilian\"\n  }, \"@Kilian\"), \") on \", mdx(\"a\", {\n    href: \"https://codepen.io\"\n  }, \"CodePen\"), \".\")), mdx(\"h2\", {\n    \"id\": \"the-css\"\n  }, `The CSS`), mdx(\"p\", null, `Support for the hidden attribute goes back to IE11, but if you need to support older browsers, then adding the CSS below will let you support them. `, mdx(\"em\", {\n    parentName: \"p\"\n  }, `(keep in mind you might need to change the javascript above too)`)), mdx(\"div\", {\n    \"className\": \"gatsby-highlight\",\n    \"data-language\": \"css\"\n  }, mdx(\"pre\", _extends({\n    parentName: \"div\"\n  }, {\n    \"className\": \"language-css\"\n  }), mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-css\"\n  }), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token selector\"\n  }), `[hidden]`), ` `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `{`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `display`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` none`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `}`)))), mdx(\"p\", null, `At a certain width, the viewport will be wide enough to hide the button and show the menu:`), mdx(\"div\", {\n    \"className\": \"gatsby-highlight\",\n    \"data-language\": \"css\"\n  }, mdx(\"pre\", _extends({\n    parentName: \"div\"\n  }, {\n    \"className\": \"language-css\"\n  }), mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-css\"\n  }), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token atrule\"\n  }), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token rule\"\n  }), `@media`), ` `, mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `(`), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token property\"\n  }), `min-width`), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` 40rem`, mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `)`)), ` `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `{`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token selector\"\n  }), `#navigation button`), ` `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `{`), `\n    `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `display`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` none`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `}`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token selector\"\n  }), `#menu`), ` `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `{`), `\n    `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `display`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` block`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `}`), `\n`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `}`)))), mdx(\"p\", null, `The width at which this happens depends on your design and the length of your menu, so while 40rem works for me, it might not work for you.`), mdx(\"p\", null, `To show this in action, toggle the \"CSS\" panel in the pen below, it will switch between showing just the button and just the menu.`), mdx(\"div\", null, mdx(\"iframe\", {\n    height: \"265\",\n    style: {\n      \"width\": \"100%\"\n    },\n    scrolling: \"no\",\n    title: \"The perfect responsive menu (responsive)\",\n    src: \"https://codepen.io/Kilian/embed/NWKEKag?height=265&theme-id=0&default-tab=js,result\",\n    frameBorder: \"no\",\n    allowtransparency: \"true\",\n    allowFullScreen: \"true\"\n  }, \"See the Pen \", mdx(\"a\", {\n    href: \"https://codepen.io/Kilian/pen/NWKEKag\"\n  }, \"The perfect responsive menu (responsive)\"), \" by Kilian Valkhof (\", mdx(\"a\", {\n    href: \"https://codepen.io/Kilian\"\n  }, \"@Kilian\"), \") on \", mdx(\"a\", {\n    href: \"https://codepen.io\"\n  }, \"CodePen\"), \".\")), mdx(\"h2\", {\n    \"id\": \"the-finishing-touch-styling\"\n  }, `The finishing touch: styling`), mdx(\"p\", null, `At this point, it's up to you how you want to style the button and the menu. You can make it as simple or complicated as you want.`), mdx(\"p\", null, `For example, the mobile menu on the Polypane website uses an svg icon for the menu with an animated growing background and a staggered animation of the menu items. I switched to PostCSS (which allows nesting) to make things a little more readable.`), mdx(\"div\", null, mdx(\"iframe\", {\n    height: \"265\",\n    style: {\n      \"width\": \"100%\"\n    },\n    scrolling: \"no\",\n    title: \"The perfect responsive menu (styled)\",\n    src: \"https://codepen.io/Kilian/embed/yLBQBpK?height=265&theme-id=0&default-tab=css,result\",\n    frameBorder: \"no\",\n    allowtransparency: \"true\",\n    allowFullScreen: \"true\"\n  }, \"See the Pen \", mdx(\"a\", {\n    href: \"https://codepen.io/Kilian/pen/yLBQBpK\"\n  }, \"The perfect responsive menu (styled)\"), \" by Kilian Valkhof (\", mdx(\"a\", {\n    href: \"https://codepen.io/Kilian\"\n  }, \"@Kilian\"), \") on \", mdx(\"a\", {\n    href: \"https://codepen.io\"\n  }, \"CodePen\"), \".\")), mdx(\"p\", null, `It doesn't have to look like this though! With just this skeleton HTML and JavaScript, you can use CSS to style it in many different ways. You might choose to slide open the menu like a dropdown, pushing the rest of the content down, or you could have it slide in from the left like a side panel. And using css transforms you can animate the transition in any way you like.`), mdx(\"p\", null, `As long as you keep the HTML and the core functionality of the JavaScript intact, you will have an accessible, responsive menu that uses the same HTML on both mobile and wider viewports. `, mdx(\"strong\", {\n    parentName: \"p\"\n  }, `The perfect responsive menu.`)));\n}\n;\nMDXContent.isMDXComponent = true;","timeToRead":2,"tableOfContents":{"items":[{"url":"#the-html","title":"The HTML"},{"url":"#the-javascript","title":"The JavaScript"},{"url":"#the-css","title":"The CSS"},{"url":"#the-finishing-touch-styling","title":"The finishing touch: styling"}]},"excerpt":"On a desktop, websites have the space to show the full menu or navbar. On a mobile device that space isn't there and you want to hide the menu behind a toggle…","frontmatter":{"title":"The perfect responsive menu (2021)","cover":"/blogs/perfectmenu/cover.svg","date":"2019-09-20","updated":"2021-05-30"},"fields":{"slug":"/blog/the-perfect-responsive-menu/","date":"2019-09-19T22:00:00.000Z","ogFileName":"the-perfect-responsive-menu-2021"}}},"pageContext":{"slug":"/blog/the-perfect-responsive-menu/"}},"staticQueryHashes":["4164364741","425175329"]}