{"componentChunkName":"component---node-modules-narative-gatsby-theme-novela-src-templates-articles-template-tsx","path":"/blog/page/2","webpackCompilationHash":"98ad53f8c1f4a6cb2faa","result":{"pageContext":{"isCreatedByStatefulCreatePages":false,"basePath":"/blog","skip":6,"limit":6,"group":[{"node":{"id":"bef10cf7-43ca-5296-982e-96b6cf4bede7","slug":"/blog/did-you-know-responsive-images-require-just-an-image-tag-and-two-attributes","title":"Did You Know Responsive Images Require Just an Image Tag and Two Attributes?","author":"Marcus Wood","date":"September 10th, 2017","dateForSEO":"2017-09-10T00:00:00.000Z","timeToRead":3,"excerpt":"Web performance matters. Studies show that 40 percent of your visitors will abandon your page if it takes more than three seconds to load.","body":"function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }\n\nfunction _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }\n\nfunction _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }\n\n/* @jsx mdx */\nvar _frontmatter = {\n  \"title\": \"Did You Know Responsive Images Require Just an Image Tag and Two Attributes?\",\n  \"author\": \"Marcus Wood\",\n  \"date\": \"2017-09-10T00:00:00.000Z\",\n  \"hero\": \"./images/hero.jpg\",\n  \"excerpt\": \"Web performance matters. Studies show that 40 percent of your visitors will abandon your page if it takes more than three seconds to load.\"\n};\n\nvar makeShortcode = function makeShortcode(name) {\n  return function MDXDefaultShortcode(props) {\n    console.warn(\"Component \" + name + \" was not imported, exported, or provided by MDXProvider as global scope\");\n    return mdx(\"div\", props);\n  };\n};\n\nvar layoutProps = {\n  _frontmatter: _frontmatter\n};\nvar MDXLayout = \"wrapper\";\nreturn function MDXContent(_ref) {\n  var components = _ref.components,\n      props = _objectWithoutProperties(_ref, [\"components\"]);\n\n  return mdx(MDXLayout, _extends({}, layoutProps, props, {\n    components: components,\n    mdxType: \"MDXLayout\"\n  }), mdx(\"p\", null, \"Web performance matters. \", mdx(\"a\", _extends({\n    parentName: \"p\"\n  }, {\n    \"href\": \"https://blog.kissmetrics.com/loading-time/\"\n  }), \"Studies show\"), \" that 40 percent of your visitors will abandon your page if it takes more than three seconds to load. If you are developing a new site or trying to make your current one faster, optimizing images and enabling the browser to choose the right image depending on the device and screen size will yield the most impressive gains. We\\u2019ll be using Cloudinary, a cloud-based image management solution to optimize, host, transform, and create responsive images.\\nCloudinary offers a variety of ways to optimize the images on your website. Their convenient API allows you to make transformations to images by using parameters in the URL of the image to make sure you always have what you need. This makes it a great fit for creating responsive images and shaving precious kilobytes off your initial page load time. We\\u2019ll be using a script I wrote to upload and generate responsive image tags to replace the current ones on your website.\"), mdx(\"h2\", {\n    \"id\": \"the-story-behind-responsive-images\"\n  }, \"The Story Behind Responsive Images\"), mdx(\"p\", null, mdx(\"a\", _extends({\n    parentName: \"p\"\n  }, {\n    \"href\": \"http://cloudinary.com/documentation/responsive_images\"\n  }), \"Responsive images\"), \" have been around for a couple of years, and current browsers offer good support. They fall back gracefully to the original image if a browser does not support them, and the markup for a responsive image is just a normal tag plus two attributes.\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {}), \"<img sizes=\\u201D(max-width: 500px) 100vw, (max-width: 1400px) 33vw, 1400\\\"\\nsrcset=\\u201Dhttps://res.cloudinary.com/yourapp/image/upload/c_crop,r_max/c_scale,w_1400/v1501546428/Puppy.jpg 1400w,\\nhttps://res.cloudinary.com/yourapp/image/upload/c_crop,r_max/c_scale,w_1365/v1501546428/Puppy.jpg 1365w,\\nhttps://res.cloudinary.com/yourapp/image/upload/c_crop,r_max/c_scale,w_1202/v1501546428/Puppy.jpg 1202w,\\nhttps://res.cloudinary.com/yourapp/image/upload/c_crop,r_max/c_scale,w_872/v1501546428/Puppy.jpg 872w,\\nhttps://res.cloudinary.com/yourapp/image/upload/c_crop,r_max/c_scale,w_625/v1501546428/Puppy.jpg 625w,\\nhttps://res.cloudinary.com/yourapp/image/upload/c_crop,r_max/c_scale,w_200/v1501546428/Puppy.jpg 200w\\u201D\\nsrc=\\u201Dhttps://res.cloudinary.com/yourapp/image/upload/v1501546428/Puppy.jpg\\\"\\nalt=\\u201D\\u201D\\n/>\\n\")), mdx(\"p\", null, \"Responsive images use the same image tag with the addition of two attributes, sizes and srcset. Sizes are media conditions you define based off how the image reacts on certain website sizes. For instance, the tag above tells the browser for devices up to a width of 500 pixels, the image will be 100 percent of the view width(vw) and only 33 percent of the view width up to 1400 pixels. If neither are met, fall back to the size of the image.\\nNext up we have the srcset attribute, which defines the various widths of images the browser can choose from when rendering the page.\"), mdx(\"h2\", {\n    \"id\": \"knowing-the-right-number-of-images-to-make\"\n  }, \"Knowing the Right Number of Images to Make\"), mdx(\"p\", null, \"One of the most challenging parts of responsive images is knowing how many different image sizes to make to see relevant performance gains. Luckily, Cloudinary has a built a \", mdx(\"a\", _extends({\n    parentName: \"p\"\n  }, {\n    \"href\": \"http://www.responsivebreakpoints.com/\"\n  }), \"great tool\"), \" that enables you to choose the min-width, max-width, max images to make, and define the byte step before making another image transform.\"), mdx(\"h2\", {\n    \"id\": \"images-to-the-cloud\"\n  }, \"Images to the Cloud\"), mdx(\"p\", null, \"The first thing you\\u2019ll need to do to optimize your images and generate responsive images is to create an account with Cloudinary. They have a generous free tier that supports storing up to 75,000 images. Once you have an account you can manually upload images using the web app or API. We\\u2019ll be using the Cloudinary API, and a little script I made to handle uploading multiple images and generating responsive image tags to place in your app. This helps us create the markup we need and also automatically create the transformations we need to add into our app.\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {}), \"git clone\\n\\nhttps://github.com/mwood23/responsiveImageUploaderCloudinary.git\\n\\nnpm install\\n\")), mdx(\"p\", null, \"Next you\\u2019ll want to take your API information and place it in the .env file from the cloned repo. It can be found on the front page of the Cloudinary web console. While you\\u2019re in the console go over to the settings and choose a default upload quality. I use quality-eco, which will trim off a lot of size on the images while keeping them looking crisp. Now every time you upload an image it will automatically shave off several KBs. Next up, getting the images in there.\\nThe script takes in a JSON file, photosToUpload.json, with the path of where the file is, the responsive configuration and the image transform object.\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {}), \"{\\n  \\\"photos\\\": [\\n    {\\n      \\\"bytes_step\\\": 20000,\\n      \\\"location\\\": \\\"http://res.cloudinary.com/responsivebreakpoints/image/upload/dog.jpg\\\",\\n      \\\"max_images\\\": 20,\\n      \\\"max_width\\\": 1400,\\n      \\\"min_width\\\": 200,\\n      \\\"public_id\\\": \\\"Puppy\\\",\\n      \\\"tags\\\": [],\\n      \\\"transformation\\\": {\\n        \\\"crop\\\": \\\"crop\\\",\\n        \\\"radius\\\": \\\"max\\\"\\n      }\\n    },\\n    {\\n      \\\"bytes_step\\\": 15000,\\n      \\\"location\\\": \\\"/user/name/your/cool/puppy\\\",\\n      \\\"max_images\\\": 14,\\n      \\\"max_width\\\": 1200,\\n      \\\"min_width\\\": 800,\\n      \\\"public_id\\\": \\\"Your cool puppy photo\\\",\\n      \\\"tags\\\": [],\\n      \\\"transformation\\\": {}\\n    }\\n  ]\\n}\\n\")), mdx(\"p\", null, \"The location can take the local path on your computer or a link on the internet. Make sure to give it a public id that is different for each image to keep it organized. It\\u2019s best to look at the size your image is on your website and use the the responsive breakpoints tool mentioned above to determine the breakpoint configuration.\\nNow, back to the script. Navigate to the cloned repo in your terminal of choice and run node index.js. This will give you some logs in the console telling you that your images have been updated successfully and write some pretty markup to output.html that should look something like this:\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {}), \"<! \\u2014 Upload for PUBLIC_ID Puppy \\u2192\\n<img sizes=\\u201D(max-width: 1400px) 100vw, 1400px\\u201D\\nsrcset=\\u201Dhttps://res.cloudinary.com/yourapp/image/upload/c_crop,r_max/c_scale,w_1400/v1501546428/Puppy.jpg 1400w,\\nhttps://res.cloudinary.com/yourapp/image/upload/c_crop,r_max/c_scale,w_1365/v1501546428/Puppy.jpg 1365w,\\nhttps://res.cloudinary.com/yourapp/image/upload/c_crop,r_max/c_scale,w_1202/v1501546428/Puppy.jpg 1202w,\\nhttps://res.cloudinary.com/yourapp/image/upload/c_crop,r_max/c_scale,w_872/v1501546428/Puppy.jpg 872w,\\nhttps://res.cloudinary.com/yourapp/image/upload/c_crop,r_max/c_scale,w_625/v1501546428/Puppy.jpg 625w,\\nhttps://res.cloudinary.com/yourapp/image/upload/c_crop,r_max/c_scale,w_200/v1501546428/Puppy.jpg 200w\\u201D\\nsrc=\\u201Dhttps://res.cloudinary.com/yourapp/image/upload/v1501546428/Puppy.jpg\\\"\\nalt=\\u201D\\u201D\\n/>\\n<! \\u2014 Upload for PUBLIC_ID Your cool puppy photo \\u2192\\n<img sizes=\\u201D(max-width: 1200px) 100vw, 1200px\\u201D\\nsrcset=\\u201Dhttps://res.cloudinary.com/yourapp/image/upload/c_scale,w_1200/v1501546589/Your%20cool%20puppy%20photo.jpg 1200w,\\nhttps://res.cloudinary.com/yourapp/image/upload/c_scale,w_1182/v1501546589/Your%20cool%20puppy%20photo.jpg 1182w,\\nhttps://res.cloudinary.com/yourapp/image/upload/c_scale,w_1018/v1501546589/Your%20cool%20puppy%20photo.jpg 1018w,\\nhttps://res.cloudinary.com/yourapp/image/upload/c_scale,w_800/v1501546589/Your%20cool%20puppy%20photo.jpg 800w\\u201D\\nsrc=\\u201Dhttps://res.cloudinary.com/yourapp/image/upload/v1501546589/Your%20cool%20puppy%20photo.jpg\\\"\\nalt=\\u201D\\u201D\\n/>\\n\")), mdx(\"p\", null, \"Now you just need to replace the image tag in your app with the one above and you will have performant, responsive images. The image optimization alone should take a good amount of time off page rendering times. Combine that with responsive images and you\\u2019ve created a better user experience with just a couple hours of work (depending on how many images you have). This method works great for server-side rendered apps, static sites, or web apps where you don\\u2019t want to introduce another dependency into your app to optimize a couple of images. However, if your web app is heavily focuses on uploading and showing images Cloudinary has a \", mdx(\"a\", _extends({\n    parentName: \"p\"\n  }, {\n    \"href\": \"http://cloudinary.com/documentation/responsive_images#step_3_call_the_cloudinary_responsive_method\"\n  }), \"Javascript solution\"), \" that works well.\\nLet me know what kind of performance gains this did for you by running a \", mdx(\"a\", _extends({\n    parentName: \"p\"\n  }, {\n    \"href\": \"https://developers.google.com/web/tools/lighthouse/\"\n  }), \"Lighthouse test\"), \" before and after on your app!\"));\n}\n;\nMDXContent.isMDXComponent = true;","hero":{"full":{"fluid":{"base64":"data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAJABQDASIAAhEBAxEB/8QAGAAAAgMAAAAAAAAAAAAAAAAAAAQBAgP/xAAWAQEBAQAAAAAAAAAAAAAAAAACAAH/2gAMAwEAAhADEAAAAaSblIipl//EABwQAAAGAwAAAAAAAAAAAAAAAAABAgMSMgQRMf/aAAgBAQABBQIjLUgtxEservF2/8QAFhEBAQEAAAAAAAAAAAAAAAAAEQEQ/9oACAEDAQE/AUhn/8QAFREBAQAAAAAAAAAAAAAAAAAAEBH/2gAIAQIBAT8Bh//EABoQAAICAwAAAAAAAAAAAAAAAAABEEFRgZH/2gAIAQEABj8CWC+Fmxx//8QAHhAAAQMEAwAAAAAAAAAAAAAAAAERMRAhUXGBobH/2gAIAQEAAT8hQeDIzaZCu5nBNsdRaH//2gAMAwEAAgADAAAAEOQv/8QAFhEAAwAAAAAAAAAAAAAAAAAAAAEx/9oACAEDAQE/EFIFD//EABYRAQEBAAAAAAAAAAAAAAAAAAEREP/aAAgBAgEBPxApuf/EAB4QAQACAQQDAAAAAAAAAAAAAAEAESFRYXHwMUGx/9oACAEBAAE/EG0q9rVVXtCI5AhyMAc7EUUUCx2zvNZ0Wk8nB8n/2Q==","aspectRatio":2.2264150943396226,"src":"/static/1d9cd0d60d7a77e770cf2bb93e44b7fa/22328/hero.jpg","srcSet":"/static/1d9cd0d60d7a77e770cf2bb93e44b7fa/6d250/hero.jpg 236w,\n/static/1d9cd0d60d7a77e770cf2bb93e44b7fa/1a26c/hero.jpg 472w,\n/static/1d9cd0d60d7a77e770cf2bb93e44b7fa/22328/hero.jpg 944w,\n/static/1d9cd0d60d7a77e770cf2bb93e44b7fa/cca5d/hero.jpg 1260w","srcWebp":"/static/1d9cd0d60d7a77e770cf2bb93e44b7fa/1d644/hero.webp","srcSetWebp":"/static/1d9cd0d60d7a77e770cf2bb93e44b7fa/cbe96/hero.webp 236w,\n/static/1d9cd0d60d7a77e770cf2bb93e44b7fa/8ab83/hero.webp 472w,\n/static/1d9cd0d60d7a77e770cf2bb93e44b7fa/1d644/hero.webp 944w,\n/static/1d9cd0d60d7a77e770cf2bb93e44b7fa/7614f/hero.webp 1260w","sizes":"(max-width: 944px) 100vw, 944px"}},"regular":{"fluid":{"base64":"data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAMABQDASIAAhEBAxEB/8QAGAAAAgMAAAAAAAAAAAAAAAAAAAQBAgP/xAAWAQEBAQAAAAAAAAAAAAAAAAACAAH/2gAMAwEAAhADEAAAAaTkqUwLmX//xAAaEAEBAAIDAAAAAAAAAAAAAAABAgMSABEx/9oACAEBAAEFAhA25eSNl6xTd3Xj/8QAFhEBAQEAAAAAAAAAAAAAAAAAEQEQ/9oACAEDAQE/AUhn/8QAFREBAQAAAAAAAAAAAAAAAAAAEBH/2gAIAQIBAT8Bh//EABoQAAICAwAAAAAAAAAAAAAAAAAhAUECEFH/2gAIAQEABj8CjhZYkPKdf//EAB0QAAICAgMBAAAAAAAAAAAAAAABESFRcTFBgbH/2gAIAQEAAT8h9AVkhtpj9oVgbPcn0fYcakXOz//aAAwDAQACAAMAAAAQ5A//xAAXEQADAQAAAAAAAAAAAAAAAAAAAREx/9oACAEDAQE/EFbAsP/EABcRAAMBAAAAAAAAAAAAAAAAAAABIRH/2gAIAQIBAT8Qpjjw/8QAHBABAAICAwEAAAAAAAAAAAAAAQARITFRYXFB/9oACAEBAAE/EGgoSrNVfUI32ULdmoe+ptBpYvj2J3zF4rfPMMCgvGj7LwWruqz/2Q==","aspectRatio":1.6804123711340206,"src":"/static/1d9cd0d60d7a77e770cf2bb93e44b7fa/6694a/hero.jpg","srcSet":"/static/1d9cd0d60d7a77e770cf2bb93e44b7fa/70b8f/hero.jpg 163w,\n/static/1d9cd0d60d7a77e770cf2bb93e44b7fa/7ec88/hero.jpg 327w,\n/static/1d9cd0d60d7a77e770cf2bb93e44b7fa/6694a/hero.jpg 653w,\n/static/1d9cd0d60d7a77e770cf2bb93e44b7fa/ed86f/hero.jpg 980w,\n/static/1d9cd0d60d7a77e770cf2bb93e44b7fa/30932/hero.jpg 1260w","srcWebp":"/static/1d9cd0d60d7a77e770cf2bb93e44b7fa/d603c/hero.webp","srcSetWebp":"/static/1d9cd0d60d7a77e770cf2bb93e44b7fa/64a97/hero.webp 163w,\n/static/1d9cd0d60d7a77e770cf2bb93e44b7fa/a98ca/hero.webp 327w,\n/static/1d9cd0d60d7a77e770cf2bb93e44b7fa/d603c/hero.webp 653w,\n/static/1d9cd0d60d7a77e770cf2bb93e44b7fa/c1bd6/hero.webp 980w,\n/static/1d9cd0d60d7a77e770cf2bb93e44b7fa/f031e/hero.webp 1260w","sizes":"(max-width: 653px) 100vw, 653px"}},"narrow":{"fluid":{"base64":"data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAMABQDASIAAhEBAxEB/8QAGAAAAgMAAAAAAAAAAAAAAAAAAAQBAgP/xAAWAQEBAQAAAAAAAAAAAAAAAAACAAH/2gAMAwEAAhADEAAAAaTkqUwLmX//xAAaEAEBAAIDAAAAAAAAAAAAAAABAgMSABEx/9oACAEBAAEFAhA25eSNl6xTd3Xj/8QAFhEBAQEAAAAAAAAAAAAAAAAAEQEQ/9oACAEDAQE/AUhn/8QAFREBAQAAAAAAAAAAAAAAAAAAEBH/2gAIAQIBAT8Bh//EABoQAAICAwAAAAAAAAAAAAAAAAAhAUECEFH/2gAIAQEABj8CjhZYkPKdf//EAB0QAAICAgMBAAAAAAAAAAAAAAABESFRcTFBgbH/2gAIAQEAAT8h9AVkhtpj9oVgbPcn0fYcakXOz//aAAwDAQACAAMAAAAQ5A//xAAXEQADAQAAAAAAAAAAAAAAAAAAAREx/9oACAEDAQE/EFbAsP/EABcRAAMBAAAAAAAAAAAAAAAAAAABIRH/2gAIAQIBAT8Qpjjw/8QAHBABAAICAwEAAAAAAAAAAAAAAQARITFRYXFB/9oACAEBAAE/EGgoSrNVfUI32ULdmoe+ptBpYvj2J3zF4rfPMMCgvGj7LwWruqz/2Q==","aspectRatio":1.6764705882352942,"src":"/static/1d9cd0d60d7a77e770cf2bb93e44b7fa/c1e08/hero.jpg","srcSet":"/static/1d9cd0d60d7a77e770cf2bb93e44b7fa/8bed6/hero.jpg 114w,\n/static/1d9cd0d60d7a77e770cf2bb93e44b7fa/1e283/hero.jpg 229w,\n/static/1d9cd0d60d7a77e770cf2bb93e44b7fa/c1e08/hero.jpg 457w,\n/static/1d9cd0d60d7a77e770cf2bb93e44b7fa/8ae28/hero.jpg 686w,\n/static/1d9cd0d60d7a77e770cf2bb93e44b7fa/5cf51/hero.jpg 914w,\n/static/1d9cd0d60d7a77e770cf2bb93e44b7fa/30932/hero.jpg 1260w","srcWebp":"/static/1d9cd0d60d7a77e770cf2bb93e44b7fa/72aed/hero.webp","srcSetWebp":"/static/1d9cd0d60d7a77e770cf2bb93e44b7fa/03a0a/hero.webp 114w,\n/static/1d9cd0d60d7a77e770cf2bb93e44b7fa/d2b1d/hero.webp 229w,\n/static/1d9cd0d60d7a77e770cf2bb93e44b7fa/72aed/hero.webp 457w,\n/static/1d9cd0d60d7a77e770cf2bb93e44b7fa/1a85c/hero.webp 686w,\n/static/1d9cd0d60d7a77e770cf2bb93e44b7fa/90a86/hero.webp 914w,\n/static/1d9cd0d60d7a77e770cf2bb93e44b7fa/f031e/hero.webp 1260w","sizes":"(max-width: 457px) 100vw, 457px"}},"seo":{"fixed":{"src":"/static/1d9cd0d60d7a77e770cf2bb93e44b7fa/0ff54/hero.jpg"}}}}}],"pathPrefix":"/blog","first":false,"last":true,"index":2,"pageCount":2,"additionalContext":{"basePath":"/blog","skip":6,"limit":6}}}}