{"id":671,"date":"2024-01-29T13:12:20","date_gmt":"2024-01-29T19:12:20","guid":{"rendered":"https:\/\/frontendmasters.com\/blog\/?p=671"},"modified":"2024-01-29T15:54:08","modified_gmt":"2024-01-29T21:54:08","slug":"glowing-hover-effect","status":"publish","type":"post","link":"https:\/\/frontendmasters.com\/blog\/glowing-hover-effect\/","title":{"rendered":"How To Build a Glowing Hover Effect that Follows the Pointer"},"content":{"rendered":"\n<p>One of the <a href=\"https:\/\/codepen.io\/2023\/popular\/pens\/10\">Top Pens of 2023<\/a> was this <a href=\"https:\/\/codepen.io\/inescodes\/pen\/PoxMyvX\">Glowy Hover Effect<\/a> by Ines. When I was <a href=\"https:\/\/www.instagram.com\/p\/C2a6QcVtKkZ\/\">taking a look at it<\/a>, it finally clicked how it works. In a nutshell, there are <em>two copies<\/em> of the same HTML layered on top of one another. The top one has a fancy colors and such, but it ultimately &#8220;masked&#8221; such that you can only see part of it at a time. As you move the pointer around, the mask moves with it, making it look like the glowing is happening wherever the pointer is.<\/p>\n\n\n\n<p>Let&#8217;s do it step by step. And again, this is just my own explanation of how <a href=\"https:\/\/codepen.io\/inescodes\">Ines<\/a> pulled this off. <\/p>\n\n\n\n<h2 class=\"wp-block-heading\">1) Duplicate and Hide Another Layer of HTML<\/h2>\n\n\n\n<p>To keep this simple, let&#8217;s say we&#8217;re dealing with a single Card element.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"560\" src=\"https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2024\/01\/Screenshot-2024-01-29-at-10.39.39%E2%80%AFAM.png?resize=1024%2C560&#038;ssl=1\" alt=\"\" class=\"wp-image-674\" srcset=\"https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2024\/01\/Screenshot-2024-01-29-at-10.39.39%E2%80%AFAM.png?resize=1024%2C560&amp;ssl=1 1024w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2024\/01\/Screenshot-2024-01-29-at-10.39.39%E2%80%AFAM.png?resize=300%2C164&amp;ssl=1 300w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2024\/01\/Screenshot-2024-01-29-at-10.39.39%E2%80%AFAM.png?resize=768%2C420&amp;ssl=1 768w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2024\/01\/Screenshot-2024-01-29-at-10.39.39%E2%80%AFAM.png?resize=1536%2C840&amp;ssl=1 1536w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2024\/01\/Screenshot-2024-01-29-at-10.39.39%E2%80%AFAM.png?w=1562&amp;ssl=1 1562w\" sizes=\"auto, (max-width: 1000px) 100vw, 1000px\" \/><\/figure>\n\n\n\n<p>Our job is to duplicate the HTML that produces this, and place it directly on top of the original. <\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" 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\">main<\/span> <span class=\"hljs-attr\">id<\/span>=<span class=\"hljs-string\">\"main\"<\/span>&gt;<\/span>\n\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"card\"<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">h2<\/span>&gt;<\/span>Lorem ipsum dolor sit.<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">h2<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">p<\/span>&gt;<\/span>Lorem ipsum dolor sit amet consectetur adipisicing elit. Reprehenderit nobis veniam sit sint est temporibus eligendi neque ducimus doloribus facere doloremque, vel accusamus, eos ab iste. Eveniet atque alias consequatur.<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">p<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">button<\/span>&gt;<\/span>Read More<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">button<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"overlay\"<\/span> <span class=\"hljs-attr\">aria-hidden<\/span>=<span class=\"hljs-string\">\"true\"<\/span>&gt;<\/span>\n    <span class=\"hljs-comment\">&lt;!-- duplicate will go here --&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">main<\/span>&gt;<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><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>Above we have the original HTML, and a place to put the duplicated HTML. We can ensure the duplicate is exactly on top, in this setup, like:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-tag\">main<\/span> {\n  <span class=\"hljs-attribute\">position<\/span>: relative;\n}\n\n<span class=\"hljs-selector-class\">.overlay<\/span> {\n  <span class=\"hljs-attribute\">position<\/span>: absolute;\n  <span class=\"hljs-attribute\">inset<\/span>: <span class=\"hljs-number\">0<\/span>;\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Then we&#8217;ll do the actual duplication like:<\/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-keyword\">const<\/span> main = <span class=\"hljs-built_in\">document<\/span>.querySelector(<span class=\"hljs-string\">\"#main\"<\/span>);\n<span class=\"hljs-keyword\">const<\/span> content = main.querySelector(<span class=\"hljs-string\">\":scope &gt; *\"<\/span>);\n<span class=\"hljs-keyword\">const<\/span> clone = content.cloneNode(<span class=\"hljs-literal\">true<\/span>);\n<span class=\"hljs-keyword\">const<\/span> overlay = <span class=\"hljs-built_in\">document<\/span>.querySelector(<span class=\"hljs-string\">\".overlay\"<\/span>);\noverlay.insertAdjacentElement(<span class=\"hljs-string\">\"beforeend\"<\/span>, clone);<\/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>I chose to use <code>cloneNode<\/code> here in case we wanted do manipulate the HTML in any way before inserting. We&#8217;re not really doing that here, so we could have used <code>innerHTML<\/code> and <code>insertAdjacentHTML<\/code> instead, but whatever, always multiple ways to crack an egg.<\/p>\n\n\n\n<p>Now we&#8217;ve got our two copies.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"683\" src=\"https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2024\/01\/layers.jpg?resize=1024%2C683&#038;ssl=1\" alt=\"\" class=\"wp-image-675\" srcset=\"https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2024\/01\/layers.jpg?resize=1024%2C683&amp;ssl=1 1024w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2024\/01\/layers.jpg?resize=300%2C200&amp;ssl=1 300w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2024\/01\/layers.jpg?resize=768%2C512&amp;ssl=1 768w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2024\/01\/layers.jpg?w=1200&amp;ssl=1 1200w\" sizes=\"auto, (max-width: 1000px) 100vw, 1000px\" \/><\/figure>\n\n\n\n<p>See how I&#8217;ve made the top layer all full of colors. That&#8217;s the one we&#8217;ll reveal only parts of to achieve this effect.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">2) Hide the Top Layer in a Mask<\/h2>\n\n\n\n<p>That whole top layer is in an <code>&lt;div class=\"overlay\" aria-hidden=\"true\"&gt;<\/code>. The <code>aria-hidden<\/code> attribute is there because that bit of HTML should be entirely ignored by screen readers. <\/p>\n\n\n\n<p>The overlay class is what gives us an opportunity to do fancy styling.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-class\">.card<\/span> {\n  <span class=\"hljs-comment\">\/* default styling *\/<\/span>\n  <span class=\"hljs-attribute\">max-width<\/span>: <span class=\"hljs-number\">50ch<\/span>;\n  <span class=\"hljs-attribute\">border<\/span>: <span class=\"hljs-number\">2px<\/span> solid <span class=\"hljs-number\">#333<\/span>;\n  <span class=\"hljs-attribute\">padding<\/span>: <span class=\"hljs-number\">3rem<\/span>;\n  <span class=\"hljs-attribute\">border-radius<\/span>: <span class=\"hljs-number\">0.5rem<\/span>;\n\n  <span class=\"hljs-comment\">\/* hover mask styling *\/<\/span>\n  .overlay &amp; {\n    <span class=\"hljs-attribute\">background<\/span>: <span class=\"hljs-built_in\">linear-gradient<\/span>(\n      <span class=\"hljs-number\">45deg<\/span>,\n      hsl(<span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">100%<\/span>, <span class=\"hljs-number\">50%<\/span>),\n      <span class=\"hljs-built_in\">hsl<\/span>(<span class=\"hljs-number\">60<\/span>, <span class=\"hljs-number\">100%<\/span>, <span class=\"hljs-number\">50%<\/span>),\n      <span class=\"hljs-built_in\">hsl<\/span>(<span class=\"hljs-number\">120<\/span>, <span class=\"hljs-number\">100%<\/span>, <span class=\"hljs-number\">50%<\/span>),\n      <span class=\"hljs-built_in\">hsl<\/span>(<span class=\"hljs-number\">180<\/span>, <span class=\"hljs-number\">100%<\/span>, <span class=\"hljs-number\">50%<\/span>),\n      <span class=\"hljs-built_in\">hsl<\/span>(<span class=\"hljs-number\">240<\/span>, <span class=\"hljs-number\">100%<\/span>, <span class=\"hljs-number\">50%<\/span>),\n      <span class=\"hljs-built_in\">hsl<\/span>(<span class=\"hljs-number\">300<\/span>, <span class=\"hljs-number\">100%<\/span>, <span class=\"hljs-number\">50%<\/span>),\n      <span class=\"hljs-built_in\">hsl<\/span>(<span class=\"hljs-number\">360<\/span>, <span class=\"hljs-number\">100%<\/span>, <span class=\"hljs-number\">50%<\/span>)\n    );\n    <span class=\"hljs-attribute\">border-color<\/span>: white;\n  }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The trick to mostly hide the overlay element is the masking. But we&#8217;ll also make sure it&#8217;s entirely visual and doesn&#8217;t snag any clicks or anything.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-class\">.overlay<\/span> {\n  <span class=\"hljs-attribute\">position<\/span>: absolute;\n  <span class=\"hljs-attribute\">inset<\/span>: <span class=\"hljs-number\">0<\/span>;\n\n  <span class=\"hljs-comment\">\/* visual only, don't steal clicks or interactions *\/<\/span>\n  <span class=\"hljs-attribute\">pointer-events<\/span>: none;\n  <span class=\"hljs-attribute\">user-select<\/span>: none;\n\n  <span class=\"hljs-comment\">\/* JavaScript will make this visible. This ensures progressive enhancement *\/<\/span>\n  <span class=\"hljs-attribute\">opacity<\/span>: <span class=\"hljs-built_in\">var<\/span>(--opacity, <span class=\"hljs-number\">0<\/span>);\n\n  <span class=\"hljs-attribute\">-webkit-mask<\/span>: <span class=\"hljs-built_in\">radial-gradient<\/span>(\n    <span class=\"hljs-number\">25rem<\/span> <span class=\"hljs-number\">25rem<\/span> at var(--x) <span class=\"hljs-built_in\">var<\/span>(--y),\n    <span class=\"hljs-number\">#000<\/span> <span class=\"hljs-number\">1%<\/span>,\n    transparent <span class=\"hljs-number\">50%<\/span>\n  );\n  <span class=\"hljs-attribute\">mask<\/span>: <span class=\"hljs-built_in\">radial-gradient<\/span>(\n    <span class=\"hljs-number\">25rem<\/span> <span class=\"hljs-number\">25rem<\/span> at var(--x) <span class=\"hljs-built_in\">var<\/span>(--y),\n    <span class=\"hljs-number\">#000<\/span> <span class=\"hljs-number\">1%<\/span>,\n    transparent <span class=\"hljs-number\">50%<\/span>\n  );\n\n  <span class=\"hljs-comment\">\/* smooooooth *\/<\/span>\n  <span class=\"hljs-attribute\">transition<\/span>: <span class=\"hljs-number\">400ms<\/span> mask ease;\n  <span class=\"hljs-attribute\">will-change<\/span>: mask;\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>So now we can only see a <em>part<\/em> of the overlay, a circular 25rem bit, as per the mask:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"529\" src=\"https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2024\/01\/Screenshot-2024-01-29-at-11.07.32%E2%80%AFAM.png?resize=1024%2C529&#038;ssl=1\" alt=\"\" class=\"wp-image-676\" srcset=\"https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2024\/01\/Screenshot-2024-01-29-at-11.07.32%E2%80%AFAM.png?resize=1024%2C529&amp;ssl=1 1024w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2024\/01\/Screenshot-2024-01-29-at-11.07.32%E2%80%AFAM.png?resize=300%2C155&amp;ssl=1 300w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2024\/01\/Screenshot-2024-01-29-at-11.07.32%E2%80%AFAM.png?resize=768%2C397&amp;ssl=1 768w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2024\/01\/Screenshot-2024-01-29-at-11.07.32%E2%80%AFAM.png?w=1498&amp;ssl=1 1498w\" sizes=\"auto, (max-width: 1000px) 100vw, 1000px\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">3) Positioning the Mask<\/h2>\n\n\n\n<p>But how does it know <em>where<\/em> to put the center of that mask? Well note the <code>var(--x) var(--y)<\/code> coordinates! Those are set in JavaScript:<\/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> applyOverlayMask = <span class=\"hljs-function\">(<span class=\"hljs-params\">e<\/span>) =&gt;<\/span> {\n  <span class=\"hljs-keyword\">const<\/span> overlayEl = e.currentTarget;\n  <span class=\"hljs-keyword\">const<\/span> x = e.pageX - main.offsetLeft;\n  <span class=\"hljs-keyword\">const<\/span> y = e.pageY - main.offsetTop;\n  overlayEl.style = <span class=\"hljs-string\">`--opacity: 1; --x: <span class=\"hljs-subst\">${x}<\/span>px; --y:<span class=\"hljs-subst\">${y}<\/span>px;`<\/span>;\n};\n\n<span class=\"hljs-built_in\">document<\/span>.body.addEventListener(<span class=\"hljs-string\">\"pointermove\"<\/span>, applyOverlayMask);<\/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>Now it follows the pointer around.<\/p>\n\n\n\n\t\t<figure class=\"wp-block-jetpack-videopress jetpack-videopress-player\" style=\"\" >\n\t\t\t<div class=\"jetpack-videopress-player__wrapper\"> <iframe title=\"VideoPress Video Player\" aria-label='VideoPress Video Player' width='500' height='257' src='https:\/\/videopress.com\/embed\/eJpSXqpz?cover=1&amp;autoPlay=0&amp;controls=1&amp;loop=0&amp;muted=0&amp;persistVolume=1&amp;playsinline=0&amp;preloadContent=metadata&amp;useAverageColor=1&amp;hd=0' frameborder='0' allowfullscreen data-resize-to-parent=\"true\" allow='clipboard-write'><\/iframe><script src='https:\/\/v0.wordpress.com\/js\/next\/videopress-iframe.js?m=1674852142'><\/script><\/div>\n\t\t\t\n\t\t\t\n\t\t<\/figure>\n\t\t\n\n\n<h2 class=\"wp-block-heading\">That&#8217;s the effect! Demo time.<\/h2>\n\n\n\n<div class=\"wp-block-cp-codepen-gutenberg-embed-block cp_embed_wrapper\"><iframe id=\"cp_embed_LYaOeVM\" src=\"\/\/codepen.io\/anon\/embed\/LYaOeVM?height=550&amp;theme-id=47434&amp;slug-hash=LYaOeVM&amp;default-tab=result\" height=\"550\" scrolling=\"no\" frameborder=\"0\" allowfullscreen allowpaymentrequest name=\"CodePen Embed LYaOeVM\" title=\"CodePen Embed LYaOeVM\" class=\"cp_embed_iframe\" style=\"width:100%;overflow:hidden\">CodePen Embed Fallback<\/iframe><\/div>\n","protected":false},"excerpt":{"rendered":"<p>One of the Top Pens of 2023 was this Glowy Hover Effect by Ines. When I was taking a look at it, it finally clicked how it works. In a nutshell, there are two copies of the same HTML layered on top of one another. The top one has a fancy colors and such, but [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":677,"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":""},"categories":[1],"tags":[90,3],"class_list":["post-671","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-blog-post","tag-hover","tag-javascript"],"acf":[],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2024\/01\/facy-hover-thumb.jpg?fit=1000%2C500&ssl=1","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/posts\/671","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=671"}],"version-history":[{"count":7,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/posts\/671\/revisions"}],"predecessor-version":[{"id":686,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/posts\/671\/revisions\/686"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/media\/677"}],"wp:attachment":[{"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/media?parent=671"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/categories?post=671"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/tags?post=671"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}