{"id":261,"date":"2021-02-28T09:26:13","date_gmt":"2021-02-28T09:26:13","guid":{"rendered":"https:\/\/asdfghjkl.me.uk\/blog\/?p=261"},"modified":"2022-08-19T18:27:35","modified_gmt":"2022-08-19T17:27:35","slug":"click-play","status":"publish","type":"post","link":"https:\/\/asdfghjkl.me.uk\/blog\/click-play\/","title":{"rendered":"Creating click-to-play YouTube videos in JS and CSS that don&#8217;t load anything until they&#8217;re needed"},"content":{"rendered":"\n<p>Let's be honest: streaming video is kinda hard. If you want to embed a video on your website, you're going to need it in multiple formats to support all the major browsers, and you'll probably want each of those in multiple resolutions too so your visitors with slower connections or less powerful devices aren't left out in the cold.<\/p>\n\n\n\n<p>You can always roll your own native HTML5 player with a bit of messing about in ffmpeg and a DASH manifest, or go ready-made and embed JWPlayer or Video.js. Of course, since video can be pretty heavy, you might want to host the files from a CDN too.<\/p>\n\n\n\n<p>But I just want a simple little website for my personal portfolio, and since I don't expect many visitors, it's just not worth the effort. I'm not the biggest Google fan but it's undeniable that YouTube have built a very competent platform, and it's very tempting to just throw a couple iframes up and call it a day. But my website is lightweight and fast (and I feel smug about it): it doesn't <em>need<\/em> to pull in any external resources, and I don't want Google tracking all of my visitors before they've even watched a video. With a few simple changes, we can make our embeds only load when they're clicked, and give them nice thumbnails and buttons to boot.<\/p>\n\n\n\n<p>We start by creating our placeholder player:<\/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 shcb-code-table shcb-line-numbers shcb-wrap-lines\"><span class='shcb-loc'><span><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"youtube overlay\"<\/span> <span class=\"hljs-attr\">data-id<\/span>=<span class=\"hljs-string\">\"xi7U1afxMQY\"<\/span>&gt;<\/span>\n<\/span><\/span><span class='shcb-loc'><span>\t<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">a<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"play\"<\/span> <span class=\"hljs-attr\">href<\/span>=<span class=\"hljs-string\">\"https:\/\/youtube.com\/watch?v=xi7U1afxMQY\"<\/span> <span class=\"hljs-attr\">aria-label<\/span>=<span class=\"hljs-string\">\"Play video\"<\/span>&gt;<\/span>\n<\/span><\/span><span class='shcb-loc'><span>\t\t<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"thumbnail-container\"<\/span>&gt;<\/span>\n<\/span><\/span><span class='shcb-loc'><span>\t\t\t<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">picture<\/span>&gt;<\/span>\n<\/span><\/span><span class='shcb-loc'><span>\t\t\t\t<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">source<\/span> <span class=\"hljs-attr\">srcset<\/span>=<span class=\"hljs-string\">\"thumbnails\/mountains.avif 960w, thumbnails\/mountains-2x.avif 1920w\"<\/span> <span class=\"hljs-attr\">type<\/span>=<span class=\"hljs-string\">\"image\/avif\"<\/span>&gt;<\/span>\n<\/span><\/span><span class='shcb-loc'><span>\t\t\t\t<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">img<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"thumbnail\"<\/span> <span class=\"hljs-attr\">srcset<\/span>=<span class=\"hljs-string\">\"thumbnails\/mountains.jpg 960w, thumbnails\/mountains-2x.jpg 1920w\"<\/span> <span class=\"hljs-attr\">src<\/span>=<span class=\"hljs-string\">\"thumbnails\/mountains.jpg\"<\/span> <span class=\"hljs-attr\">alt<\/span>=<span class=\"hljs-string\">\"Life in the Mountains\"<\/span> <span class=\"hljs-attr\">loading<\/span>=<span class=\"hljs-string\">\"lazy\"<\/span>&gt;<\/span>\n<\/span><\/span><span class='shcb-loc'><span>\t\t\t<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">picture<\/span>&gt;<\/span>\n<\/span><\/span><span class='shcb-loc'><span>\t\t\t<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">span<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"duration\"<\/span>&gt;<\/span>8:48<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">span<\/span>&gt;<\/span>\n<\/span><\/span><span class='shcb-loc'><span>\t\t\t<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"play-overlay\"<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n<\/span><\/span><span class='shcb-loc'><span>\t\t<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n<\/span><\/span><span class='shcb-loc'><span>\t<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">a<\/span>&gt;<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n<\/span><\/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>The ID of the video is stored in the <code>data-id<\/code> attribute, which we'll use later to insert the iframe. Since we'll need Javascript for this, the <code>play<\/code> link contains the full URL so non-JS users can click through to watch it directly on YouTube. We include a thumbnail, in JPG for compatibility and AVIF for better compression on modern browsers (<a href=\"https:\/\/avif.io\">avif.io<\/a> is a great little online tool to convert all of your images, since as I write this it's rarely supported by image editors), and in two resolutions (960px and 1920px) as smaller screens don't need the full-size image. We also include the duration \u2013 why not? \u2013 and <code>play-overlay<\/code> will hold a play button icon.<\/p>\n\n\n\n<p>We can now apply some CSS:<\/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 shcb-code-table shcb-line-numbers shcb-wrap-lines\"><span class='shcb-loc'><span><span class=\"hljs-selector-class\">.overlay<\/span> {\n<\/span><\/span><span class='shcb-loc'><span>\t<span class=\"hljs-attribute\">position<\/span>: relative;\n<\/span><\/span><span class='shcb-loc'><span>\t<span class=\"hljs-attribute\">width<\/span>: <span class=\"hljs-number\">100vw<\/span>;\n<\/span><\/span><span class='shcb-loc'><span>\t<span class=\"hljs-attribute\">height<\/span>: <span class=\"hljs-built_in\">calc<\/span>((<span class=\"hljs-number\">100vw<\/span>\/<span class=\"hljs-number\">16<\/span>)*<span class=\"hljs-number\">9<\/span>);\n<\/span><\/span><span class='shcb-loc'><span>\t<span class=\"hljs-attribute\">max-width<\/span>: <span class=\"hljs-number\">1920px<\/span>;\n<\/span><\/span><span class='shcb-loc'><span>\t<span class=\"hljs-attribute\">max-height<\/span>: <span class=\"hljs-number\">1080px<\/span>;\n<\/span><\/span><span class='shcb-loc'><span>}\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-selector-class\">.overlay<\/span> <span class=\"hljs-selector-class\">.thumbnail-container<\/span> {\n<\/span><\/span><span class='shcb-loc'><span>\t<span class=\"hljs-attribute\">position<\/span>: relative;\n<\/span><\/span><span class='shcb-loc'><span>}\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-selector-class\">.overlay<\/span> <span class=\"hljs-selector-class\">.thumbnail<\/span> {\n<\/span><\/span><span class='shcb-loc'><span>\t<span class=\"hljs-attribute\">display<\/span>: block;\n<\/span><\/span><span class='shcb-loc'><span>}\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-selector-class\">.overlay<\/span> <span class=\"hljs-selector-class\">.duration<\/span> {\n<\/span><\/span><span class='shcb-loc'><span>\t<span class=\"hljs-attribute\">position<\/span>: absolute;\n<\/span><\/span><span class='shcb-loc'><span>\t<span class=\"hljs-attribute\">z-index<\/span>: <span class=\"hljs-number\">2<\/span>;\n<\/span><\/span><span class='shcb-loc'><span>\t<span class=\"hljs-attribute\">right<\/span>: <span class=\"hljs-number\">0.5rem<\/span>;\n<\/span><\/span><span class='shcb-loc'><span>\t<span class=\"hljs-attribute\">bottom<\/span>: <span class=\"hljs-number\">0.5rem<\/span>;\n<\/span><\/span><span class='shcb-loc'><span>\t<span class=\"hljs-attribute\">padding<\/span>: <span class=\"hljs-number\">0.2rem<\/span> <span class=\"hljs-number\">0.4rem<\/span>;\n<\/span><\/span><span class='shcb-loc'><span>\t<span class=\"hljs-attribute\">background-color<\/span>: <span class=\"hljs-built_in\">rgba<\/span>(<span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0.6<\/span>);\n<\/span><\/span><span class='shcb-loc'><span>\t<span class=\"hljs-attribute\">color<\/span>: white;\n<\/span><\/span><span class='shcb-loc'><span>}\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-selector-class\">.overlay<\/span> <span class=\"hljs-selector-class\">.play-overlay<\/span> {\n<\/span><\/span><span class='shcb-loc'><span>\t<span class=\"hljs-attribute\">position<\/span>: absolute;\n<\/span><\/span><span class='shcb-loc'><span>\t<span class=\"hljs-attribute\">z-index<\/span>: <span class=\"hljs-number\">1<\/span>;\n<\/span><\/span><span class='shcb-loc'><span>\t<span class=\"hljs-attribute\">top<\/span>: <span class=\"hljs-number\">0<\/span>;\n<\/span><\/span><span class='shcb-loc'><span>\t<span class=\"hljs-attribute\">width<\/span>: <span class=\"hljs-number\">100%<\/span>;\n<\/span><\/span><span class='shcb-loc'><span>\t<span class=\"hljs-attribute\">height<\/span>: <span class=\"hljs-number\">100%<\/span>;\n<\/span><\/span><span class='shcb-loc'><span>\t<span class=\"hljs-attribute\">background<\/span>: <span class=\"hljs-built_in\">rgba<\/span>(<span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0.1<\/span>) <span class=\"hljs-built_in\">url<\/span>(<span class=\"hljs-string\">\"images\/arrow.svg\"<\/span>) no-repeat scroll center center \/ <span class=\"hljs-number\">3rem<\/span> <span class=\"hljs-number\">3rem<\/span>;\n<\/span><\/span><span class='shcb-loc'><span>\t<span class=\"hljs-attribute\">transition<\/span>: background-color <span class=\"hljs-number\">0.7s<\/span>;\n<\/span><\/span><span class='shcb-loc'><span>}\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-selector-class\">.overlay<\/span> <span class=\"hljs-selector-class\">.play-overlay<\/span><span class=\"hljs-selector-pseudo\">:hover<\/span> {\n<\/span><\/span><span class='shcb-loc'><span>\t<span class=\"hljs-attribute\">background-color<\/span>: <span class=\"hljs-built_in\">rgba<\/span>(<span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>);\n<\/span><\/span><span class='shcb-loc'><span>}\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-selector-class\">.overlay<\/span> <span class=\"hljs-selector-tag\">iframe<\/span> {\n<\/span><\/span><span class='shcb-loc'><span>\t<span class=\"hljs-attribute\">position<\/span>: absolute;\n<\/span><\/span><span class='shcb-loc'><span>\t<span class=\"hljs-attribute\">z-index<\/span>: <span class=\"hljs-number\">3<\/span>;\n<\/span><\/span><span class='shcb-loc'><span>\t<span class=\"hljs-attribute\">width<\/span>: <span class=\"hljs-number\">100%<\/span>;\n<\/span><\/span><span class='shcb-loc'><span>\t<span class=\"hljs-attribute\">height<\/span>: <span class=\"hljs-number\">100%<\/span>;\n<\/span><\/span><span class='shcb-loc'><span>}\n<\/span><\/span><\/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>On my site I've already set the width and height for the video's container, so I've just shown an example for <code>overlay<\/code> here, using <code>vw<\/code> units so it fills the viewport's width whether portrait or landscape. My thumbnails only go up to 1920x1080 so I've limited it to that in this example. Sorry 4K users! You can use a <code>calc<\/code> expression for the height to get the correct aspect ratio (here 16:9).<\/p>\n\n\n\n<p>On to positioning. Setting <code>position: relative<\/code> for the container means we can use absolute positioning for the iframe to fit to the thumbnail's size, and <code>position: relative<\/code> on the thumbnail's container and <code>display: block<\/code> on the thumbnail itself fits everything else to the thumbnail too. Duration sits in the bottom right with a little space to breathe. We set z-indexes so elements will stack in the correct order: thumbnail on the bottom, overlay above it, duration on top of that, and the iframe will cover everything once it's added.<\/p>\n\n\n\n<p>What remains is just little extras: the overlay slightly darkens the thumbnail until it's hovered over, and we take advantage of the <code>background<\/code> property allowing both colour and URL to drop a play button on top. The button is an SVG so simple you can paste the code into arrow.svg yourself:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml shcb-wrap-lines\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">svg<\/span> <span class=\"hljs-attr\">xmlns<\/span>=<span class=\"hljs-string\">\"http:\/\/www.w3.org\/2000\/svg\"<\/span> <span class=\"hljs-attr\">viewBox<\/span>=<span class=\"hljs-string\">\"0 0 100 100\"<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">polygon<\/span> <span class=\"hljs-attr\">points<\/span>=<span class=\"hljs-string\">\"0 0 100 50 0 100 0 0\"<\/span> <span class=\"hljs-attr\">style<\/span>=<span class=\"hljs-string\">\"fill:#fff\"<\/span>\/&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">svg<\/span>&gt;<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><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>Now all we need is a little JS to handle inserting the iframe when the placeholder is clicked \u2013 no JQuery required! Insert it just before the closing <code>&lt;\/body&gt;<\/code> tag so it runs once all the placeholders it'll be working on have loaded.<\/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 shcb-code-table shcb-line-numbers shcb-wrap-lines\"><span class='shcb-loc'><span><span class=\"hljs-built_in\">document<\/span>.querySelectorAll(<span class=\"hljs-string\">\".youtube\"<\/span>).forEach(<span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span>(<span class=\"hljs-params\">element<\/span>) <\/span>{\n<\/span><\/span><span class='shcb-loc'><span>\telement.querySelector(<span class=\"hljs-string\">\".play\"<\/span>).addEventListener(<span class=\"hljs-string\">\"click\"<\/span>, (event) =&gt; {\n<\/span><\/span><span class='shcb-loc'><span>\t\tevent.preventDefault();\n<\/span><\/span><span class='shcb-loc'><span>\t\tloadVideo(element);\n<\/span><\/span><span class='shcb-loc'><span>\t});\n<\/span><\/span><span class='shcb-loc'><span>});\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-keyword\">var<\/span> loadVideo = <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span>(<span class=\"hljs-params\">element<\/span>) <\/span>{\n<\/span><\/span><span class='shcb-loc'><span>\t<span class=\"hljs-keyword\">var<\/span> iframe = <span class=\"hljs-built_in\">document<\/span>.createElement(<span class=\"hljs-string\">\"iframe\"<\/span>);\n<\/span><\/span><span class='shcb-loc'><span>\tiframe.setAttribute(<span class=\"hljs-string\">\"src\"<\/span>, <span class=\"hljs-string\">\"https:\/\/www.youtube.com\/embed\/\"<\/span> + element.getAttribute(<span class=\"hljs-string\">\"data-id\"<\/span>) + <span class=\"hljs-string\">\"?autoplay=1\"<\/span>);\n<\/span><\/span><span class='shcb-loc'><span>\tiframe.setAttribute(<span class=\"hljs-string\">\"frameborder\"<\/span>, <span class=\"hljs-string\">\"0\"<\/span>);\n<\/span><\/span><span class='shcb-loc'><span>\tiframe.setAttribute(<span class=\"hljs-string\">\"allowfullscreen\"<\/span>, <span class=\"hljs-string\">\"1\"<\/span>);\n<\/span><\/span><span class='shcb-loc'><span>\tiframe.setAttribute(<span class=\"hljs-string\">\"allow\"<\/span>, <span class=\"hljs-string\">\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\"<\/span>);\n<\/span><\/span><span class='shcb-loc'><span>\telement.insertBefore(iframe, element.querySelector(<span class=\"hljs-string\">\".play\"<\/span>));\n<\/span><\/span><span class='shcb-loc'><span>};\n<\/span><\/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>The first function finds every placeholder on the page, adding a listener for each play button being clicked. Note that we use the <code>overlay<\/code> class for the CSS but <code>youtube<\/code> for the JS \u2013 this is so we can extend our code later to cover more platforms if we like, which would need different JS. When a visitor clicks play, it cancels the default action (navigating to the URL, which we included for non-JS users) and calls the <code>loadVideo<\/code> function, passing on the specific video they clicked.<\/p>\n\n\n\n<p>The <code>loadVideo<\/code> function puts together the iframe for the video embed, getting the ID from the container's <code>data-id<\/code> attribute. We use www.youtube-nocookie.com (the www is necessary!) as it pinkie promises not to set cookies until you play the video <em>(2022 edit - this URL seems to be commonly blocked by adblockers, so I've reverted it to the standard one)<\/em>, and set a few attributes to let mobile users rotate the screen, copy the link to their clipboard etc. Although we set it to autoplay since we've already clicked on the placeholder, it doesn't seem to work as I write this. I'm not sure why and they encourage you to embed their JS API instead, but that would sort of defeat the point. Finally, it inserts the iframe as the first element in the container, where it covers up the rest.<\/p>\n\n\n\n<p>If all goes well, you should now have something that looks like this (albeit functional):<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" loading=\"lazy\" width=\"855\" height=\"482\" src=\"https:\/\/asdfghjkl.me.uk\/blog\/wp-content\/uploads\/image.png\" alt=\"Completed placeholder for click-to-play video\" class=\"wp-image-266\" srcset=\"https:\/\/asdfghjkl.me.uk\/blog\/wp-content\/uploads\/image.png 855w, https:\/\/asdfghjkl.me.uk\/blog\/wp-content\/uploads\/image-300x169.png 300w, https:\/\/asdfghjkl.me.uk\/blog\/wp-content\/uploads\/image-768x433.png 768w, https:\/\/asdfghjkl.me.uk\/blog\/wp-content\/uploads\/image-624x352.png 624w\" sizes=\"(max-width: 855px) 100vw, 855px\" \/><\/figure>\n\n\n\n<p>You can also see it in action <a href=\"https:\/\/michaeldarling.uk\">on my website<\/a>. Thanks for reading!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Let's be honest: streaming video is kinda hard. If you want to embed a video on your website, you're going to need it in multiple formats to support all the major browsers, and you'll probably want each of those in multiple resolutions too so your visitors with slower connections or less powerful devices aren't left [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[11],"tags":[],"_links":{"self":[{"href":"https:\/\/asdfghjkl.me.uk\/blog\/wp-json\/wp\/v2\/posts\/261"}],"collection":[{"href":"https:\/\/asdfghjkl.me.uk\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/asdfghjkl.me.uk\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/asdfghjkl.me.uk\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/asdfghjkl.me.uk\/blog\/wp-json\/wp\/v2\/comments?post=261"}],"version-history":[{"count":15,"href":"https:\/\/asdfghjkl.me.uk\/blog\/wp-json\/wp\/v2\/posts\/261\/revisions"}],"predecessor-version":[{"id":342,"href":"https:\/\/asdfghjkl.me.uk\/blog\/wp-json\/wp\/v2\/posts\/261\/revisions\/342"}],"wp:attachment":[{"href":"https:\/\/asdfghjkl.me.uk\/blog\/wp-json\/wp\/v2\/media?parent=261"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/asdfghjkl.me.uk\/blog\/wp-json\/wp\/v2\/categories?post=261"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/asdfghjkl.me.uk\/blog\/wp-json\/wp\/v2\/tags?post=261"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}