{"id":19174,"date":"2012-11-07T13:03:35","date_gmt":"2012-11-07T20:03:35","guid":{"rendered":"http:\/\/css-tricks.com\/?p=19174"},"modified":"2012-11-07T13:04:29","modified_gmt":"2012-11-07T20:04:29","slug":"off-canvas-menu-with-css-target","status":"publish","type":"post","link":"https:\/\/css-tricks.com\/off-canvas-menu-with-css-target\/","title":{"rendered":"Off Canvas Menu with CSS :target"},"content":{"rendered":"

“Off Canvas” patterns<\/a> are different ways to approach layout where content on the web isn’t just laid out in a vertical column. For instance, navigation could be positioned hidden off the left edge of the “canvas” (visible browser window) and slid in on demand. Anthony Colangelo created jPanelMenu<\/a> to do just that. Hakim El Hattab’s Meny<\/a> is fancier but similar in what it accomplishes.<\/p>\n

They both use JavaScript. I thought it would be fun to try and recreate Anthony’s jPanelMenu using only CSS. It’s do-able – with several advantages and disadvantages.<\/p>\n

<\/p>\n

\ncssPanelMenu
\n
View Demo<\/a>
\n<\/figure>\n

Two Columns, One Collapsed<\/h3>\n

The layout technique here is essentially a two column grid. Only the left column is 0% wide and the right column is 100% wide by default. The left column is the navigation we intend to reveal as needed. With hidden overflow, this column is completely hidden.<\/p>\n

<!-- I am collapsed by default -->\r\n<nav id=\"main-navigation\" class=\"navigation\">\r\n   <a href=\"#\">Nav Links<\/a>\r\n   <!-- more -->\r\n<\/nav>\r\n\r\n<!-- I am full width by default -->\r\n<div class=\"page-wrap\">\r\n  <header>\r\n    <a href=\"#main-navigation\">Menu<\/a>\r\n    <h1>Title<\/h1>\r\n  <\/header>\r\n\r\n  <!-- content -->\r\n<\/div><\/code><\/pre>\n
.navigation {\r\n  \r\n  \/* Collapsed *\/\r\n  width: 0; \r\n\r\n  overflow: hidden;\r\n  position: fixed;\r\n  top: 0;\r\n  left: 0;\r\n  height: 100%;\r\n}\r\n\r\n.page-wrap {\r\n  width: 100%;\r\n  float: right;\r\n}<\/code><\/pre>\n

Open Menu State with :target<\/h3>\n

Notice that this link:<\/p>\n

<a href=\"#main-navigation\">Menu<\/a><\/code><\/pre>\n

Matches the ID of:<\/p>\n

<nav id=\"main-navigation\" class=\"navigation\"><\/code><\/pre>\n

That’s a regular ol’ hash-link. The page will “jump” to that element. More importantly to us, it will make this selector match:<\/p>\n

#main-navigation:target {\r\n\r\n}<\/code><\/pre>\n

So when that link is clicked, we can un-hide the menu by increasing it’s width. Might as well make it slide out nicely.<\/p>\n

.navigation {\r\n  transition: width 0.3s ease;\r\n}\r\n#main-nav:target {\r\n  width: 20%; \r\n}<\/code><\/pre>\n

We could leave it at that, and the menu would overlap the content (make sure it has a higher z-index). That would be perfectly fine. But we do have options. We could “push” the content off the right edge of the content instead. That’s what, for example, Facebook does in their mobile app when the left menu is revealed. Or we could squish up the main content making a 20%\/80% grid. That’s what we’ll do here.<\/p>\n

But wait… how do we select the .page-wrap only in the particular state when the menu is open? We can use an adjacent sibling combinator<\/a>!<\/p>\n

#main-nav:target + .page-wrap {\r\n  width: 80%;\r\n}<\/code><\/pre>\n

It’s that easy.<\/p>\n

To close the menu, we just need to remove the hash-link in the URL. Essentially, provide an link like this anywhere:<\/p>\n

<a href=\"#\">Close Menu<\/a><\/code><\/pre>\n

If you wanted to get real fancy you could hide\/show different links positioned in the same exact place to create a “toggle link”.<\/p>\n

Advantages<\/h3>\n

It’s all CSS! Less code overall. Less resources to load. Works without JavaScript. Transition smoother than JavaScript transition.<\/p>\n

Disadvantages<\/h3>\n

Limited browser support. :target<\/a> is IE9+ (the whole thing fails if :target doesn’t work). Transitions<\/a> are IE 10+. Changing classes or hide\/showing\/animating with JavaScript can overcome any browser limitations. Also you’ll have more freedom in how the markup can be arranged instead of being forced into the specific order presented here. Also possibly slightly better semantics, not needing separate links for opening and closing the menu.<\/p>\n","protected":false},"excerpt":{"rendered":"

“Off Canvas” patterns are different ways to approach layout where content on the web isn’t just laid out in a vertical column. For instance, navigation could be positioned hidden off the left edge of the “canvas” (visible browser window) and slid in on demand. Anthony Colangelo created jPanelMenu to do just that. Hakim El Hattab’s […]<\/p>\n","protected":false},"author":3,"featured_media":0,"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":[],"jetpack_publicize_connections":[],"acf":[],"jetpack_featured_media_url":"","jetpack-related-posts":[{"id":176437,"url":"https:\/\/css-tricks.com\/guide-responsive-friendly-css-columns\/","url_meta":{"origin":19174,"position":0},"title":"Guide to Responsive-Friendly CSS Columns","date":"July 25, 2014","format":false,"excerpt":"With CSS columns you can create a print-inspired layout with little added markup that can adapt beyond a fixed canvas. A supported browser will make calculations to wrap and balance content into tidy columns. If you're already working with a fluid layout, the columns will reflow automatically. With the right\u2026","rel":"","context":"In "Article"","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":153033,"url":"https:\/\/css-tricks.com\/arranging-elements-top-bottom-instead-left-right-float\/","url_meta":{"origin":19174,"position":1},"title":"Arranging Elements from Top to Bottom instead of Left to Right (float: down?)","date":"October 15, 2013","format":false,"excerpt":"Reader Marcin A wrote in with this question about a simple unordered list in which they wanted the elements to be arranged in vertical order (top to bottom) instead of horizontal (left to right). So markup like: 1 2 3 4 5 6 Which would end up like: 1 4\u2026","rel":"","context":"In "Article"","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":303379,"url":"https:\/\/css-tricks.com\/responsive-grid-magazine-layout-in-just-20-lines-of-css\/","url_meta":{"origin":19174,"position":2},"title":"Responsive Grid Magazine Layout in Just 20 Lines of CSS","date":"February 25, 2020","format":false,"excerpt":"I was recently working on a modern take of the blogroll. The idea was to offer readers a selection of latest posts from those blogs in a magazine-style layout, instead of just popping a list of our favorite blogs in the sidebar. The easy part was grabbing a list of\u2026","rel":"","context":"In "Article"","img":{"alt_text":"","src":"https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2020\/02\/grid-spans.png?fit=1200%2C600&ssl=1&resize=350%2C200","width":350,"height":200},"classes":[]},{"id":323307,"url":"https:\/\/css-tricks.com\/full-bleed\/","url_meta":{"origin":19174,"position":3},"title":"Full Bleed","date":"October 15, 2020","format":false,"excerpt":"We've covered techniques before for when you want a full-width element within a constrained-width column, like an edge-to-edge image within a narrower column of text. There are loads of techniques. Perhaps my favorite is this little utility class: .full-width { width: 100vw; position: relative; left: 50%; right: 50%; margin-left: -50vw;\u2026","rel":"","context":"In "Article"","img":{"alt_text":"","src":"https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2020\/10\/full-bleed-breakout.jpg?fit=1200%2C600&ssl=1&resize=350%2C200","width":350,"height":200},"classes":[]},{"id":376307,"url":"https:\/\/css-tricks.com\/faking-min-width-on-a-table-column\/","url_meta":{"origin":19174,"position":4},"title":"Faking Min Width on a Table Column","date":"January 10, 2023","format":false,"excerpt":"The good ol\u2019 tag is the most semantic HTML for showing tabular data. But I find it very hard to control how the table is presented, particularly column widths in a dynamic environment where you might not know how much content is going into each table cell. In some\u2026","rel":"","context":"In "Article"","img":{"alt_text":"","src":"https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2019\/07\/table-pattern.png?fit=1200%2C600&ssl=1&resize=350%2C200","width":350,"height":200},"classes":[]},{"id":351481,"url":"https:\/\/css-tricks.com\/minding-the-gap\/","url_meta":{"origin":19174,"position":5},"title":"Minding the “gap”","date":"September 16, 2021","format":false,"excerpt":"You might already know about the CSS gap property. It isn\u2019t exactly new, but it did gain an important new ability last year: it now works in Flexbox in addition to CSS Grid. That, and the fact that I believe the property is more complicated than it appears, made me\u2026","rel":"","context":"In "Article"","img":{"alt_text":"","src":"https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2021\/09\/z8fc2xmA.jpeg?fit=1200%2C1003&ssl=1&resize=350%2C200","width":350,"height":200},"classes":[]}],"featured_media_src_url":null,"_links":{"self":[{"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/posts\/19174"}],"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=19174"}],"version-history":[{"count":5,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/posts\/19174\/revisions"}],"predecessor-version":[{"id":19185,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/posts\/19174\/revisions\/19185"}],"wp:attachment":[{"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/media?parent=19174"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/categories?post=19174"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/tags?post=19174"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}