{"id":186,"date":"2014-09-29T16:02:19","date_gmt":"2014-09-29T22:02:19","guid":{"rendered":"http:\/\/laubsterboy.com\/blog\/?p=186"},"modified":"2014-09-29T16:16:16","modified_gmt":"2014-09-29T22:16:16","slug":"wordpress-menu-anchor","status":"publish","type":"post","link":"https:\/\/www.johnrussell.dev\/blog\/2014\/09\/wordpress-menu-anchor\/","title":{"rendered":"WordPress Menu Anchor"},"content":{"rendered":"<p>I recently had the need to add a series of anchor links to a WordPress menu that linked to specific sections\u00a0of a page. I found this to be tedious, since the page URL needed to be hard coded into the custom link menu item and if the page URL was ever updated each anchor needed to be updated as well. To complicate things further, when looking at the custom link within the menu editor it&#8217;s not immediately obvious that the link is an anchor if the URL is longer than the input box.<\/p>\n<p>What I wanted to be able to do is simply create a custom link menu item and set the link value to <em>#my-custom-anchor.\u00a0<\/em>Generally if you create a custom link menu item and set the link to be something like\u00a0<em>#my-custom-anchor<\/em> it will work, if you&#8217;re already on the page for the given anchor, however it will also navigate to &#8220;my-custom-anchor&#8221; even if you&#8217;re on another page where &#8220;my-custom-anchor&#8221; doesn&#8217;t exist.<\/p>\n<p>What I needed was for the anchor to navigate to the desired page and then to the specific section of the page. To do this, the URL would need to have the page URL prepended to the anchor hash. This would allow anchor links to be clicked from anywhere on the website and still navigate to the correct page, and correct section, but if the page was already being viewed the page would not reload (so scrolling animations would still work as well).<\/p>\n<p>Since all of the anchor links were nested under a page menu item, as illustrated in the example below, I was able to filter the menu and prepend\u00a0the URL with the URL of its&#8217; parent menu item.<\/p>\n<h3>Menu Structure Example<\/h3>\n<ul>\n<li>Page Menu Item 1\n<ul>\n<li>Page Section 1 Anchor Menu Item<\/li>\n<li>Page Section 2 Anchor Menu Item\n<ul>\n<li>Page Section 2 Sub Section 1 Anchor Menu Item<\/li>\n<li>Page Section 2 Sub Section 2 Anchor Menu Item<\/li>\n<\/ul>\n<\/li>\n<li>Page Section 3 Anchor Menu Item<\/li>\n<\/ul>\n<\/li>\n<li>Page Menu Item 2<\/li>\n<li>Page Menu Item 3<\/li>\n<\/ul>\n<p>In the above example each &#8220;Page Section&#8230; Menu Item&#8221; would link to &#8220;Page Menu Item 1&#8221; and scroll to the specified section of that page. This is very useful for long pages with many sections and sub-sections.<\/p>\n<h2>The Solution is in the Code<\/h2>\n<p>To accomplish this I created a menu filter function, that gets added to the themes functions.php file, that searches for menu items with URLs that begin with a # and then prepends the URL with the URL of its&#8217; parent menu item.<\/p>\n<pre class=\"lang:php decode:true\">function lb_menu_anchors($items, $args) {\r\n\t$urls = array();\r\n\t$custom_anchor_links = array();\r\n\t\r\n\tforeach ($items as $key =&gt; $item) {\r\n\t\t$urls[$item-&gt;ID] = $item-&gt;url;\r\n\t\t\r\n\t\tif ($item-&gt;object == 'custom' &amp;&amp; substr($item-&gt;url, 0, 1) == '#') {\r\n\t\t\t$custom_anchor_links[] = $item;\r\n\t\t} \r\n\t}\r\n\t\r\n\tforeach ($custom_anchor_links as $custom_anchor_link) {\r\n\t\tif (strpos($urls[$custom_anchor_link-&gt;menu_item_parent], '#') === false) {\r\n\t\t\t$custom_anchor_link-&gt;url = $urls[$custom_anchor_link-&gt;menu_item_parent] . $custom_anchor_link-&gt;url;\r\n\t\t} else {\r\n\t\t\t\/\/ multiple nested menu items with anchors\r\n\t\t\t$custom_anchor_link-&gt;url = explode('#', $urls[$custom_anchor_link-&gt;menu_item_parent])[0] . $custom_anchor_link-&gt;url;\r\n\t\t}\r\n\t}\r\n\t\r\n\treturn $items;\r\n}\r\nadd_filter('wp_nav_menu_objects', 'lb_menu_anchors', 10, 2);<\/pre>\n<p>This allowed me to create custom link menu items with easily readable anchor links, that could\u00a0be nested, and would also dynamically update if the page URL ever changed. Another benefit to this method vs &#8220;hard coding&#8221; an anchor link menu item is that the URL continues to work in a <a href=\"https:\/\/wordpress.org\/plugins\/wordpress-mu-domain-mapping\/\">Domain Mapped<\/a> environment, and across dev, staging, and production environments as well.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I recently had the need to add a series of anchor links to a WordPress menu that linked to specific sections\u00a0of a page. I found this to be tedious, since the page URL needed to be hard coded into the custom link menu item and if the page URL was ever updated each anchor needed [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[2],"tags":[73,72,22,77,78,74,42,75,76,64,69,71],"class_list":["post-186","post","type-post","status-publish","format-standard","hentry","category-code-snippet","tag-anchor","tag-custom-link","tag-domain-mapping","tag-filter","tag-functions","tag-link","tag-menu","tag-nested-menu","tag-url","tag-wordpress","tag-wp_nav_menu","tag-wp_nav_menu_objects"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.1.1 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>WordPress Menu Anchor - John Russell Blog<\/title>\n<meta name=\"description\" content=\"WordPress Menu Anchor - A code snippet for creating maintainable anchors in WordPress menus.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.johnrussell.dev\/blog\/2014\/09\/wordpress-menu-anchor\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"WordPress Menu Anchor - John Russell Blog\" \/>\n<meta property=\"og:description\" content=\"WordPress Menu Anchor - A code snippet for creating maintainable anchors in WordPress menus.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.johnrussell.dev\/blog\/2014\/09\/wordpress-menu-anchor\/\" \/>\n<meta property=\"og:site_name\" content=\"John Russell Blog\" \/>\n<meta property=\"article:published_time\" content=\"2014-09-29T22:02:19+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2014-09-29T22:16:16+00:00\" \/>\n<meta name=\"author\" content=\"John Russell\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@laubsterboy\" \/>\n<meta name=\"twitter:site\" content=\"@laubsterboy\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"John Russell\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"3 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.johnrussell.dev\/blog\/2014\/09\/wordpress-menu-anchor\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.johnrussell.dev\/blog\/2014\/09\/wordpress-menu-anchor\/\"},\"author\":{\"name\":\"John Russell\",\"@id\":\"https:\/\/www.johnrussell.dev\/blog\/#\/schema\/person\/296c0c6bd1deeeb20834393e1e16325c\"},\"headline\":\"WordPress Menu Anchor\",\"datePublished\":\"2014-09-29T22:02:19+00:00\",\"dateModified\":\"2014-09-29T22:16:16+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.johnrussell.dev\/blog\/2014\/09\/wordpress-menu-anchor\/\"},\"wordCount\":481,\"commentCount\":11,\"keywords\":[\"anchor\",\"custom link\",\"Domain Mapping\",\"filter\",\"functions\",\"link\",\"Menu\",\"nested menu\",\"URL\",\"WordPress\",\"wp_nav_menu\",\"wp_nav_menu_objects\"],\"articleSection\":[\"Code Snippet\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.johnrussell.dev\/blog\/2014\/09\/wordpress-menu-anchor\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.johnrussell.dev\/blog\/2014\/09\/wordpress-menu-anchor\/\",\"url\":\"https:\/\/www.johnrussell.dev\/blog\/2014\/09\/wordpress-menu-anchor\/\",\"name\":\"WordPress Menu Anchor - John Russell Blog\",\"isPartOf\":{\"@id\":\"https:\/\/www.johnrussell.dev\/blog\/#website\"},\"datePublished\":\"2014-09-29T22:02:19+00:00\",\"dateModified\":\"2014-09-29T22:16:16+00:00\",\"author\":{\"@id\":\"https:\/\/www.johnrussell.dev\/blog\/#\/schema\/person\/296c0c6bd1deeeb20834393e1e16325c\"},\"description\":\"WordPress Menu Anchor - A code snippet for creating maintainable anchors in WordPress menus.\",\"breadcrumb\":{\"@id\":\"https:\/\/www.johnrussell.dev\/blog\/2014\/09\/wordpress-menu-anchor\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.johnrussell.dev\/blog\/2014\/09\/wordpress-menu-anchor\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.johnrussell.dev\/blog\/2014\/09\/wordpress-menu-anchor\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.johnrussell.dev\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"WordPress Menu Anchor\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.johnrussell.dev\/blog\/#website\",\"url\":\"https:\/\/www.johnrussell.dev\/blog\/\",\"name\":\"John Russell Blog\",\"description\":\"\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.johnrussell.dev\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.johnrussell.dev\/blog\/#\/schema\/person\/296c0c6bd1deeeb20834393e1e16325c\",\"name\":\"John Russell\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.johnrussell.dev\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/00ce0f258fcc5e5d29897a5e81316009713e9104cfaf49f481c5bce3f81c7cb1?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/00ce0f258fcc5e5d29897a5e81316009713e9104cfaf49f481c5bce3f81c7cb1?s=96&d=mm&r=g\",\"caption\":\"John Russell\"},\"url\":\"https:\/\/www.johnrussell.dev\/blog\/author\/laubsterboy\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"WordPress Menu Anchor - John Russell Blog","description":"WordPress Menu Anchor - A code snippet for creating maintainable anchors in WordPress menus.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.johnrussell.dev\/blog\/2014\/09\/wordpress-menu-anchor\/","og_locale":"en_US","og_type":"article","og_title":"WordPress Menu Anchor - John Russell Blog","og_description":"WordPress Menu Anchor - A code snippet for creating maintainable anchors in WordPress menus.","og_url":"https:\/\/www.johnrussell.dev\/blog\/2014\/09\/wordpress-menu-anchor\/","og_site_name":"John Russell Blog","article_published_time":"2014-09-29T22:02:19+00:00","article_modified_time":"2014-09-29T22:16:16+00:00","author":"John Russell","twitter_card":"summary_large_image","twitter_creator":"@laubsterboy","twitter_site":"@laubsterboy","twitter_misc":{"Written by":"John Russell","Est. reading time":"3 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.johnrussell.dev\/blog\/2014\/09\/wordpress-menu-anchor\/#article","isPartOf":{"@id":"https:\/\/www.johnrussell.dev\/blog\/2014\/09\/wordpress-menu-anchor\/"},"author":{"name":"John Russell","@id":"https:\/\/www.johnrussell.dev\/blog\/#\/schema\/person\/296c0c6bd1deeeb20834393e1e16325c"},"headline":"WordPress Menu Anchor","datePublished":"2014-09-29T22:02:19+00:00","dateModified":"2014-09-29T22:16:16+00:00","mainEntityOfPage":{"@id":"https:\/\/www.johnrussell.dev\/blog\/2014\/09\/wordpress-menu-anchor\/"},"wordCount":481,"commentCount":11,"keywords":["anchor","custom link","Domain Mapping","filter","functions","link","Menu","nested menu","URL","WordPress","wp_nav_menu","wp_nav_menu_objects"],"articleSection":["Code Snippet"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.johnrussell.dev\/blog\/2014\/09\/wordpress-menu-anchor\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.johnrussell.dev\/blog\/2014\/09\/wordpress-menu-anchor\/","url":"https:\/\/www.johnrussell.dev\/blog\/2014\/09\/wordpress-menu-anchor\/","name":"WordPress Menu Anchor - John Russell Blog","isPartOf":{"@id":"https:\/\/www.johnrussell.dev\/blog\/#website"},"datePublished":"2014-09-29T22:02:19+00:00","dateModified":"2014-09-29T22:16:16+00:00","author":{"@id":"https:\/\/www.johnrussell.dev\/blog\/#\/schema\/person\/296c0c6bd1deeeb20834393e1e16325c"},"description":"WordPress Menu Anchor - A code snippet for creating maintainable anchors in WordPress menus.","breadcrumb":{"@id":"https:\/\/www.johnrussell.dev\/blog\/2014\/09\/wordpress-menu-anchor\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.johnrussell.dev\/blog\/2014\/09\/wordpress-menu-anchor\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.johnrussell.dev\/blog\/2014\/09\/wordpress-menu-anchor\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.johnrussell.dev\/blog\/"},{"@type":"ListItem","position":2,"name":"WordPress Menu Anchor"}]},{"@type":"WebSite","@id":"https:\/\/www.johnrussell.dev\/blog\/#website","url":"https:\/\/www.johnrussell.dev\/blog\/","name":"John Russell Blog","description":"","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.johnrussell.dev\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/www.johnrussell.dev\/blog\/#\/schema\/person\/296c0c6bd1deeeb20834393e1e16325c","name":"John Russell","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.johnrussell.dev\/blog\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/00ce0f258fcc5e5d29897a5e81316009713e9104cfaf49f481c5bce3f81c7cb1?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/00ce0f258fcc5e5d29897a5e81316009713e9104cfaf49f481c5bce3f81c7cb1?s=96&d=mm&r=g","caption":"John Russell"},"url":"https:\/\/www.johnrussell.dev\/blog\/author\/laubsterboy\/"}]}},"_links":{"self":[{"href":"https:\/\/www.johnrussell.dev\/blog\/wp-json\/wp\/v2\/posts\/186","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.johnrussell.dev\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.johnrussell.dev\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.johnrussell.dev\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.johnrussell.dev\/blog\/wp-json\/wp\/v2\/comments?post=186"}],"version-history":[{"count":6,"href":"https:\/\/www.johnrussell.dev\/blog\/wp-json\/wp\/v2\/posts\/186\/revisions"}],"predecessor-version":[{"id":279,"href":"https:\/\/www.johnrussell.dev\/blog\/wp-json\/wp\/v2\/posts\/186\/revisions\/279"}],"wp:attachment":[{"href":"https:\/\/www.johnrussell.dev\/blog\/wp-json\/wp\/v2\/media?parent=186"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.johnrussell.dev\/blog\/wp-json\/wp\/v2\/categories?post=186"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.johnrussell.dev\/blog\/wp-json\/wp\/v2\/tags?post=186"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}