{"id":251715,"date":"2017-02-20T08:52:28","date_gmt":"2017-02-20T15:52:28","guid":{"rendered":"http:\/\/css-tricks.com\/?p=251715"},"modified":"2017-02-20T08:52:28","modified_gmt":"2017-02-20T15:52:28","slug":"squeezy-stretchy-flexbox-nav","status":"publish","type":"post","link":"https:\/\/css-tricks.com\/squeezy-stretchy-flexbox-nav\/","title":{"rendered":"Squeezy Stretchy Flexbox Nav"},"content":{"rendered":"

I saw an interesting take on off-canvas navigation the other day over on The New Tropic<\/a>. It wasn’t the off-canvas part so much. It was how the elements within the nav took up space. They stretched out to take up all the space, when available, but never squished too far. Those are concepts that flexbox makes pretty easy to express! Let’s dig in a little.<\/p>\n

<\/p>\n

Here’s the nav, a video showing what I mean:<\/p>\n

Standard Two-Level Nav HTML<\/h3>\n

Pretty easy to mock out with Emmet<\/a>:<\/p>\n

<nav class=\"main-nav\">\r\n  <ul class=\"nav-list\">\r\n    <li><a href=\"\">Lorem ipsum.<\/a><\/li>\r\n    <li>\r\n      <button class=\"submenu-toggle-button\">+<\/button>\r\n      <a href=\"\">Explicabo, perspiciatis.<\/a>\r\n      <ul class=\"submenu nav-list\">\r\n        <li><a href=\"\">Lorem ipsum.<\/a><\/li>\r\n        <li><a href=\"\">Culpa, qui!<\/a><\/li>\r\n        <li><a href=\"\">Repudiandae, eaque.<\/a><\/li>\r\n      <\/ul>\r\n    <\/li>\r\n    <li><a href=\"\">Sit, dolor.<\/a><\/li>\r\n    <li><a href=\"\">Dicta, possimus?<\/a><\/li>\r\n    \r\n    <!-- etc -->\r\n\r\n  <\/ul>\r\n<\/nav><\/code><\/pre>\n

Flexbox the Column<\/h3>\n

Let’s make sure that list is as tall as the browser window, which is easy with viewport units. Then make sure each of the list items stretch to fill the space:<\/p>\n

.main-nav > ul {\r\n  height: 100vh;\r\n  display: flex;\r\n  flex-direction: column;\r\n}\r\n.main-nav > ul > li {\r\n  flex: 1;\r\n}<\/code><\/pre>\n

We’ve already gotten almost all the way there! Stretching works great, only when there is room, like we want:<\/p>\n

Quick Toggles<\/h3>\n

We have a <button><\/code> in place to toggle the submenus (arguably, we should probably place<\/em> those buttons with JavaScript, since they don’t do anything without). Here’s how they could work. The submenus are hidden by default:<\/p>\n

.submenu {\r\n  max-height: 0;\r\n  transition: 0.5s;\r\n  overflow: hidden;\r\n}<\/code><\/pre>\n

We can open it with a class:<\/p>\n

.submenu.open {\r\n  max-height: 200px; \/* non-ideal magic number *\/\r\n}<\/code><\/pre>\n

We’re animating to an unknown height here, which is tricky. We hope to have a good article addressing this out soon (there are options). <\/p>\n

Toggling classes is plenty easy<\/a>:<\/p>\n

var buttons = document.querySelectorAll('.submenu-toggle-button');\r\n\r\n[].forEach.call(buttons, function(button) {\r\n  button.addEventListener('click', function() {\r\n    var submenu = button.parentNode.querySelector('.submenu');\r\n    submenu.classList.toggle('open');\r\n  });\r\n});<\/code><\/pre>\n

That gets those submenus behaving like we want:<\/p>\n

Demo<\/h3>\n

You’ll probably need to pop over to the Pen<\/a> to play with the vertical stretching stuff.<\/p>\n

See the Pen Squeezy Stretchy Nav<\/a> by Chris Coyier (@chriscoyier<\/a>) on CodePen<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"

I saw an interesting take on off-canvas navigation the other day over on The New Tropic. It wasn’t the off-canvas part so much. It was how the elements within the nav took up space. They stretched out to take up all the space, when available, but never squished too far. Those are concepts that flexbox […]<\/p>\n","protected":false},"author":3,"featured_media":251731,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_bbp_topic_count":0,"_bbp_reply_count":0,"_bbp_total_topic_count":0,"_bbp_total_reply_count":0,"_bbp_voice_count":0,"_bbp_anonymous_reply_count":0,"_bbp_topic_count_hidden":0,"_bbp_reply_count_hidden":0,"_bbp_forum_subforum_count":0,"sig_custom_text":"","sig_image_type":"featured-image","sig_custom_image":0,"sig_is_disabled":false,"inline_featured_image":false,"c2c_always_allow_admin_comments":false,"footnotes":"","jetpack_publicize_message":"","jetpack_is_tweetstorm":false,"jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":[]},"categories":[4],"tags":[532,880,1143],"jetpack_publicize_connections":[],"acf":[],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2017\/02\/flex-nav.png?fit=486%2C277&ssl=1","jetpack-related-posts":[{"id":289115,"url":"https:\/\/css-tricks.com\/making-width-and-flexible-items-play-nice-together\/","url_meta":{"origin":251715,"position":0},"title":"Making width and flexible items play nice together","date":"July 1, 2019","format":false,"excerpt":"The short answer: flex-shrink and flex-basis are probably what you\u2019re lookin\u2019 for. The long answer Let\u2019s say you want to align an image and some text next to each other with like this: Now let's say you reach for flexbox to make it happen. Setting the parent element to display:\u2026","rel":"","context":"In "Article"","img":{"alt_text":"","src":"https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2019\/06\/connected-boxes.png?fit=1200%2C600&ssl=1&resize=350%2C200","width":350,"height":200},"classes":[]},{"id":188502,"url":"https:\/\/css-tricks.com\/flexbox-nav-bar-fixed-variable-take-rest-elements\/","url_meta":{"origin":251715,"position":1},"title":"Flexbox Nav Bar with Fixed, Variable, and Take-Up-The-Rest Elements","date":"November 17, 2014","format":false,"excerpt":"a CSS-Tricks reader wrote to me with a layout question. A variety of elements need to be arranged in a horizontal bar. Some of fixed size, some vary, and one needs to take up the rest of the space. Flexbox is beautifully suited for this, so I explain with that.","rel":"","context":"In "Article"","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":150992,"url":"https:\/\/css-tricks.com\/targetting-menu-elements-submenus-navigation-bar\/","url_meta":{"origin":251715,"position":2},"title":"Targeting Menu Elements with Submenus in a Navigation Bar","date":"September 23, 2013","format":false,"excerpt":"The following is a guest post by Ray Messina. Ray was interested in sharing this technique as a way to pay forward things he's learned from this site in the past, which is awesome. You might be aware of the jQuery .has method, which allows you to select an element\u2026","rel":"","context":"In "Article"","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":359260,"url":"https:\/\/css-tricks.com\/topological-sort\/","url_meta":{"origin":251715,"position":3},"title":"Topological sort","date":"December 16, 2021","format":false,"excerpt":"Jordan Scales explores the computer science concept of topological sorting, and what it might look like if applied to the concept of z-index in CSS. So, you don't express what the z-index should be directly; instead, you say exactly what other element you want to be on top of. I\u2026","rel":"","context":"In "Link"","img":{"alt_text":"","src":"https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2018\/09\/z-index.jpg?fit=1200%2C600&ssl=1&resize=350%2C200","width":350,"height":200},"classes":[]},{"id":334042,"url":"https:\/\/css-tricks.com\/how-to-create-a-shrinking-header-on-scroll-without-javascript\/","url_meta":{"origin":251715,"position":4},"title":"How to Create a Shrinking Header on Scroll Without JavaScript","date":"February 16, 2021","format":false,"excerpt":"Imagine a header of a website that is nice and thick, with plenty of padding on top and bottom of the content. As you scroll down, it shrinks up on itself, reducing some of that padding, making more screen real estate for other content. Normally you would have to use\u2026","rel":"","context":"In "Article"","img":{"alt_text":"","src":"https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2021\/02\/shrinking-sticky-header-1.jpg?fit=1200%2C600&ssl=1&resize=350%2C200","width":350,"height":200},"classes":[]},{"id":164659,"url":"https:\/\/css-tricks.com\/flexbox-bar-navigation\/","url_meta":{"origin":251715,"position":5},"title":"Flexbox Bar Navigation Demo","date":"March 4, 2014","format":false,"excerpt":"Someone wrote in to me asking how to create a simple bar navigation with icons. This is a pretty simple layout thing that could be accomplished loads of different ways. List items as inline-block probably makes the most sense in general. But I've been enjoying tinkering with flexbox, so I\u2026","rel":"","context":"In "Article"","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]}],"featured_media_src_url":"https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2017\/02\/flex-nav.png?fit=486%2C277&ssl=1","_links":{"self":[{"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/posts\/251715"}],"collection":[{"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/comments?post=251715"}],"version-history":[{"count":7,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/posts\/251715\/revisions"}],"predecessor-version":[{"id":251730,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/posts\/251715\/revisions\/251730"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/media\/251731"}],"wp:attachment":[{"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/media?parent=251715"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/categories?post=251715"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/tags?post=251715"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}