{"id":28365,"date":"2022-08-16T11:26:10","date_gmt":"2022-08-16T11:26:10","guid":{"rendered":"http:\/\/improve-image-accessibility-with-cloudinary"},"modified":"2022-08-16T11:26:10","modified_gmt":"2022-08-16T11:26:10","slug":"improve-image-accessibility-with-cloudinary","status":"publish","type":"post","link":"https:\/\/cloudinary.com\/blog\/guest_post\/improve-image-accessibility-with-cloudinary\/","title":{"rendered":"Improve Image Accessibility with Cloudinary"},"content":{"rendered":"<div class=\"wp-block-cloudinary-markdown \"><p>Accessibility is one of the most prominent concerns in modern web development. The need to optimize websites for screen readers and cater to the needs of the visually impaired cannot be overemphasized. In this post, we\u2019ll look at how we can improve the accessibility of our media assets using Cloudinary and Next.js. We\u2019ll build a demo with Next.js to implement accessibility enhancements like &#8211; auto-generating alt text for images, color-blind friendly images, dark\/light modes, and more.<\/p>\n<h2>Prerequisites<\/h2>\n<p>To follow along with this tutorial, you will need to have:<\/p>\n<ul>\n<li>A free <a href=\"https:\/\/cloudinary.com\/\">Cloudinary account<\/a>.<\/li>\n<li>Working experience with React and Next.js.<\/li>\n<\/ul>\n<\/div>\n  \n  <div class=\"wp-block-cloudinary-code-sandbox \">\n    <iframe\n      src=\"https:\/\/codesandbox.io\/embed\/stupefied-rubin-xry44b?theme=dark&amp;codemirror=1&amp;highlights=&amp;editorsize=50&amp;fontsize=14&amp;expanddevtools=0&amp;hidedevtools=0&amp;eslint=0&amp;forcerefresh=0&amp;hidenavigation=0&amp;initialpath=%2F&amp;module=&amp;moduleview=0&amp;previewwindow=&amp;view=&amp;runonclick=1\"\n      height=\"500\"\n      style=\"width: 100%;\"\n      title=\"How to improve image accessibility with Cloudinary and Next.js.\"\n      loading=\"lazy\"\n      allow=\"accelerometer; ambient-light-sensor; camera; encrypted-media; geolocation; gyroscope; hid; microphone; midi; payment; usb; vr; xr-spatial-tracking\"\n      sandbox=\"allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts\"\n    ><\/iframe>\n  <\/div>\n\n  <div class=\"wp-block-cloudinary-markdown \"><h2>Setting up the Project<\/h2>\n<p>Create a new <a href=\"https:\/\/nextjs.org\/\">Next.js<\/a> application using the following command:<\/p>\n<pre class=\"js-syntax-highlighted\"><span><code class=\"hljs shcb-wrap-lines\">npx create-next-app media-assets\n<\/code><\/span><\/pre>\n<p>The above command creates a starter next.js application in the project folder.<\/p>\n<p>Now, run these commands to navigate into the project directory and install the required dependencies:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css shcb-wrap-lines\"><span class=\"hljs-selector-tag\">cd<\/span> <span class=\"hljs-selector-tag\">media-assets<\/span>\n<span class=\"hljs-selector-tag\">npm<\/span> <span class=\"hljs-selector-tag\">i<\/span> <span class=\"hljs-keyword\">@cloudinary<\/span>\/url-gen isomorphic-dompurify\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><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<p>After the installation is complete, run:<\/p>\n<pre class=\"js-syntax-highlighted\"><span><code class=\"hljs shcb-wrap-lines\">npm run dev\n<\/code><\/span><\/pre>\n<p>Next.js will start a live development server at <a href=\"http:\/\/localhost:3000\">http:\/\/localhost:3000<\/a><\/p>\n<h2>Implementing the dark-mode effect<\/h2>\n<p>We will implement dark mode using the Next.js custom <a href=\"https:\/\/nextjs.org\/docs\/advanced-features\/custom-document#caveats\"><\/a><code>[_document](https:\/\/nextjs.org\/docs\/advanced-features\/custom-document#caveats)<\/code> <a href=\"https:\/\/nextjs.org\/docs\/advanced-features\/custom-document#caveats\">configuration<\/a>.<\/p>\n<p>First, override the default <code>Document<\/code> by creating a <code>_document.js<\/code> file in the <code>\/pages<\/code> folder, then add the following code snippet:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\"><span class=\"hljs-comment\">\/\/pages\/_document.js<\/span>\n<span class=\"hljs-keyword\">import<\/span> Document, { Html, Head, Main, NextScript } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"next\/document\"<\/span>;\n<span class=\"hljs-keyword\">import<\/span> DOMPurify <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"isomorphic-dompurify\"<\/span>;\n<span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">MyDocument<\/span> <span class=\"hljs-keyword\">extends<\/span> <span class=\"hljs-title\">Document<\/span> <\/span>{\n  render() {\n    <span class=\"hljs-keyword\">return<\/span> (\n      <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Html<\/span> <span class=\"hljs-attr\">lang<\/span>=<span class=\"hljs-string\">\"en\"<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Head<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">Head<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">body<\/span>&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">script<\/span>\n            <span class=\"hljs-attr\">dangerouslySetInnerHTML<\/span>=<span class=\"hljs-string\">{{<\/span>\n              <span class=\"hljs-attr\">__html:<\/span> <span class=\"hljs-attr\">DOMPurify.sanitize<\/span>(<span class=\"hljs-attr\">themeInitializerScript<\/span>)\n            }}\n          &gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">script<\/span>&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Main<\/span> \/&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">NextScript<\/span> \/&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">body<\/span>&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">Html<\/span>&gt;<\/span><\/span>\n    );\n  }\n}\n<span class=\"hljs-comment\">\/\/ This function needs to be a String<\/span>\n<span class=\"hljs-keyword\">const<\/span> themeInitializerScript = <span class=\"hljs-string\">`(function() {\n  <span class=\"hljs-subst\">${setInitialColorMode.toString()}<\/span>\n  setInitialColorMode();\n})()\n`<\/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\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>In the snippet above, we import <code>Document, { Html, Head, Main, NextScript }<\/code> from the <code>next\/document<\/code> package. We also Import <code>DOMPurify<\/code> from our <code>isomorphic-dompurify<\/code> package and use it to sanitize our <code>dangerouslySetHtml<\/code> data.<\/p>\n<p>Next, we define a <code>themeInitializerScript<\/code> to set our initial color mode, this is the data we sanitize using the DOMPurify package. Notice that we called a <code>setInitialColorMode()<\/code> function our <code>themeInitializerScript<\/code> ? let\u2019s define that function below:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\"><span class=\"hljs-comment\">\/\/pages\/_document.js<\/span>\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">setInitialColorMode<\/span>(<span class=\"hljs-params\"><\/span>) <\/span>{\n  <span class=\"hljs-comment\">\/\/ Check initial color preference<\/span>\n  <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">getInitialColorMode<\/span>(<span class=\"hljs-params\"><\/span>) <\/span>{\n    <span class=\"hljs-keyword\">const<\/span> persistedPreferenceMode = <span class=\"hljs-built_in\">window<\/span>.localStorage.getItem(<span class=\"hljs-string\">\"theme\"<\/span>);\n    <span class=\"hljs-keyword\">const<\/span> hasPersistedPreference = <span class=\"hljs-keyword\">typeof<\/span> persistedPreferenceMode === <span class=\"hljs-string\">\"string\"<\/span>;\n    <span class=\"hljs-keyword\">if<\/span> (hasPersistedPreference) {\n      <span class=\"hljs-keyword\">return<\/span> persistedPreferenceMode;\n    }\n    <span class=\"hljs-comment\">\/\/ Check the current preference<\/span>\n    <span class=\"hljs-keyword\">const<\/span> preference = <span class=\"hljs-built_in\">window<\/span>.matchMedia(<span class=\"hljs-string\">\"(prefers-color-scheme: dark)\"<\/span>);\n    <span class=\"hljs-keyword\">const<\/span> hasMediaQueryPreference = <span class=\"hljs-keyword\">typeof<\/span> preference.matches === <span class=\"hljs-string\">\"boolean\"<\/span>;\n    <span class=\"hljs-keyword\">if<\/span> (hasMediaQueryPreference) {\n      <span class=\"hljs-keyword\">return<\/span> preference.matches ? <span class=\"hljs-string\">\"dark\"<\/span> : <span class=\"hljs-string\">\"light\"<\/span>;\n    }\n    <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-string\">\"light\"<\/span>;\n }\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<p>In the snippet above, we:<\/p>\n<ul>\n<li>Create the <code>getInitialColorMode()<\/code> function to fetch the <code>persistedPreferenceMode<\/code> from the <code>LocalStorage<\/code> using the <code>theme<\/code> key.<\/li>\n<li>Create a <code>hasPersistancePreference<\/code> variable that stores a boolean result after checking to ensure that the <code>typeof<\/code> of the <code>persistedPreferenceMode<\/code> is a <code>string<\/code>.<\/li>\n<li>Declare a conditional  statement that returns the <code>persistedPreferenceMode<\/code> if <code>hasPersistedPreference<\/code> is true.<\/li>\n<li>Set <code>preference<\/code> variable that equals the value of <code>window.matchMedia(&quot;(prefers-color-scheme: dark)&quot;)<\/code>.<\/li>\n<li>Set a check to confirm the <code>typeof<\/code> of <code>preference.matches<\/code> is equal to a <code>boolean<\/code> and stores its value in the <code>hasMediaQueryPreference<\/code>.<\/li>\n<li>Lastly, we create a conditional statement to check if <code>hasMediaQueryPreference<\/code> is true, and perform different actions when the conditions match and fail respectively.<\/li>\n<\/ul>\n<p>Next, let\u2019s link these settings to our next app by adding the following snippet:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\"><span class=\"hljs-comment\">\/\/pages\/_document.js<\/span>\n<span class=\"hljs-keyword\">const<\/span> currentColorMode = getInitialColorMode();\n  <span class=\"hljs-keyword\">const<\/span> element = <span class=\"hljs-built_in\">document<\/span>.documentElement;\n  element.style.setProperty(<span class=\"hljs-string\">\"--initial-color-mode\"<\/span>, currentColorMode);\n  <span class=\"hljs-comment\">\/\/ If darkmode, apply darkmode<\/span>\n  <span class=\"hljs-keyword\">if<\/span> (currentColorMode === <span class=\"hljs-string\">\"dark\"<\/span>)\n    <span class=\"hljs-built_in\">document<\/span>.documentElement.setAttribute(<span class=\"hljs-string\">\"data-theme\"<\/span>, <span class=\"hljs-string\">\"dark\"<\/span>);\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\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>In the snippet above, we store the value of our <code>getInitialColorMode()<\/code> function into a new variable <code>currentColorMode<\/code>. We do the same to <code>document.documentElement<\/code> as we store its value into a new <code>element<\/code> variable to make it easier to reference.<\/p>\n<p>With that, we can easily assign a CSS property to that element using the <code>setProperty()<\/code> function, which sets the value of our <code>--initial-color-mode<\/code>  property to the <code>currentColorMode()<\/code>. Lastly, we check if the <code>currentcColorMode<\/code> is dark and, if so, set the <code>data-theme<\/code> attribute to <code>dark<\/code>. Next, let\u2019s configure the index page with the necessary markup and logic for our demo.<\/p>\n<p>First, we\u2019ll set up state management in our application using React hooks. This will allow us to track and modify the state of our applications theme such that we can toggle it from light to dark and vice versa:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\"><span class=\"hljs-comment\">\/\/pages\/index.js<\/span>\n<span class=\"hljs-keyword\">import<\/span> { useEffect, useState } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"react\"<\/span>\n<span class=\"hljs-keyword\">const<\/span> HomePage = <span class=\"hljs-function\"><span class=\"hljs-params\">()<\/span> =&gt;<\/span> {\n<span class=\"hljs-keyword\">const<\/span> &#91; darkTheme, setDarkTheme ] = useState(<span class=\"hljs-literal\">undefined<\/span>)\nuseEffect(<span class=\"hljs-function\"><span class=\"hljs-params\">()<\/span> =&gt;<\/span> {\n    <span class=\"hljs-keyword\">const<\/span> root = <span class=\"hljs-built_in\">window<\/span>.document.documentElement;\n    <span class=\"hljs-keyword\">const<\/span> initialColorValue = root.style.getPropertyValue(\n      <span class=\"hljs-string\">\"--initial-color-mode\"<\/span>\n    );\n    <span class=\"hljs-comment\">\/\/ Set initial darkmode to light<\/span>\n    setDarkTheme(initialColorValue === <span class=\"hljs-string\">\"dark\"<\/span>);\n  }, &#91;]);\n}\n<\/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<p>Here, we:<\/p>\n<ul>\n<li>Import the <code>useState<\/code>, and <code>useEffect<\/code> hooks from react for state management.<\/li>\n<li>Initialize a <code>darkTheme<\/code> state and assign it an undefined value for a start.<\/li>\n<li>Create a <code>useEffect<\/code> hook without a dependency that sets the initial theme to light mode.<\/li>\n<\/ul>\n<p>Next, we create another <code>useEffect<\/code> hook that depends on the <code>darkTheme<\/code> state to conditionally toggle our application from light mode to dark mode. It does this by setting the <code>data-theme<\/code> attribute on the DOM and storing the value in localStorage:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\"><span class=\"hljs-comment\">\/\/ pages\/index.js<\/span>\nuseEffect(<span class=\"hljs-function\"><span class=\"hljs-params\">()<\/span> =&gt;<\/span> {\n    <span class=\"hljs-keyword\">if<\/span> (darkTheme !== <span class=\"hljs-literal\">undefined<\/span>) {\n      <span class=\"hljs-keyword\">if<\/span> (darkTheme) {\n        <span class=\"hljs-comment\">\/\/ Set value of  darkmode to dark<\/span>\n        <span class=\"hljs-built_in\">document<\/span>.documentElement.setAttribute(<span class=\"hljs-string\">\"data-theme\"<\/span>, <span class=\"hljs-string\">\"dark\"<\/span>);\n        <span class=\"hljs-built_in\">window<\/span>.localStorage.setItem(<span class=\"hljs-string\">\"theme\"<\/span>, <span class=\"hljs-string\">\"dark\"<\/span>);\n      } <span class=\"hljs-keyword\">else<\/span> {\n        <span class=\"hljs-comment\">\/\/ Set value of  darkmode to light<\/span>\n        <span class=\"hljs-built_in\">document<\/span>.documentElement.removeAttribute(<span class=\"hljs-string\">\"data-theme\"<\/span>);\n        <span class=\"hljs-built_in\">window<\/span>.localStorage.setItem(<span class=\"hljs-string\">\"theme\"<\/span>, <span class=\"hljs-string\">\"light\"<\/span>);\n      }\n    }\n  }, &#91;darkTheme]);\n<\/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<p>In the above snippet, we will do a check to ensure that the <code>darkTheme<\/code> value is not undefined, then we set the <code>data-theme<\/code> attribute and the <code>localstorage<\/code>\u2019s theme key to dark. Else, we remove the <code>data-theme<\/code> attribute and set the <code>theme<\/code> key to light.<\/p>\n<p>Next, we create a checkbox input with a checked attribute and set its value to the <code>darkTheme<\/code> state. Then, we add an <code>onChange<\/code> event to listen and execute our <code>handleToggle()<\/code> function when the <code>darkTheme<\/code> state changes:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-7\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml shcb-wrap-lines\">\/\/pages\/index.js\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n  {darkTheme !== undefined &amp;&amp; (\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">form<\/span> <span class=\"hljs-attr\">action<\/span>=<span class=\"hljs-string\">\"#\"<\/span>&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">label<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"switch\"<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">input<\/span>\n          <span class=\"hljs-attr\">type<\/span>=<span class=\"hljs-string\">\"checkbox\"<\/span>\n          <span class=\"hljs-attr\">checked<\/span>=<span class=\"hljs-string\">{darkTheme}<\/span>\n          <span class=\"hljs-attr\">onChange<\/span>=<span class=\"hljs-string\">{handleToggle}<\/span>\n        \/&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">span<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"slider\"<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">span<\/span>&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">label<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">form<\/span>&gt;<\/span>\n  )}\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-7\"><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<p>Next, let\u2019s define the <code>handleToggle``()<\/code> function to toggle the theme by adding the following snippet:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-8\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\">  <span class=\"hljs-keyword\">const<\/span> handleToggle = <span class=\"hljs-function\">(<span class=\"hljs-params\">event<\/span>) =&gt;<\/span> {\n    setDarkTheme(event.target.checked);\n  };\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-8\"><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<p>With this, we have successfully configured dark mode theming in this project. Next, let\u2019s implement the color blind effects on assets uploaded to our Cloudinary application.<\/p>\n<h2>Implementing Color Blind Effects on Assets<\/h2>\n<p>For this part of the article, we will integrate our application with Cloudinary using the <a href=\"https:\/\/cloudinary.com\/documentation\/react_quick_start\">C<\/a><a href=\"https:\/\/cloudinary.com\/documentation\/react_quick_start\">loudinary React SDK<\/a>. Here, we will work to cater for a commonly observed condition, <strong>deuteranopia<\/strong> (difficulty seeing different shades of red, green, and yellow).<\/p>\n<p>Open the <code>index.js<\/code> file and update it with the snippet below:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-9\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\"><span class=\"hljs-comment\">\/\/ pages\/index.js<\/span>\n<span class=\"hljs-keyword\">import<\/span> { Cloudinary } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"@cloudinary\/url-gen\"<\/span>;\n<span class=\"hljs-keyword\">import<\/span> { simulateColorBlind } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"@cloudinary\/url-gen\/actions\/effect\"<\/span>;\n    \n<span class=\"hljs-keyword\">const<\/span> HomePage = <span class=\"hljs-function\"><span class=\"hljs-params\">()<\/span> =&gt;<\/span> {\n  <span class=\"hljs-keyword\">const<\/span> &#91;colorBlindEffect, setColorBlindEffect] = useState(<span class=\"hljs-string\">\"\"<\/span>);\n  <span class=\"hljs-keyword\">const<\/span> handleClick = <span class=\"hljs-function\"><span class=\"hljs-params\">()<\/span> =&gt;<\/span> {\n    setColorBlindEffect(<span class=\"hljs-string\">\"\"<\/span>);\n    <span class=\"hljs-keyword\">const<\/span> cld = <span class=\"hljs-keyword\">new<\/span> Cloudinary({\n      <span class=\"hljs-attr\">cloud<\/span>: {\n        <span class=\"hljs-attr\">cloudName<\/span>: \u201cYOUR_CLOUDNAME\u201d\n      }\n    });\n    <span class=\"hljs-keyword\">const<\/span> myImage = cld.image(<span class=\"hljs-string\">\"color-effect\/afro\"<\/span>);\n    myImage.effect(simulateColorBlind().condition(<span class=\"hljs-string\">\"deuteranopia\"<\/span>));\n    <span class=\"hljs-keyword\">const<\/span> imageUrl = myImage.toURL();\n    setColorBlindEffect(imageUrl);\n  };\n  <span class=\"hljs-keyword\">const<\/span> reset = <span class=\"hljs-function\"><span class=\"hljs-params\">()<\/span> =&gt;<\/span> {\n    setColorBlindEffect(<span class=\"hljs-string\">\"\/afro.jpg\"<\/span>);\n  };\n    \n  <span class=\"hljs-keyword\">return<\/span> (\n    <span class=\"xml\"><span class=\"hljs-tag\">&lt;&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"container\"<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">section<\/span> <span class=\"hljs-attr\">id<\/span>=<span class=\"hljs-string\">\"image\"<\/span>&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"image-wrapper\"<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">img<\/span>\n              <span class=\"hljs-attr\">src<\/span>=<span class=\"hljs-string\">{colorBlindEffect<\/span> ? <span class=\"hljs-attr\">colorBlindEffect<\/span> <span class=\"hljs-attr\">:<\/span> \"\/<span class=\"hljs-attr\">afro.jpg<\/span>\"}\n              <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"afro\"<\/span>\n              <span class=\"hljs-attr\">alt<\/span>=<span class=\"hljs-string\">\"woman on afro\"<\/span>\n            \/&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">button<\/span>\n              <span class=\"hljs-attr\">onClick<\/span>=<span class=\"hljs-string\">{handleClick}<\/span>\n              <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"btn\"<\/span>\n            &gt;<\/span>\n              ColorBlind Switch\n            <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">button<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">button<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"btn\"<\/span> <span class=\"hljs-attr\">onClick<\/span>=<span class=\"hljs-string\">{reset}<\/span>&gt;<\/span>\n              Restore Image\n            <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        <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">section<\/span>&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;\/&gt;<\/span><\/span>\n  );\n};\n<span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">default<\/span> HomePage;\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-9\"><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<p>In the snippet above, we:<\/p>\n<ul>\n<li>Import <code>Cloudinary<\/code> and the <code>simulateColorBlind<\/code> method to help achieve the desired functionalities.<\/li>\n<li>We then define a <code>colorBlindEffect<\/code> state to hold the initial value of the effect.<\/li>\n<li>Next, we create an HTML image element to display the image, along with two buttons to initiate the Cloudinary conversion of the image, and restore the original image respectively.<\/li>\n<li>In the <code>handleClick<\/code> function, we implement the logic to reset our <code>colorBlindEffect<\/code> state and fetch a sample image from Cloudinary. With the image saved in a variable <code>myImage<\/code>, we then apply the color blind effect on it by calling the <code>simulateColorBlind().condition()<\/code> method. In our case, we want to simulate the <code>deuteranopia<\/code> condition, so we specify it in the method as <code>condition(&quot;deuteranopia&quot;)<\/code>. To convert the value of <code>myImage<\/code> to a URL, we call the <code>toURL()<\/code> method on it and save the value to a new variable <code>imageUrl<\/code>. Finally, we update our colorBlindEffect state with the imageURL.<\/li>\n<\/ul>\n<p>With this, we have successfully implemented a colour-blind effect for the <code>deuteranopia<\/code> condition using Cloudinary. You can access this project <a href=\"https:\/\/github.com\/JohnpaulEze\/next-media-assets\">here<\/a> for a more hands-on experience with the source code.<\/p>\n<h2>Implementing Auto Alt Text Generation<\/h2>\n<p>For this part of the article, we\u2019ll show you how you can generate descriptive text for web images using Cloudinary\u2019s Google Auto Tagging add-on. To achieve this, we\u2019ll leverage the next.js API routes feature to create a Node environment that communicates with the Cloudinary API.<\/p>\n<p>In your pages folder, create an API route called <code>update.js<\/code> and add the following code:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-10\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\"><span class=\"hljs-comment\">\/\/ pages\/update.js<\/span>\n<span class=\"hljs-keyword\">import<\/span> { v2 <span class=\"hljs-keyword\">as<\/span> Cloudinary } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"cloudinary\"<\/span>;\n<span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">default<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">handler<\/span>(<span class=\"hljs-params\">req, res<\/span>) <\/span>{\n  <span class=\"hljs-keyword\">try<\/span> {\n    Cloudinary.config({\n      <span class=\"hljs-attr\">cloud_name<\/span>: process.env.CLOUD_NAME,\n      <span class=\"hljs-attr\">api_key<\/span>: process.env.API_KEY,\n      <span class=\"hljs-attr\">api_secret<\/span>: process.env.API_SECRET,\n      <span class=\"hljs-attr\">secure<\/span>: <span class=\"hljs-literal\">true<\/span>\n    });\n    <span class=\"hljs-keyword\">const<\/span> imageUpdate = Cloudinary.api.update(\n      <span class=\"hljs-string\">\"color-effect\/afro\"<\/span>,\n      { <span class=\"hljs-attr\">categorization<\/span>: <span class=\"hljs-string\">\"google_tagging\"<\/span>, <span class=\"hljs-attr\">auto_tagging<\/span>: <span class=\"hljs-number\">0.9<\/span> },\n      <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> (<span class=\"hljs-params\">error, result<\/span>) <\/span>{\n        <span class=\"hljs-built_in\">console<\/span>.log(result, error);\n        <span class=\"hljs-keyword\">return<\/span> result;\n      }\n    );\n    imageUpdate.then(<span class=\"hljs-function\">(<span class=\"hljs-params\">data<\/span>) =&gt;<\/span> {\n      res.status(<span class=\"hljs-number\">200<\/span>).json(data.tags&#91;<span class=\"hljs-number\">0<\/span>]);\n    });\n  } <span class=\"hljs-keyword\">catch<\/span> (error) {\n    <span class=\"hljs-built_in\">console<\/span>.log(error.message);\n    res.status(<span class=\"hljs-number\">500<\/span>).json();\n  }\n}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-10\"><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<p>Here, we:<\/p>\n<ul>\n<li>Import the Cloudinary Node SDK and export a handler function with <code>req<\/code> and <code>res<\/code> parameters.<\/li>\n<li>Create a conditional statement to handle the Cloudinary configurations and execute an update call.<\/li>\n<li>Update the image using the <code>update<\/code> API and set the <code>categorization<\/code> property to <code>google_tagging<\/code>.<\/li>\n<\/ul>\n<p>With the above configurations, we will be able to receive a URL from Cloudinary that contains an array of automatically generated texts that defines the image displayed.<\/p>\n<p>Next, let\u2019s display the returned result on the client by adding the following snippet to our <code>index.js<\/code> file:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-11\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\"><span class=\"hljs-comment\">\/\/pages\/index.js<\/span>\n<span class=\"hljs-keyword\">const<\/span> &#91;altText, setAltText] = useState(<span class=\"hljs-string\">\"\"<\/span>);\n<span class=\"hljs-keyword\">const<\/span> &#91;altTextToggle, setAltTextToggle] = useState(<span class=\"hljs-literal\">false<\/span>);\n\n<span class=\"hljs-keyword\">const<\/span> toggleAlt = <span class=\"hljs-keyword\">async<\/span> () =&gt; {\n  <span class=\"hljs-keyword\">const<\/span> altT = <span class=\"hljs-keyword\">await<\/span> fetch(<span class=\"hljs-string\">\"\/api\/update\"<\/span>);\n  <span class=\"hljs-keyword\">const<\/span> alt = <span class=\"hljs-keyword\">await<\/span> altT.json();\n  setAltText(alt);\n  setAltTextToggle(!altTextToggle);\n}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-11\"><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<p>Here, we make a fetch request to our <code>\/api\/update<\/code> route. As earlier mentioned, this endpoint will return a URL from Cloudinary that contains an array of generated texts that describes the image displayed. When we get this response, we update the <code>altText<\/code> in state with the first item in the array that we returned from the server.<\/p>\n<p>Now that we have the descriptive text in state, let\u2019s apply it to our HTML image element and also just display it on screen for visibility:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-12\" 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\">section<\/span> <span class=\"hljs-attr\">id<\/span>=<span class=\"hljs-string\">\"image\"<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"image-wrapper\"<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">img<\/span>\n      <span class=\"hljs-attr\">src<\/span>=<span class=\"hljs-string\">{colorBlindEffect<\/span> ? <span class=\"hljs-attr\">colorBlindEffect<\/span> <span class=\"hljs-attr\">:<\/span> \"\/<span class=\"hljs-attr\">afro.jpg<\/span>\"}\n      <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"afro\"<\/span>\n      <span class=\"hljs-attr\">alt<\/span>=<span class=\"hljs-string\">{altText}<\/span>\n    \/&gt;<\/span>\n    {altTextToggle ? <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">i<\/span>&gt;<\/span>{altText}<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">i<\/span>&gt;<\/span> : \"\"}\n  <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">button<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"btn\"<\/span> <span class=\"hljs-attr\">onClick<\/span>=<span class=\"hljs-string\">{toggleAlt}<\/span>&gt;<\/span>\n    view alt text\n  <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">button<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">section<\/span>&gt;<\/span>\n\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-12\"><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<p>Bringing it all together, we\u2019ve just built a small Next.js app with light and dark modes. We implement an accessibility-friendly image display that caters for the deuteranopia condition and lastly showed you how to auto-generate alt texts for your images using Cloudinary. Here\u2019s a working demo for your convenience.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/cloudinary-marketing-res.cloudinary.com\/image\/upload\/c_limit,w_2000\/f_auto\/q_auto\/media_jams\/s_30D71BF39FD8935B4F27DF889AE6F63AF928BB6E0B9B459BA886817077B341F8_1660338925500_ezgif.com-gif-maker+1.gif\" alt=\"demo of the app\" loading=\"lazy\" class=\"c-transformed-asset\"  width=\"600\" height=\"338\"\/><\/p>\n<p>Feel free to use the <a href=\"https:\/\/github.com\/JohnpaulEze\/next-media-assets\">source code<\/a> via this sandbox and extend it as you see fit.<\/p>\n<\/div>","protected":false},"excerpt":{"rendered":"","protected":false},"author":41,"featured_media":28366,"comment_status":"","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"_cloudinary_featured_overwrite":false,"footnotes":""},"categories":[1],"tags":[337,134,212,246,371],"class_list":["post-28365","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized","tag-accessibility","tag-guest-post","tag-next-js","tag-react","tag-under-review"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v25.6 (Yoast SEO v26.9) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>Improve Image Accessibility with Cloudinary<\/title>\n<meta name=\"description\" content=\"Accessibility is one of the most prominent concerns in modern web development. The need to optimise websites for screen readers and cater for the needs of the visually impaired cannot be overemphasized\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/cloudinary.com\/blog\/guest_post\/improve-image-accessibility-with-cloudinary\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Improve Image Accessibility with Cloudinary\" \/>\n<meta property=\"og:description\" content=\"Accessibility is one of the most prominent concerns in modern web development. The need to optimise websites for screen readers and cater for the needs of the visually impaired cannot be overemphasized\" \/>\n<meta property=\"og:url\" content=\"https:\/\/cloudinary.com\/blog\/guest_post\/improve-image-accessibility-with-cloudinary\/\" \/>\n<meta property=\"og:site_name\" content=\"Cloudinary Blog\" \/>\n<meta property=\"article:published_time\" content=\"2022-08-16T11:26:10+00:00\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:image\" content=\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681923568\/Web_Assets\/blog\/71f84d738e883ddbe15ee9926ef0bd50741dffc8-6000x4000-1_283669db8c\/71f84d738e883ddbe15ee9926ef0bd50741dffc8-6000x4000-1_283669db8c.jpg?_i=AA\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"NewsArticle\",\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/improve-image-accessibility-with-cloudinary\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/improve-image-accessibility-with-cloudinary\/\"},\"author\":{\"name\":\"\",\"@id\":\"\"},\"headline\":\"Improve Image Accessibility with Cloudinary\",\"datePublished\":\"2022-08-16T11:26:10+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/improve-image-accessibility-with-cloudinary\/\"},\"wordCount\":5,\"publisher\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/improve-image-accessibility-with-cloudinary\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681923568\/Web_Assets\/blog\/71f84d738e883ddbe15ee9926ef0bd50741dffc8-6000x4000-1_283669db8c\/71f84d738e883ddbe15ee9926ef0bd50741dffc8-6000x4000-1_283669db8c.jpg?_i=AA\",\"keywords\":[\"Accessibility\",\"Guest Post\",\"Next.js\",\"React\",\"Under Review\"],\"inLanguage\":\"en-US\",\"copyrightYear\":\"2022\",\"copyrightHolder\":{\"@id\":\"https:\/\/cloudinary.com\/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/improve-image-accessibility-with-cloudinary\/\",\"url\":\"https:\/\/cloudinary.com\/blog\/guest_post\/improve-image-accessibility-with-cloudinary\/\",\"name\":\"Improve Image Accessibility with Cloudinary\",\"isPartOf\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/improve-image-accessibility-with-cloudinary\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/improve-image-accessibility-with-cloudinary\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681923568\/Web_Assets\/blog\/71f84d738e883ddbe15ee9926ef0bd50741dffc8-6000x4000-1_283669db8c\/71f84d738e883ddbe15ee9926ef0bd50741dffc8-6000x4000-1_283669db8c.jpg?_i=AA\",\"datePublished\":\"2022-08-16T11:26:10+00:00\",\"description\":\"Accessibility is one of the most prominent concerns in modern web development. The need to optimise websites for screen readers and cater for the needs of the visually impaired cannot be overemphasized\",\"breadcrumb\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/improve-image-accessibility-with-cloudinary\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/cloudinary.com\/blog\/guest_post\/improve-image-accessibility-with-cloudinary\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/improve-image-accessibility-with-cloudinary\/#primaryimage\",\"url\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681923568\/Web_Assets\/blog\/71f84d738e883ddbe15ee9926ef0bd50741dffc8-6000x4000-1_283669db8c\/71f84d738e883ddbe15ee9926ef0bd50741dffc8-6000x4000-1_283669db8c.jpg?_i=AA\",\"contentUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681923568\/Web_Assets\/blog\/71f84d738e883ddbe15ee9926ef0bd50741dffc8-6000x4000-1_283669db8c\/71f84d738e883ddbe15ee9926ef0bd50741dffc8-6000x4000-1_283669db8c.jpg?_i=AA\",\"width\":6000,\"height\":4000},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/improve-image-accessibility-with-cloudinary\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/cloudinary.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Improve Image Accessibility with Cloudinary\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/cloudinary.com\/blog\/#website\",\"url\":\"https:\/\/cloudinary.com\/blog\/\",\"name\":\"Cloudinary Blog\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/cloudinary.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/cloudinary.com\/blog\/#organization\",\"name\":\"Cloudinary Blog\",\"url\":\"https:\/\/cloudinary.com\/blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/cloudinary.com\/blog\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649718331\/Web_Assets\/blog\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877.png?_i=AA\",\"contentUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649718331\/Web_Assets\/blog\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877.png?_i=AA\",\"width\":312,\"height\":60,\"caption\":\"Cloudinary Blog\"},\"image\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#\/schema\/logo\/image\/\"}},{\"@type\":\"Person\",\"@id\":\"\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Improve Image Accessibility with Cloudinary","description":"Accessibility is one of the most prominent concerns in modern web development. The need to optimise websites for screen readers and cater for the needs of the visually impaired cannot be overemphasized","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:\/\/cloudinary.com\/blog\/guest_post\/improve-image-accessibility-with-cloudinary\/","og_locale":"en_US","og_type":"article","og_title":"Improve Image Accessibility with Cloudinary","og_description":"Accessibility is one of the most prominent concerns in modern web development. The need to optimise websites for screen readers and cater for the needs of the visually impaired cannot be overemphasized","og_url":"https:\/\/cloudinary.com\/blog\/guest_post\/improve-image-accessibility-with-cloudinary\/","og_site_name":"Cloudinary Blog","article_published_time":"2022-08-16T11:26:10+00:00","twitter_card":"summary_large_image","twitter_image":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681923568\/Web_Assets\/blog\/71f84d738e883ddbe15ee9926ef0bd50741dffc8-6000x4000-1_283669db8c\/71f84d738e883ddbe15ee9926ef0bd50741dffc8-6000x4000-1_283669db8c.jpg?_i=AA","schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"NewsArticle","@id":"https:\/\/cloudinary.com\/blog\/guest_post\/improve-image-accessibility-with-cloudinary\/#article","isPartOf":{"@id":"https:\/\/cloudinary.com\/blog\/guest_post\/improve-image-accessibility-with-cloudinary\/"},"author":{"name":"","@id":""},"headline":"Improve Image Accessibility with Cloudinary","datePublished":"2022-08-16T11:26:10+00:00","mainEntityOfPage":{"@id":"https:\/\/cloudinary.com\/blog\/guest_post\/improve-image-accessibility-with-cloudinary\/"},"wordCount":5,"publisher":{"@id":"https:\/\/cloudinary.com\/blog\/#organization"},"image":{"@id":"https:\/\/cloudinary.com\/blog\/guest_post\/improve-image-accessibility-with-cloudinary\/#primaryimage"},"thumbnailUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681923568\/Web_Assets\/blog\/71f84d738e883ddbe15ee9926ef0bd50741dffc8-6000x4000-1_283669db8c\/71f84d738e883ddbe15ee9926ef0bd50741dffc8-6000x4000-1_283669db8c.jpg?_i=AA","keywords":["Accessibility","Guest Post","Next.js","React","Under Review"],"inLanguage":"en-US","copyrightYear":"2022","copyrightHolder":{"@id":"https:\/\/cloudinary.com\/#organization"}},{"@type":"WebPage","@id":"https:\/\/cloudinary.com\/blog\/guest_post\/improve-image-accessibility-with-cloudinary\/","url":"https:\/\/cloudinary.com\/blog\/guest_post\/improve-image-accessibility-with-cloudinary\/","name":"Improve Image Accessibility with Cloudinary","isPartOf":{"@id":"https:\/\/cloudinary.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/cloudinary.com\/blog\/guest_post\/improve-image-accessibility-with-cloudinary\/#primaryimage"},"image":{"@id":"https:\/\/cloudinary.com\/blog\/guest_post\/improve-image-accessibility-with-cloudinary\/#primaryimage"},"thumbnailUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681923568\/Web_Assets\/blog\/71f84d738e883ddbe15ee9926ef0bd50741dffc8-6000x4000-1_283669db8c\/71f84d738e883ddbe15ee9926ef0bd50741dffc8-6000x4000-1_283669db8c.jpg?_i=AA","datePublished":"2022-08-16T11:26:10+00:00","description":"Accessibility is one of the most prominent concerns in modern web development. The need to optimise websites for screen readers and cater for the needs of the visually impaired cannot be overemphasized","breadcrumb":{"@id":"https:\/\/cloudinary.com\/blog\/guest_post\/improve-image-accessibility-with-cloudinary\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/cloudinary.com\/blog\/guest_post\/improve-image-accessibility-with-cloudinary\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/cloudinary.com\/blog\/guest_post\/improve-image-accessibility-with-cloudinary\/#primaryimage","url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681923568\/Web_Assets\/blog\/71f84d738e883ddbe15ee9926ef0bd50741dffc8-6000x4000-1_283669db8c\/71f84d738e883ddbe15ee9926ef0bd50741dffc8-6000x4000-1_283669db8c.jpg?_i=AA","contentUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681923568\/Web_Assets\/blog\/71f84d738e883ddbe15ee9926ef0bd50741dffc8-6000x4000-1_283669db8c\/71f84d738e883ddbe15ee9926ef0bd50741dffc8-6000x4000-1_283669db8c.jpg?_i=AA","width":6000,"height":4000},{"@type":"BreadcrumbList","@id":"https:\/\/cloudinary.com\/blog\/guest_post\/improve-image-accessibility-with-cloudinary\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/cloudinary.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Improve Image Accessibility with Cloudinary"}]},{"@type":"WebSite","@id":"https:\/\/cloudinary.com\/blog\/#website","url":"https:\/\/cloudinary.com\/blog\/","name":"Cloudinary Blog","description":"","publisher":{"@id":"https:\/\/cloudinary.com\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/cloudinary.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/cloudinary.com\/blog\/#organization","name":"Cloudinary Blog","url":"https:\/\/cloudinary.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/cloudinary.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649718331\/Web_Assets\/blog\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877.png?_i=AA","contentUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649718331\/Web_Assets\/blog\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877.png?_i=AA","width":312,"height":60,"caption":"Cloudinary Blog"},"image":{"@id":"https:\/\/cloudinary.com\/blog\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":""}]}},"jetpack_featured_media_url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681923568\/Web_Assets\/blog\/71f84d738e883ddbe15ee9926ef0bd50741dffc8-6000x4000-1_283669db8c\/71f84d738e883ddbe15ee9926ef0bd50741dffc8-6000x4000-1_283669db8c.jpg?_i=AA","_links":{"self":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts\/28365","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/users\/41"}],"replies":[{"embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/comments?post=28365"}],"version-history":[{"count":0,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts\/28365\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/media\/28366"}],"wp:attachment":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/media?parent=28365"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/categories?post=28365"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/tags?post=28365"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}