{"id":6686,"date":"2025-08-07T08:45:02","date_gmt":"2025-08-07T13:45:02","guid":{"rendered":"https:\/\/frontendmasters.com\/blog\/?p=6686"},"modified":"2025-08-07T08:45:03","modified_gmt":"2025-08-07T13:45:03","slug":"using-the-custom-highlight-api","status":"publish","type":"post","link":"https:\/\/frontendmasters.com\/blog\/using-the-custom-highlight-api\/","title":{"rendered":"Using the Custom Highlight API"},"content":{"rendered":"\n<p>The <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/CSS_Custom_Highlight_API\">Custom Highlight API<\/a> came to my attention recently as <a href=\"https:\/\/caniuse.com\/mdn-api_highlight\">Firefox recently started supporting<\/a> it (Firefox 140, June 2025), which brought support across all the major browsers. With it, you can apply (some) styling to text that you get your hands on in JavaScript via the <code>Range()<\/code> class. I would say text that you <em>select<\/em>, but there aren&#8217;t really normal selectors involved here, making it rather unusual to work with for a CSS guy like me.<\/p>\n\n\n\n<p>I think a basic word explanation is helpful here, as it sure would have helped me when I first started <a href=\"https:\/\/www.youtube.com\/watch?v=IWDlCNEJclU\">poking at it<\/a>:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>You need a <code>textNode<\/code><sup data-fn=\"18958d55-4f3c-4d44-9460-f364498054cf\" class=\"fn\"><a href=\"#18958d55-4f3c-4d44-9460-f364498054cf\" id=\"18958d55-4f3c-4d44-9460-f364498054cf-link\">1<\/a><\/sup>. (e.g. <code>document.querySelector(\"p\").firstChild<\/code>)<\/li>\n\n\n\n<li>Then you need a <code>Range()<\/code> in which you do a <code>setStart<\/code> and <code>setEnd<\/code> on, meaning the range is now between those two integers.<\/li>\n\n\n\n<li>Then you call <code>CSS.highlights.set()<\/code> on that Range, giving it a name.<\/li>\n\n\n\n<li>Then you use <code>::highlight()<\/code>in CSS, passing in that name you just used.<\/li>\n<\/ol>\n\n\n\n<p>If we had one <code>&lt;p&gt;<\/code> of text on a page, that whole process looks like this:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-keyword\">const<\/span> WORD_TO_HIGHLIGHT = <span class=\"hljs-string\">\"wisdom\"<\/span>;\n<span class=\"hljs-keyword\">const<\/span> NAME_OF_HIGHLIGHT = <span class=\"hljs-string\">\"our-highlight\"<\/span>;\n\n<span class=\"hljs-keyword\">const<\/span> textNode = <span class=\"hljs-built_in\">document<\/span>.querySelector(<span class=\"hljs-string\">\"p\"<\/span>).firstChild;\n<span class=\"hljs-keyword\">const<\/span> textContent = textNode.textContent;\n\n<span class=\"hljs-keyword\">const<\/span> startIndex = textContent.indexOf(WORD_TO_HIGHLIGHT);\n<span class=\"hljs-keyword\">const<\/span> endIndex = startIndex + WORD_TO_HIGHLIGHT.length;\n\n<span class=\"hljs-keyword\">const<\/span> range = <span class=\"hljs-keyword\">new<\/span> Range();\nrange.setStart(textNode, startIndex);\nrange.setEnd(textNode, endIndex);\n\n<span class=\"hljs-keyword\">const<\/span> highlight = <span class=\"hljs-keyword\">new<\/span> Highlight(range);\nCSS.highlights.set(NAME_OF_HIGHLIGHT, highlight);<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>This is neat to see in DevTools, where the word &#8220;wisdom&#8221; clearly has custom CSS styling applied to it, but there is no element around that word that you&#8217;d normally think would be necessary to apply those styles.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large is-resized\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"794\" src=\"https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2025\/08\/Screenshot-2025-08-02-at-7.30.21-AM.png?resize=1024%2C794&#038;ssl=1\" alt=\"\" class=\"wp-image-6690\" style=\"width:637px;height:auto\" srcset=\"https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2025\/08\/Screenshot-2025-08-02-at-7.30.21-AM.png?resize=1024%2C794&amp;ssl=1 1024w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2025\/08\/Screenshot-2025-08-02-at-7.30.21-AM.png?resize=300%2C233&amp;ssl=1 300w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2025\/08\/Screenshot-2025-08-02-at-7.30.21-AM.png?resize=768%2C596&amp;ssl=1 768w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2025\/08\/Screenshot-2025-08-02-at-7.30.21-AM.png?w=1338&amp;ssl=1 1338w\" sizes=\"auto, (max-width: 1000px) 100vw, 1000px\" \/><\/figure>\n<\/div>\n\n\n<p>It&#8217;s likely what the browser itself does when it needs to apply styling to only certain parts of text, like it does when you use the <strong>Find<em> <\/em><\/strong>feature baked into browsers.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large is-resized\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"798\" src=\"https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2025\/08\/Screenshot-2025-08-02-at-7.32.03-AM.png?resize=1024%2C798&#038;ssl=1\" alt=\"\" class=\"wp-image-6691\" style=\"width:546px;height:auto\" srcset=\"https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2025\/08\/Screenshot-2025-08-02-at-7.32.03-AM.png?resize=1024%2C798&amp;ssl=1 1024w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2025\/08\/Screenshot-2025-08-02-at-7.32.03-AM.png?resize=300%2C234&amp;ssl=1 300w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2025\/08\/Screenshot-2025-08-02-at-7.32.03-AM.png?resize=768%2C599&amp;ssl=1 768w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2025\/08\/Screenshot-2025-08-02-at-7.32.03-AM.png?w=1380&amp;ssl=1 1380w\" sizes=\"auto, (max-width: 1000px) 100vw, 1000px\" \/><\/figure>\n<\/div>\n\n\n<p>Here&#8217;s that demo:<\/p>\n\n\n\n<div class=\"wp-block-cp-codepen-gutenberg-embed-block cp_embed_wrapper\"><iframe id=\"cp_embed_yyYMzKG\" src=\"\/\/codepen.io\/editor\/anon\/embed\/yyYMzKG?height=485&amp;theme-id=1&amp;slug-hash=yyYMzKG&amp;default-tab=js,result\" height=\"485\" scrolling=\"no\" frameborder=\"0\" allowfullscreen allowpaymentrequest name=\"CodePen Embed yyYMzKG\" title=\"CodePen Embed yyYMzKG\" class=\"cp_embed_iframe\" style=\"width:100%;overflow:hidden\">CodePen Embed Fallback<\/iframe><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Why is this useful?<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Having the ability to target and style text <em>without<\/em> needing to touch the DOM <em>at all<\/em> is interesting. <span style=\"box-sizing: border-box; margin: 0px; padding: 0px;\">Sometimes, DOM APIs are criticized for being slow, so being able to avoid that might be advantageous, particularly if you have to do it&nbsp;<em>a lo<\/em><\/span><em>t.<\/em> <\/li>\n\n\n\n<li>Adding and removing <code>&lt;span&gt;<\/code>s, aside from potentially being &#8220;slow&#8221; affects the DOM structure and thus might affect other CSS and JavaScript deal with the DOM.<\/li>\n\n\n\n<li>DOM weight can be a performance concern on web pages. Too much DOM, recalcs can be very &#8220;expensive&#8221; and the UX on the page can suffer with things like slow animations and scrolling.<\/li>\n<\/ul>\n\n\n\n<p>Here&#8217;s a GitHub PR page with just 17 changed files. The page has over 4,500 spans on it already used in things like colorizing the diffs and syntax highlighting. That&#8217;s decently heavy, and it can definitely get worse.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"641\" src=\"https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2025\/08\/CleanShot-2025-08-02-at-07.38.54%402x.png?resize=1024%2C641&#038;ssl=1\" alt=\"\" class=\"wp-image-6693\" srcset=\"https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2025\/08\/CleanShot-2025-08-02-at-07.38.54%402x.png?resize=1024%2C641&amp;ssl=1 1024w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2025\/08\/CleanShot-2025-08-02-at-07.38.54%402x.png?resize=300%2C188&amp;ssl=1 300w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2025\/08\/CleanShot-2025-08-02-at-07.38.54%402x.png?resize=768%2C481&amp;ssl=1 768w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2025\/08\/CleanShot-2025-08-02-at-07.38.54%402x.png?resize=1536%2C961&amp;ssl=1 1536w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2025\/08\/CleanShot-2025-08-02-at-07.38.54%402x.png?resize=2048%2C1282&amp;ssl=1 2048w\" sizes=\"auto, (max-width: 1000px) 100vw, 1000px\" \/><\/figure>\n\n\n\n<p>I&#8217;m sure there are lots more reasons this API exists, but these are just a few reasons that come to mind right away.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Doing a Bit More (Search Example)<\/h2>\n\n\n\n<p>Making a <code>new Highlight()<\/code> accepts <em>multiple<\/em> Ranges. Meaning a single <code>::highlight()<\/code> in CSS can apply to many Ranges of text. This would be useful if we built our own search feature onto a page. If search was a crucial feature of a web app you are building, I can easily see building out your own UI for it rather than relying on the built-in browser feature. <\/p>\n\n\n\n<p>This time, let&#8217;s let the word(s) we&#8217;re going to find in the text come from the user:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">label<\/span>&gt;<\/span>\n  Search the text below\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">input<\/span> <span class=\"hljs-attr\">type<\/span>=<span class=\"hljs-string\">\"search\"<\/span> <span class=\"hljs-attr\">value<\/span>=<span class=\"hljs-string\">\"oven\"<\/span> <span class=\"hljs-attr\">id<\/span>=<span class=\"hljs-string\">\"searchTerm\"<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">label<\/span>&gt;<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Then we&#8217;ll listen for changes:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-built_in\">window<\/span>.searchTerm.addEventListener(<span class=\"hljs-string\">\"input\"<\/span>, (e) =&gt; {\n  doSearch(e.target.value.toLowerCase());\n});<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Note we&#8217;re passing the value typed in to a function, and we&#8217;re lower-casing it as we do, as search is generally most useful when it&#8217;s case insensitive. <\/p>\n\n\n\n<p>Our <code>doSearch<\/code> function will then accept that search term and run a RegEx across all the text:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-keyword\">const<\/span> regex = <span class=\"hljs-keyword\">new<\/span> <span class=\"hljs-built_in\">RegExp<\/span>(searchTerm, <span class=\"hljs-string\">\"gi\"<\/span>);<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>What we need is an Array of indexes for all the found instances of the text. It&#8217;s a bit of a mouthful of code, but here you go:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-keyword\">const<\/span> indexes = &#91;...theTextContent.matchAll(<span class=\"hljs-keyword\">new<\/span> <span class=\"hljs-built_in\">RegExp<\/span>(searchTerm, <span class=\"hljs-string\">'gi'<\/span>))].map(<span class=\"hljs-function\"><span class=\"hljs-params\">a<\/span> =&gt;<\/span> a.index);<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>With that Array of indexes, we can loop over them creating Ranges, then send <em>all<\/em> the Ranges to a new Highlight.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-keyword\">const<\/span> arrayOfRanges = &#91;];\n\nindexes.forEach(<span class=\"hljs-function\"><span class=\"hljs-params\">matchIndex<\/span> =&gt;<\/span> {\n  <span class=\"hljs-comment\">\/\/ Make a \"Range\" out of the index values.<\/span>\n  <span class=\"hljs-keyword\">const<\/span> searchRange = <span class=\"hljs-keyword\">new<\/span> Range();\n  searchRange.setStart(par, matchIndex);\n  searchRange.setEnd(par, matchIndex + searchTerm.length);\n\n  arrayOfRanges.push(searchRange);\n})\n\n<span class=\"hljs-keyword\">const<\/span> ourHighlight = <span class=\"hljs-keyword\">new<\/span> Highlight(...arrayOfRanges);\nCSS.highlights.set(<span class=\"hljs-string\">\"search-results\"<\/span>, ourHighlight);<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>All together, it makes a functional search experience:<\/p>\n\n\n\n<div class=\"wp-block-cp-codepen-gutenberg-embed-block cp_embed_wrapper\"><iframe id=\"cp_embed_NPGbbJZ\" src=\"\/\/codepen.io\/editor\/anon\/embed\/NPGbbJZ?height=450&amp;theme-id=1&amp;slug-hash=NPGbbJZ&amp;default-tab=js,result\" height=\"450\" scrolling=\"no\" frameborder=\"0\" allowfullscreen allowpaymentrequest name=\"CodePen Embed NPGbbJZ\" title=\"CodePen Embed NPGbbJZ\" class=\"cp_embed_iframe\" style=\"width:100%;overflow:hidden\">CodePen Embed Fallback<\/iframe><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">For Syntax Highlighting<\/h2>\n\n\n\n<p>It feels like syntax highlighting code is a pretty good use case for this API. Andr\u00e9 Ruffert has already taken that idea and ran with it, making a <a href=\"https:\/\/andreruffert.github.io\/syntax-highlight-element\/\"><code>&lt;syntax-highlight><\/code> Web Component<\/a> which uses <a href=\"https:\/\/andreruffert.github.io\/syntax-highlight-element\/\">Prism.js<\/a> by Lea Verou to tokenize the code, but then doesn&#8217;t apply <code>&lt;span><\/code>s like out-of-the-box Prism does, it uses this custom highlight API instead.<\/p>\n\n\n\n<p>Example:<\/p>\n\n\n\n<div class=\"wp-block-cp-codepen-gutenberg-embed-block cp_embed_wrapper\"><iframe id=\"cp_embed_GgpWMVy\" src=\"\/\/codepen.io\/editor\/anon\/embed\/GgpWMVy?height=450&amp;theme-id=1&amp;slug-hash=GgpWMVy&amp;default-tab=js,result\" height=\"450\" scrolling=\"no\" frameborder=\"0\" allowfullscreen allowpaymentrequest name=\"CodePen Embed GgpWMVy\" title=\"CodePen Embed GgpWMVy\" class=\"cp_embed_iframe\" style=\"width:100%;overflow:hidden\">CodePen Embed Fallback<\/iframe><\/div>\n\n\n\n<p>I think this is awesome, but it&#8217;s noteworthy that this API is <em>only<\/em> possible client-side. And for something like syntax highlighting, that can mean a delay between seeing the code and having the syntax-highlighting &#8220;pop in&#8221;. I admit I prefer server-side rendered syntax highlighting when possible. Meaning if you can serve a bunch of <code>&lt;span&gt;<\/code>s from the server in code like this (and it doesn&#8217;t affect performance or accessibility badly) then that&#8217;s probably better. <\/p>\n\n\n\n<p>I also admit I&#8217;m still somewhat obsessed with <a href=\"https:\/\/blog.glyphdrawing.club\/font-with-built-in-syntax-highlighting\/\">fonts with built-in syntax highlighting<\/a>, which feels like untapped territory for font foundries to jump on.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n<ol class=\"wp-block-footnotes\"><li id=\"18958d55-4f3c-4d44-9460-f364498054cf\">I&#8217;m glad I <a href=\"https:\/\/frontendmasters.com\/blog\/firstchild-can-be-white-space\/\">learned about <code>.firstChild<\/code><\/a> the other day, and how it selects the <code>textNode<\/code> of otherwise childless text elements <a href=\"#18958d55-4f3c-4d44-9460-f364498054cf-link\" aria-label=\"Jump to footnote reference 1\">\u21a9\ufe0e<\/a><\/li><\/ol>\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>You can get your hands on ranges of text in JavaScript, then apply a named &#8220;highlight&#8221; on them, so you can style that range in CSS with no other selector necessary.<\/p>\n","protected":false},"author":1,"featured_media":6707,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"sig_custom_text":"","sig_image_type":"featured-image","sig_custom_image":0,"sig_is_disabled":false,"inline_featured_image":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"[{\"content\":\"I'm glad I <a href=\\\"https:\/\/frontendmasters.com\/blog\/firstchild-can-be-white-space\/\\\">learned about <code>.firstChild<\/code><\/a> the other day, and how it selects the <code>textNode<\/code> of otherwise childless text elements\",\"id\":\"18958d55-4f3c-4d44-9460-f364498054cf\"}]"},"categories":[1],"tags":[380,3,379],"class_list":["post-6686","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-blog-post","tag-highlight","tag-javascript","tag-range-2"],"acf":[],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2025\/08\/Using-the-Custom-Highlight-API.jpg?fit=1140%2C676&ssl=1","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/posts\/6686","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/comments?post=6686"}],"version-history":[{"count":7,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/posts\/6686\/revisions"}],"predecessor-version":[{"id":6708,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/posts\/6686\/revisions\/6708"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/media\/6707"}],"wp:attachment":[{"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/media?parent=6686"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/categories?post=6686"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/tags?post=6686"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}