{"id":40265,"date":"2026-08-18T07:00:00","date_gmt":"2026-08-18T14:00:00","guid":{"rendered":"https:\/\/cloudinary.com\/blog\/?p=40265"},"modified":"2026-08-17T15:21:39","modified_gmt":"2026-08-17T22:21:39","slug":"flutter-responsive-images-cloudinary","status":"publish","type":"post","link":"https:\/\/cloudinary.com\/blog\/flutter-responsive-images-cloudinary","title":{"rendered":"How to Build a Responsive Image Component in Flutter"},"content":{"rendered":"\n<p>Flutter apps run on phones, tablets, desktops, and TVs. One image size doesn&#8217;t fit all of those screens. A photo that looks great on a phone wastes bandwidth at that same resolution on a tablet, and looks blurry when stretched to a desktop.<\/p>\n\n\n\n<p>In this tutorial, you&#8217;ll build a <code>ResponsiveImage<\/code> widget in Flutter that uses the Cloudinary SDK to dynamically resize, reformat, and optimize images in the cloud before delivering them. The widget detects the device type, selects the right dimensions, and lets Cloudinary handle the transformation. Your app ships smaller images to phones, larger ones to desktops, and the best format for every device.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/github.com\/Princesso\/cloudinary-flutter-responsive-images\" target=\"_blank\" rel=\"noreferrer noopener\"><strong>Source Code<\/strong><\/a><\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">What You&#8217;ll Build<\/h2>\n\n\n\n<p>By the end of this tutorial, you&#8217;ll have a reusable <code>ResponsiveImage<\/code> widget that:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Detects whether the app is running on a phone, tablet, desktop, or TV.<\/li>\n\n\n\n<li>Accepts custom width and height overrides for each device type.<\/li>\n\n\n\n<li>Uses Cloudinary to resize, crop, and optimize the image in the cloud.<\/li>\n\n\n\n<li>Delivers the image in the best format (WebP, AVIF, or JPEG) automatically.<\/li>\n\n\n\n<li>Drops into any Flutter screen with a single widget call.<\/li>\n<\/ul>\n\n\n\n<p>Here&#8217;s the same image served at five different sizes across device simulators:<\/p>\n\n\n\n<div class=\"wp-block-columns is-layout-flex wp-container-core-columns-is-layout-9d6595d7 wp-block-columns-is-layout-flex\">\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/cloudinary-marketing-res.cloudinary.com\/image\/upload\/v1784665487\/blog-How_to_Build_a_Responsive_Image_Component_in_Flutter-1.png\" alt=\"\"\/><\/figure>\n<\/div>\n\n\n\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/cloudinary-marketing-res.cloudinary.com\/image\/upload\/v1784665488\/blog-How_to_Build_a_Responsive_Image_Component_in_Flutter-2.png\" alt=\"\"\/><\/figure>\n<\/div>\n\n\n\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/cloudinary-marketing-res.cloudinary.com\/image\/upload\/v1784665861\/blog-How_to_Build_a_Responsive_Image_Component_in_Flutter-3.png\" alt=\"\"\/><\/figure>\n<\/div>\n<\/div>\n\n\n\n<div class=\"wp-block-columns is-layout-flex wp-container-core-columns-is-layout-9d6595d7 wp-block-columns-is-layout-flex\">\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/cloudinary-marketing-res.cloudinary.com\/image\/upload\/v1784665861\/blog-How_to_Build_a_Responsive_Image_Component_in_Flutter-4.png\" alt=\"\"\/><\/figure>\n<\/div>\n\n\n\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/cloudinary-marketing-res.cloudinary.com\/image\/upload\/v1784665862\/blog-How_to_Build_a_Responsive_Image_Component_in_Flutter-5.png\" alt=\"\"\/><\/figure>\n<\/div>\n<\/div>\n\n\n\n<p>The above are screenshots of same Flutter app running on various simulators, including iPhone, and iPad Simulators, desktop and TV-sized windows.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Prerequisites<\/h2>\n\n\n\n<p>Before you start, make sure you have:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Flutter installed on your machine. If you need to set it up, follow the <a href=\"https:\/\/docs.flutter.dev\/get-started\/install\" target=\"_blank\" rel=\"noreferrer noopener\">Flutter installation guide<\/a>.<\/li>\n\n\n\n<li>A free <a href=\"https:\/\/cloudinary.com\/users\/register\/free\" target=\"_blank\" rel=\"noreferrer noopener\">Cloudinary account<\/a>. (Note your cloud name from the dashboard.)<\/li>\n\n\n\n<li>Basic knowledge of Dart and Flutter widgets.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Step 1: Create the Flutter Project<\/h2>\n\n\n\n<p>Open your terminal and create a new Flutter project:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs shcb-wrap-lines\">flutter create responsive_images\n\ncd responsive_images<\/code><\/span><\/pre>\n\n\n<p>Here&#8217;s a quick overview of the files you&#8217;ll work with:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td><strong>File<\/strong><\/td><td><strong>Purpose<\/strong><\/td><\/tr><tr><td>lib\/main.dart<\/td><td>Main entry point of the app<\/td><\/tr><tr><td>lib\/responsive_image.dart<\/td><td>The responsive image widget you&#8217;ll build<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/cloudinary-marketing-res.cloudinary.com\/image\/upload\/v1784665863\/blog-How_to_Build_a_Responsive_Image_Component_in_Flutter-6.png\" alt=\"Project folder structure in VS Code after running flutter create.\"\/><figcaption class=\"wp-element-caption\">Image showing project folder structure in VS Code after running flutter create.<\/figcaption><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Step 2: Install and Configure the Cloudinary SDK<\/h2>\n\n\n\n<p>Add the Cloudinary Flutter SDK and a device detection package to your <code>pubspec.yaml<\/code>:<\/p>\n\n\n<pre class=\"wp-block-code\" 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\">dependencies<\/span>:\n\n\u00a0 <span class=\"hljs-selector-tag\">flutter<\/span>:\n\n\u00a0 \u00a0 <span class=\"hljs-selector-tag\">sdk<\/span>: <span class=\"hljs-selector-tag\">flutter<\/span>\n\n\u00a0 <span class=\"hljs-selector-tag\">cupertino_icons<\/span>: ^1<span class=\"hljs-selector-class\">.0<\/span><span class=\"hljs-selector-class\">.8<\/span>\n\n\u00a0 # <span class=\"hljs-selector-tag\">Cloudinary<\/span> <span class=\"hljs-selector-tag\">dependencies<\/span>\n\n\u00a0 <span class=\"hljs-selector-tag\">cloudinary_flutter<\/span>: ^1<span class=\"hljs-selector-class\">.3<\/span><span class=\"hljs-selector-class\">.0<\/span>\n\n\u00a0 <span class=\"hljs-selector-tag\">cloudinary_url_gen<\/span>: ^1<span class=\"hljs-selector-class\">.6<\/span><span class=\"hljs-selector-class\">.0<\/span>\n\n\u00a0 # <span class=\"hljs-selector-tag\">Device<\/span> <span class=\"hljs-selector-tag\">detection<\/span> <span class=\"hljs-selector-tag\">for<\/span> <span class=\"hljs-selector-tag\">responsive<\/span> <span class=\"hljs-selector-tag\">images<\/span>\n\n\u00a0 <span class=\"hljs-selector-tag\">device_info_plus<\/span>: ^10<span class=\"hljs-selector-class\">.1<\/span><span class=\"hljs-selector-class\">.2<\/span><\/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\n\n<p>Run <code>flutter pub<\/code> get to install the packages.<\/p>\n\n\n\n<p>Next, configure the Cloudinary instance in your <code>main.dart<\/code> file. Replace the placeholder with your actual cloud name from the Cloudinary dashboard:<\/p>\n\n\n<pre class=\"wp-block-code\" 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-keyword\">import<\/span> <span class=\"hljs-string\">'package:flutter\/material.dart'<\/span>;\n\n<span class=\"hljs-keyword\">import<\/span> <span class=\"hljs-string\">'package:cloudinary_flutter\/cloudinary_context.dart'<\/span>;\n\n<span class=\"hljs-keyword\">import<\/span> <span class=\"hljs-string\">'package:cloudinary_url_gen\/cloudinary.dart'<\/span>;\n\n<span class=\"hljs-keyword\">import<\/span> <span class=\"hljs-string\">'responsive_image.dart'<\/span>;\n\n<span class=\"hljs-keyword\">void<\/span> main() {\n\n\u00a0 CloudinaryContext.cloudinary = Cloudinary.fromStringUrl(\n\n\u00a0 \u00a0 <span class=\"hljs-string\">\"cloudinary:\/\/''@YOUR_CLOUD_NAME?analytics=false\"<\/span>\n\n\u00a0 );\n\n\u00a0 runApp(<span class=\"hljs-keyword\">const<\/span> MyApp());\n\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\n\n<p>If you&#8217;re not sure where to find your cloud name, check the <a target=\"_blank\" href=\"https:\/\/cloudinary.com\/documentation\/developer_onboarding_faq_find_credentials\" rel=\"noreferrer noopener\">Cloudinary credentials guide<\/a>.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/cloudinary-marketing-res.cloudinary.com\/image\/upload\/v1784665863\/blog-How_to_Build_a_Responsive_Image_Component_in_Flutter-7.png\" alt=\"Cloudinary dashboard with the cloud name location highlighted.\"\/><figcaption class=\"wp-element-caption\">Image showing the Cloudinary dashboard with the cloud name location highlighted.<\/figcaption><\/figure>\n\n\n\n<p>That covers the setup. Now you can start building the widget.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 3: Define the Widget API<\/h2>\n\n\n\n<p>Create a new file at <code>lib\/responsive_image.dart<\/code>. Start by defining the configuration classes that control how the widget behaves on each device type:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\">enum DeviceType {\n\n\u00a0 phone,\n\n\u00a0 tablet,\n\n\u00a0 desktop,\n\n\u00a0 tv,\n\n}\n\n<span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">DeviceConfig<\/span> <\/span>{\n\n\u00a0 final int? width;\n\n\u00a0 final int? height;\n\n\u00a0 <span class=\"hljs-keyword\">const<\/span> DeviceConfig({<span class=\"hljs-keyword\">this<\/span>.width, <span class=\"hljs-keyword\">this<\/span>.height});\n\n}\n\n<span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">ResponsiveImageConfig<\/span> <\/span>{\n\n\u00a0 final DeviceConfig? phone;\n\n\u00a0 final DeviceConfig? tablet;\n\n\u00a0 final DeviceConfig? desktop;\n\n\u00a0 final DeviceConfig? tv;\n\n\u00a0 <span class=\"hljs-keyword\">const<\/span> ResponsiveImageConfig({\n\n\u00a0 \u00a0 <span class=\"hljs-keyword\">this<\/span>.phone,\n\n\u00a0 \u00a0 <span class=\"hljs-keyword\">this<\/span>.tablet,\n\n\u00a0 \u00a0 <span class=\"hljs-keyword\">this<\/span>.desktop,\n\n\u00a0 \u00a0 <span class=\"hljs-keyword\">this<\/span>.tv,\n\n\u00a0 });\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\n\n<p>The <code>ResponsiveImageConfig<\/code> class lets you specify different width and height values for each device type. If you don&#8217;t provide a config for a particular device, the widget falls back to the default dimensions.<\/p>\n\n\n\n<p>Now add the base widget structure:<\/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-wrap-lines\"><span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">ResponsiveImage<\/span> <span class=\"hljs-keyword\">extends<\/span> <span class=\"hljs-title\">StatefulWidget<\/span> <\/span>{\n\n\u00a0 final <span class=\"hljs-built_in\">String<\/span> publicId;\n\n\u00a0 final int width;\n\n\u00a0 final int height;\n\n\u00a0 final ResponsiveImageConfig? deviceConfig;\n\n\u00a0 <span class=\"hljs-keyword\">const<\/span> ResponsiveImage({\n\n\u00a0 \u00a0 Key? key,\n\n\u00a0 \u00a0 required <span class=\"hljs-keyword\">this<\/span>.publicId,\n\n\u00a0 \u00a0 required <span class=\"hljs-keyword\">this<\/span>.width,\n\n\u00a0 \u00a0 required <span class=\"hljs-keyword\">this<\/span>.height,\n\n\u00a0 \u00a0 <span class=\"hljs-keyword\">this<\/span>.deviceConfig,\n\n\u00a0 }) : <span class=\"hljs-keyword\">super<\/span>(key: key);\n\n\u00a0 @override\n\n\u00a0 State&lt;ResponsiveImage&gt; createState() =&gt; _ResponsiveImageState();\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\n\n<p>The widget accepts a Cloudinary <code>publicId<\/code>, default width and height, and an optional <code>deviceConfig<\/code> for per-device overrides. In the next step, you&#8217;ll add the device detection logic that makes the widget responsive.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 4: Add Device Detection and Breakpoints<\/h2>\n\n\n\n<p>The widget needs to know what type of device it&#8217;s running on so it can select the right image dimensions. You&#8217;ll use two detection strategies: platform-specific APIs (through the <code>device_info_plus<\/code> package) and screen-size breakpoints as a fallback.<\/p>\n\n\n\n<p>Add the state class with detection logic to <code>lib\/responsive_image.dart<\/code>:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\"><span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">_ResponsiveImageState<\/span> <span class=\"hljs-keyword\">extends<\/span> <span class=\"hljs-title\">State<\/span>&lt;<span class=\"hljs-title\">ResponsiveImage<\/span>&gt; <\/span>{\n\n\u00a0 DeviceType? _deviceType;\n\n\u00a0 @override\n\n\u00a0 <span class=\"hljs-keyword\">void<\/span> initState() {\n\n\u00a0 \u00a0 <span class=\"hljs-keyword\">super<\/span>.initState();\n\n\u00a0 \u00a0 _detectDeviceType();\n\n\u00a0 }\n\n\u00a0 Future&lt;<span class=\"hljs-keyword\">void<\/span>&gt; _detectDeviceType() <span class=\"hljs-keyword\">async<\/span> {\n\n\u00a0 \u00a0 final deviceInfo = DeviceInfoPlugin();\n\n\u00a0 \u00a0 <span class=\"hljs-keyword\">try<\/span> {\n\n\u00a0 \u00a0 \u00a0 <span class=\"hljs-keyword\">if<\/span> (Platform.isAndroid) {\n\n\u00a0 \u00a0 \u00a0 \u00a0 final androidInfo = <span class=\"hljs-keyword\">await<\/span> deviceInfo.androidInfo;\n\n\u00a0 \u00a0 \u00a0 \u00a0 _deviceType = _getDeviceTypeFromScreenSize();\n\n\u00a0 \u00a0 \u00a0 } <span class=\"hljs-keyword\">else<\/span> <span class=\"hljs-keyword\">if<\/span> (Platform.isIOS) {\n\n\u00a0 \u00a0 \u00a0 \u00a0 final iosInfo = <span class=\"hljs-keyword\">await<\/span> deviceInfo.iosInfo;\n\n\u00a0 \u00a0 \u00a0 \u00a0 <span class=\"hljs-keyword\">if<\/span> (iosInfo.model.toLowerCase().contains(<span class=\"hljs-string\">'ipad'<\/span>)) {\n\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 _deviceType = DeviceType.tablet;\n\n\u00a0 \u00a0 \u00a0 \u00a0 } <span class=\"hljs-keyword\">else<\/span> {\n\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 _deviceType = DeviceType.phone;\n\n\u00a0 \u00a0 \u00a0 \u00a0 }\n\n\u00a0 \u00a0 \u00a0 } <span class=\"hljs-keyword\">else<\/span> {\n\n\u00a0 \u00a0 \u00a0 \u00a0 _deviceType = DeviceType.desktop;\n\n\u00a0 \u00a0 \u00a0 }\n\n\u00a0 \u00a0 } <span class=\"hljs-keyword\">catch<\/span> (e) {\n\n\u00a0 \u00a0 \u00a0 _deviceType = _getDeviceTypeFromScreenSize();\n\n\u00a0 \u00a0 }\n\n\u00a0 \u00a0 <span class=\"hljs-keyword\">if<\/span> (mounted) {\n\n\u00a0 \u00a0 \u00a0 setState(() {});\n\n\u00a0 \u00a0 }\n\n\u00a0 }\n\n\u00a0 DeviceType _getDeviceTypeFromScreenSize() {\n\n\u00a0 \u00a0 final screenWidth = MediaQuery.of(context).size.width;\n\n\u00a0 \u00a0 <span class=\"hljs-keyword\">if<\/span> (screenWidth &lt; <span class=\"hljs-number\">768<\/span>) {\n\n\u00a0 \u00a0 \u00a0 <span class=\"hljs-keyword\">return<\/span> DeviceType.phone;\n\n\u00a0 \u00a0 } <span class=\"hljs-keyword\">else<\/span> <span class=\"hljs-keyword\">if<\/span> (screenWidth &gt;= <span class=\"hljs-number\">768<\/span> &amp;&amp; screenWidth &lt; <span class=\"hljs-number\">1024<\/span>) {\n\n\u00a0 \u00a0 \u00a0 <span class=\"hljs-keyword\">return<\/span> DeviceType.tablet;\n\n\u00a0 \u00a0 } <span class=\"hljs-keyword\">else<\/span> <span class=\"hljs-keyword\">if<\/span> (screenWidth &gt;= <span class=\"hljs-number\">1024<\/span> &amp;&amp; screenWidth &lt; <span class=\"hljs-number\">1920<\/span>) {\n\n\u00a0 \u00a0 \u00a0 <span class=\"hljs-keyword\">return<\/span> DeviceType.desktop;\n\n\u00a0 \u00a0 } <span class=\"hljs-keyword\">else<\/span> {\n\n\u00a0 \u00a0 \u00a0 <span class=\"hljs-keyword\">return<\/span> DeviceType.tv;\n\n\u00a0 \u00a0 }\n\n\u00a0 }\n\n\u00a0 DeviceType _getEffectiveDeviceType() {\n\n\u00a0 \u00a0 <span class=\"hljs-keyword\">return<\/span> _deviceType ?? _getDeviceTypeFromScreenSize();\n\n\u00a0 }<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Here&#8217;s how the detection works. On iOS, the widget checks the device model directly. If it contains &#8220;iPad&#8221;, the device type is tablet. Otherwise, it&#8217;s a phone. On Android and all other platforms, the widget falls back to screen-size breakpoints:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td><strong>Screen Width<\/strong><\/td><td><strong>Device Type<\/strong><\/td><\/tr><tr><td>Less than 768px<\/td><td>Phone<\/td><\/tr><tr><td>768px to 1023px<\/td><td>Tablet<\/td><\/tr><tr><td>1024px to 1919px<\/td><td>Desktop<\/td><\/tr><tr><td>1920px and above<\/td><td>TV<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>Now add the <code>_getDimensions<\/code> function that selects the right width and height based on the detected device type:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php shcb-wrap-lines\">DeviceConfig _getDimensions() {\n\n\u00a0 \u00a0 <span class=\"hljs-keyword\">final<\/span> effectiveType = _getEffectiveDeviceType();\n\n\u00a0 \u00a0 <span class=\"hljs-keyword\">if<\/span> (widget.deviceConfig != <span class=\"hljs-keyword\">null<\/span>) {\n\n\u00a0 \u00a0 \u00a0 <span class=\"hljs-keyword\">switch<\/span> (effectiveType) {\n\n\u00a0 \u00a0 \u00a0 \u00a0 <span class=\"hljs-keyword\">case<\/span> DeviceType.phone:\n\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 <span class=\"hljs-keyword\">if<\/span> (widget.deviceConfig!.phone != <span class=\"hljs-keyword\">null<\/span>) {\n\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 <span class=\"hljs-keyword\">return<\/span> DeviceConfig(\n\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 width: widget.deviceConfig!.phone!.width ?? widget.width,\n\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 height: widget.deviceConfig!.phone!.height ?? widget.height,\n\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 );\n\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 }\n\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 <span class=\"hljs-keyword\">break<\/span>;\n\n\u00a0 \u00a0 \u00a0 \u00a0 <span class=\"hljs-keyword\">case<\/span> DeviceType.tablet:\n\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 <span class=\"hljs-keyword\">if<\/span> (widget.deviceConfig!.tablet != <span class=\"hljs-keyword\">null<\/span>) {\n\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 <span class=\"hljs-keyword\">return<\/span> DeviceConfig(\n\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 width: widget.deviceConfig!.tablet!.width ?? widget.width,\n\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 height: widget.deviceConfig!.tablet!.height ?? widget.height,\n\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 );\n\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 }\n\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 <span class=\"hljs-keyword\">break<\/span>;\n\n\u00a0 \u00a0 \u00a0 \u00a0 <span class=\"hljs-keyword\">case<\/span> DeviceType.desktop:\n\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 <span class=\"hljs-keyword\">if<\/span> (widget.deviceConfig!.desktop != <span class=\"hljs-keyword\">null<\/span>) {\n\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 <span class=\"hljs-keyword\">return<\/span> DeviceConfig(\n\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 width: widget.deviceConfig!.desktop!.width ?? widget.width,\n\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 height: widget.deviceConfig!.desktop!.height ?? widget.height,\n\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 );\n\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 }\n\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 <span class=\"hljs-keyword\">break<\/span>;\n\n\u00a0 \u00a0 \u00a0 \u00a0 <span class=\"hljs-keyword\">case<\/span> DeviceType.tv:\n\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 <span class=\"hljs-keyword\">if<\/span> (widget.deviceConfig!.tv != <span class=\"hljs-keyword\">null<\/span>) {\n\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 <span class=\"hljs-keyword\">return<\/span> DeviceConfig(\n\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 width: widget.deviceConfig!.tv!.width ?? widget.width,\n\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 height: widget.deviceConfig!.tv!.height ?? widget.height,\n\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 );\n\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 }\n\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 <span class=\"hljs-keyword\">break<\/span>;\n\n\u00a0 \u00a0 \u00a0 }\n\n\u00a0 \u00a0 }\n\n\u00a0 \u00a0 <span class=\"hljs-keyword\">return<\/span> DeviceConfig(width: widget.width, height: widget.height);\n\n\u00a0 }\n\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>If you pass a <code>ResponsiveImageConfig<\/code> with custom dimensions for a device type, the widget uses those. If not, it falls back to the default width and height. The detection and dimension logic is now complete. The last step is rendering the image with Cloudinary transformations.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 5: Render the Image With Cloudinary Transformations<\/h2>\n\n\n\n<p>Cloudinary applies transformations in the cloud before delivering the image. You don&#8217;t process anything on the client. The widget constructs a transformation request, and Cloudinary returns an optimized image at the exact dimensions you specified.<\/p>\n\n\n\n<p>Three transformations matter here:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Resize.<\/strong> The fill action crops and resizes the image to the dimensions from your breakpoints, maintaining aspect ratio.<\/li>\n\n\n\n<li><strong>Quality.<\/strong> The auto setting lets Cloudinary pick the optimal compression level. This reduces file size without visible quality loss.<\/li>\n\n\n\n<li><strong>Format.<\/strong> The auto setting delivers the image in the best format for the device (WebP, AVIF, or JPEG).<\/li>\n<\/ul>\n\n\n\n<p>Add the build method to your state class:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-7\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php shcb-wrap-lines\">@override\n\nWidget build(BuildContext context) {\n\n\u00a0 <span class=\"hljs-keyword\">final<\/span> dimensions = _getDimensions();\n\n\u00a0 <span class=\"hljs-keyword\">final<\/span> effectiveWidth = dimensions.width ?? widget.width;\n\n\u00a0 <span class=\"hljs-keyword\">final<\/span> effectiveHeight = dimensions.height ?? widget.height;\n\n\u00a0 <span class=\"hljs-keyword\">return<\/span> SizedBox(\n\n\u00a0 \u00a0 width: effectiveWidth.toDouble(),\n\n\u00a0 \u00a0 height: effectiveHeight.toDouble(),\n\n\u00a0 \u00a0 child: CldImageWidget(\n\n\u00a0 \u00a0 \u00a0 publicId: widget.publicId,\n\n\u00a0 \u00a0 \u00a0 transformation: Transformation()\n\n\u00a0 \u00a0 \u00a0 \u00a0 ..resize(Resize.fill()\n\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 ..width(effectiveWidth)\n\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 ..height(effectiveHeight))\n\n\u00a0 \u00a0 \u00a0 \u00a0 ..delivery(Delivery.quality(<span class=\"hljs-string\">'auto'<\/span>))\n\n\u00a0 \u00a0 \u00a0 \u00a0 ..delivery(Delivery.format(<span class=\"hljs-string\">'auto'<\/span>)),\n\n\u00a0 \u00a0 ),\n\n\u00a0 );\n\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-7\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The <code>CldImageWidget<\/code> from the Cloudinary Flutter SDK takes the publicId of your image and the transformation chain. Cloudinary generates the optimized image URL, fetches the transformed image from its CDN, and delivers it to the widget.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/cloudinary-marketing-res.cloudinary.com\/image\/upload\/v1784665864\/blog-How_to_Build_a_Responsive_Image_Component_in_Flutter-8.png\" alt=\"Flutter app with rendered image, alongside the browser DevTools\/network inspector showing the Cloudinary URL with transformation parameters visible.\"\/><figcaption class=\"wp-element-caption\">Flutter app with rendered image, alongside the browser DevTools\/network inspector showing the Cloudinary URL with transformation parameters visible.<\/figcaption><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Step 6: Add a Responsive Image to the Home Screen<\/h2>\n\n\n\n<p>Now you can use the <code>ResponsiveImage<\/code> widget in your app. Update your <code>main.dart<\/code> file with a test image from your Cloudinary account:<\/p>\n\n\n<pre class=\"wp-block-code\" 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-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">MyApp<\/span> <span class=\"hljs-keyword\">extends<\/span> <span class=\"hljs-title\">StatelessWidget<\/span> <\/span>{\n\n\u00a0 <span class=\"hljs-keyword\">const<\/span> MyApp({<span class=\"hljs-keyword\">super<\/span>.key});\n\n\u00a0 @override\n\n\u00a0 Widget build(BuildContext context) {\n\n\u00a0 \u00a0 <span class=\"hljs-keyword\">return<\/span> MaterialApp(\n\n\u00a0 \u00a0 \u00a0 title: <span class=\"hljs-string\">'Flutter Demo'<\/span>,\n\n\u00a0 \u00a0 \u00a0 <span class=\"hljs-attr\">theme<\/span>: ThemeData(\n\n\u00a0 \u00a0 \u00a0 \u00a0 colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),\n\n\u00a0 \u00a0 \u00a0 ),\n\n\u00a0 \u00a0 \u00a0 <span class=\"hljs-attr\">home<\/span>: <span class=\"hljs-keyword\">const<\/span> MyHomePage(title: <span class=\"hljs-string\">'Cloudinary Responsive Images Demo'<\/span>),\n\n\u00a0 \u00a0 );\n\n\u00a0 }\n\n}\n\n<span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">MyHomePage<\/span> <span class=\"hljs-keyword\">extends<\/span> <span class=\"hljs-title\">StatelessWidget<\/span> <\/span>{\n\n\u00a0 <span class=\"hljs-keyword\">const<\/span> MyHomePage({<span class=\"hljs-keyword\">super<\/span>.key, required <span class=\"hljs-keyword\">this<\/span>.title});\n\n\u00a0 final <span class=\"hljs-built_in\">String<\/span> title;\n\n\u00a0 @override\n\n\u00a0 Widget build(BuildContext context) {\n\n\u00a0 \u00a0 <span class=\"hljs-keyword\">return<\/span> Scaffold(\n\n\u00a0 \u00a0 \u00a0 appBar: AppBar(\n\n\u00a0 \u00a0 \u00a0 \u00a0 backgroundColor: Theme.of(context).colorScheme.inversePrimary,\n\n\u00a0 \u00a0 \u00a0 \u00a0 <span class=\"hljs-attr\">title<\/span>: Text(title),\n\n\u00a0 \u00a0 \u00a0 ),\n\n\u00a0 \u00a0 \u00a0 <span class=\"hljs-attr\">body<\/span>: <span class=\"hljs-keyword\">const<\/span> Center(\n\n\u00a0 \u00a0 \u00a0 \u00a0 child: Column(\n\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 mainAxisAlignment: MainAxisAlignment.center,\n\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 <span class=\"hljs-attr\">children<\/span>: <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Widget<\/span>&gt;<\/span>&#91;\n\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 Text(\n\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 'Responsive Cloudinary Images',\n\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold),\n\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 ),\n\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 SizedBox(height: 20),\n\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 Text('This image adapts to your device type:'),\n\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 SizedBox(height: 20),\n\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 ResponsiveImage(\n\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 publicId: 'YOUR_IMAGE_PUBLIC_ID',\n\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 width: 300,\n\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 height: 200,\n\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 deviceConfig: ResponsiveImageConfig(\n\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 phone: DeviceConfig(width: 200, height: 130),\n\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 tablet: DeviceConfig(width: 600, height: 400),\n\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 desktop: DeviceConfig(width: 500, height: 350),\n\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 tv: DeviceConfig(width: 800, height: 600),\n\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 ),\n\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 ),\n\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 ],\n\n\u00a0 \u00a0 \u00a0 \u00a0 ),\n\n\u00a0 \u00a0 \u00a0 ),\n\n\u00a0 \u00a0 );\n\n\u00a0 }\n\n}<\/span><\/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\n\n<p>Replace <code>YOUR_IMAGE_PUBLIC_ID<\/code> with the public ID of an image you&#8217;ve uploaded to your Cloudinary account.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 7: Test on Device Simulators<\/h2>\n\n\n\n<p>Run your app to see the responsive widget in action:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-9\" 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\">code<\/span>&gt;<\/span>flutter run<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">code<\/span>&gt;<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-9\"><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>Flutter shows you the available devices to run on. Select different simulators to verify that the image adapts correctly. The ResponsiveImage widget detects the device type and applies the matching dimensions from your config:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td><strong>Device<\/strong><\/td><td><strong>Dimensions<\/strong><\/td><\/tr><tr><td>iPhone<\/td><td>200 x 130px<\/td><\/tr><tr><td>iPad<\/td><td>600 x 400px<\/td><\/tr><tr><td>Desktop<\/td><td>500 x 350px<\/td><\/tr><tr><td>TV<\/td><td>800 x 600px<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>Open the network inspector in your browser (for Flutter web) or check the Cloudinary console to confirm that different transformation URLs are generated for each device type. You should see different <code>w_<\/code> and <code>h_<\/code> parameters in the URLs.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/cloudinary-marketing-res.cloudinary.com\/image\/upload\/v1784665865\/blog-How_to_Build_a_Responsive_Image_Component_in_Flutter-9.png\" alt=\"Cloudinary transformation URL on network request for iPad simulator.\"\/><figcaption class=\"wp-element-caption\">Cloudinary transformation URL on network request for iPad simulator.<\/figcaption><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">What You Built and Next Steps<\/h2>\n\n\n\n<p>You built a reusable ResponsiveImage widget for Flutter that detects the device type, selects the right dimensions, and uses Cloudinary to transform and deliver optimized images from the cloud. All image processing happens on Cloudinary&#8217;s servers, not on the client.<\/p>\n\n\n\n<p>That means:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>No client-side processing.<\/strong> Images are optimized before delivery.<\/li>\n\n\n\n<li><strong>Automatic format selection.<\/strong> Cloudinary picks WebP, AVIF, or JPEG based on device support.<\/li>\n\n\n\n<li><strong>Dynamic quality optimization.<\/strong> The best balance of visual quality and file size, chosen automatically.<\/li>\n\n\n\n<li><strong>CDN delivery.<\/strong> Images load from the location closest to your customer.<\/li>\n<\/ul>\n\n\n\n<p>Here are a few ways to extend the widget:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Add art direction.<\/strong> Use different Cloudinary crop modes (like thumb or auto) for different device types instead of just resizing.<\/li>\n\n\n\n<li><strong>Support pixel density.<\/strong> Multiply dimensions by MediaQuery.of(context).devicePixelRatio to serve 2x or 3x images on high-DPI screens.<\/li>\n\n\n\n<li><strong>Add placeholder images.<\/strong> Show a low-quality blurred placeholder while the full image loads.<\/li>\n\n\n\n<li><strong>Cache locally.<\/strong> Combine Cloudinary&#8217;s CDN caching with Flutter&#8217;s CachedNetworkImage for offline support.<\/li>\n<\/ul>\n\n\n\n<p>Sign up for a <a target=\"_blank\" href=\"https:\/\/cloudinary.com\/users\/register\/free\" rel=\"noreferrer noopener\">free Cloudinary account<\/a> to try it yourself.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<p><strong>Resources:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/github.com\/Princesso\/cloudinary-flutter-responsive-images\" target=\"_blank\" rel=\"noreferrer noopener\">Full source code on GitHub<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/cloudinary.com\/documentation\/flutter_integration\" target=\"_blank\" rel=\"noreferrer noopener\">Cloudinary Flutter SDK documentation<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/cloudinary.com\/documentation\/image_transformations\" target=\"_blank\" rel=\"noreferrer noopener\">Cloudinary image transformations<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/pub.dev\/packages\/device_info_plus\" target=\"_blank\" rel=\"noreferrer noopener\">Flutter device_info_plus package<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/docs.flutter.dev\/ui\/adaptive-responsive\" target=\"_blank\" rel=\"noreferrer noopener\">Flutter responsive design guide<\/a><\/li>\n<\/ul>\n\n\n\n<style>\n.faqs {\n    padding: 30px 60px;\n    margin-top: 40px;\n    background: var(--color-background-offset);\n    border-radius: 20px;\n}\n\n#frequently_asked_questions {\n    margin-bottom: 20px;\n}\n\n.faq-item {\n    margin-bottom: 12px;\n    border-bottom: 1px solid rgba(128,128,128,.25);\n}\n\n.faq-item summary {\n    cursor: pointer;\n    font-weight: 700;\n    padding: 16px 0;\n    list-style: none;\n}\n\n.faq-item summary::-webkit-details-marker {\n    display: none;\n}\n\n.faq-item summary::after {\n    content: \"+\";\n    float: right;\n    font-size: 1.4rem;\n}\n\n.faq-item[open] summary::after {\n    content: \"\u2212\";\n}\n\n.faq-answer {\n    padding-bottom: 18px;\n}\n<\/style>\n\n<div class=\"faqs\">\n\n<h2 id=\"frequently_asked_questions\">Frequently Asked Questions<\/h2>\n\n<details class=\"faq-item\">\n<summary>Why should Flutter apps use responsive images?<\/summary>\n<div class=\"faq-answer\">\n<p>Serving the same large image to every device wastes bandwidth on smaller screens while potentially reducing image quality on larger displays. Responsive images improve loading performance, reduce data usage, enhance user experience, and help applications scale across Android, iOS, desktop, web, and TV devices.<\/p>\n<\/div>\n<\/details>\n\n<details class=\"faq-item\">\n<summary>How does Cloudinary optimize images for Flutter applications?<\/summary>\n<div class=\"faq-answer\">\n<p>Cloudinary performs <a href=\"https:\/\/cloudinary.com\/documentation\/image_transformations\">image transformations<\/a> in the cloud before delivery. Developers can automatically resize, crop, optimize quality, convert formats, and deliver images through Cloudinary&#8217;s global CDN. Using <code>q_auto<\/code> and <code>f_auto<\/code>, <a href=\"https:\/\/cloudinary.com\/documentation\/image_optimization\">Cloudinary automatically selects<\/a> the optimal compression level and image format for each user&#8217;s browser or device.<\/p>\n<\/div>\n<\/details>\n\n<details class=\"faq-item\">\n<summary>What image formats does Cloudinary automatically deliver?<\/summary>\n<div class=\"faq-answer\">\n<p>Cloudinary serves <a href=\"https:\/\/cloudinary.com\/documentation\/image_optimization#automatic_format_selection_f_auto\">modern formats such as AVIF or WebP<\/a> when supported by the device and falls back to JPEG or PNG when necessary. This improves performance without requiring developers to manage multiple image versions.<\/p>\n<\/div>\n<\/details>\n\n<details class=\"faq-item\">\n<summary>Can Cloudinary automatically optimize image quality?<\/summary>\n<div class=\"faq-answer\">\n<p>Yes. Using <code>q_auto<\/code>, Cloudinary analyzes each image and automatically selects an optimal quality level that balances visual fidelity and file size. This helps improve page load times while maintaining <a href=\"https:\/\/cloudinary.com\/documentation\/image_optimization#automatic_quality_selection_q_auto\">excellent image quality across devices<\/a>.<\/p>\n<\/div>\n<\/details>\n\n<details class=\"faq-item\">\n<summary>What are the benefits of using a reusable ResponsiveImage widget?<\/summary>\n<div class=\"faq-answer\">\n<p>A reusable widget centralizes image optimization logic, reduces duplicate code, improves maintainability, and ensures every screen delivers appropriately sized images. Developers can easily customize dimensions for different device classes while allowing Cloudinary to handle optimization, transformations, and CDN delivery automatically.<\/p>\n<\/div>\n<\/details>\n\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Flutter apps run on phones, tablets, desktops, and TVs. One image size doesn&#8217;t fit all of those screens. A photo that looks great on a phone wastes bandwidth at that same resolution on a tablet, and looks blurry when stretched to a desktop. In this tutorial, you&#8217;ll build a ResponsiveImage widget in Flutter that uses [&hellip;]<\/p>\n","protected":false},"author":87,"featured_media":40276,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"_cloudinary_featured_overwrite":false,"footnotes":"","jetpack_post_was_ever_published":false},"categories":[1],"tags":[370,251],"class_list":["post-40265","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized","tag-image","tag-responsive-images"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v28.3 (Yoast SEO v28.3) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>How to Build a Responsive Image Component in Flutter<\/title>\n<meta name=\"description\" content=\"Build a ResponsiveImage widget in Flutter using the Cloudinary SDK. Serve optimized, dynamically resized images based on device type with automatic format and quality selection.\" \/>\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\/flutter-responsive-images-cloudinary\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"How to Build a Responsive Image Component in Flutter\" \/>\n<meta property=\"og:description\" content=\"Build a ResponsiveImage widget in Flutter using the Cloudinary SDK. Serve optimized, dynamically resized images based on device type with automatic format and quality selection.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/cloudinary.com\/blog\/flutter-responsive-images-cloudinary\" \/>\n<meta property=\"og:site_name\" content=\"Cloudinary Blog\" \/>\n<meta property=\"article:published_time\" content=\"2026-08-18T14:00:00+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1784752829\/Web_Assets\/blog\/Blog_Building_a_Responsive_Image_Component_in_Flutter\/Blog_Building_a_Responsive_Image_Component_in_Flutter.jpg?_i=AA\" \/>\n\t<meta property=\"og:image:width\" content=\"2000\" \/>\n\t<meta property=\"og:image:height\" content=\"1100\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"melindapham\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/cloudinary.com\\\/blog\\\/flutter-responsive-images-cloudinary#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/cloudinary.com\\\/blog\\\/flutter-responsive-images-cloudinary\"},\"author\":{\"name\":\"melindapham\",\"@id\":\"https:\\\/\\\/cloudinary.com\\\/blog\\\/#\\\/schema\\\/person\\\/0d5ad601e4c3b5be89245dfb14be42d9\"},\"headline\":\"How to Build a Responsive Image Component in Flutter\",\"datePublished\":\"2026-08-18T14:00:00+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/cloudinary.com\\\/blog\\\/flutter-responsive-images-cloudinary\"},\"wordCount\":1438,\"publisher\":{\"@id\":\"https:\\\/\\\/cloudinary.com\\\/blog\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/cloudinary.com\\\/blog\\\/flutter-responsive-images-cloudinary#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/res.cloudinary.com\\\/cloudinary-marketing\\\/images\\\/f_auto,q_auto\\\/v1784752829\\\/Web_Assets\\\/blog\\\/Blog_Building_a_Responsive_Image_Component_in_Flutter\\\/Blog_Building_a_Responsive_Image_Component_in_Flutter.jpg?_i=AA\",\"keywords\":[\"Image\",\"Responsive Images\"],\"inLanguage\":\"en-US\",\"copyrightYear\":\"2026\",\"copyrightHolder\":{\"@id\":\"https:\\\/\\\/cloudinary.com\\\/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/cloudinary.com\\\/blog\\\/flutter-responsive-images-cloudinary\",\"url\":\"https:\\\/\\\/cloudinary.com\\\/blog\\\/flutter-responsive-images-cloudinary\",\"name\":\"How to Build a Responsive Image Component in Flutter\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/cloudinary.com\\\/blog\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/cloudinary.com\\\/blog\\\/flutter-responsive-images-cloudinary#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/cloudinary.com\\\/blog\\\/flutter-responsive-images-cloudinary#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/res.cloudinary.com\\\/cloudinary-marketing\\\/images\\\/f_auto,q_auto\\\/v1784752829\\\/Web_Assets\\\/blog\\\/Blog_Building_a_Responsive_Image_Component_in_Flutter\\\/Blog_Building_a_Responsive_Image_Component_in_Flutter.jpg?_i=AA\",\"datePublished\":\"2026-08-18T14:00:00+00:00\",\"description\":\"Build a ResponsiveImage widget in Flutter using the Cloudinary SDK. Serve optimized, dynamically resized images based on device type with automatic format and quality selection.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/cloudinary.com\\\/blog\\\/flutter-responsive-images-cloudinary#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/cloudinary.com\\\/blog\\\/flutter-responsive-images-cloudinary\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/cloudinary.com\\\/blog\\\/flutter-responsive-images-cloudinary#primaryimage\",\"url\":\"https:\\\/\\\/res.cloudinary.com\\\/cloudinary-marketing\\\/images\\\/f_auto,q_auto\\\/v1784752829\\\/Web_Assets\\\/blog\\\/Blog_Building_a_Responsive_Image_Component_in_Flutter\\\/Blog_Building_a_Responsive_Image_Component_in_Flutter.jpg?_i=AA\",\"contentUrl\":\"https:\\\/\\\/res.cloudinary.com\\\/cloudinary-marketing\\\/images\\\/f_auto,q_auto\\\/v1784752829\\\/Web_Assets\\\/blog\\\/Blog_Building_a_Responsive_Image_Component_in_Flutter\\\/Blog_Building_a_Responsive_Image_Component_in_Flutter.jpg?_i=AA\",\"width\":2000,\"height\":1100},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/cloudinary.com\\\/blog\\\/flutter-responsive-images-cloudinary#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/cloudinary.com\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"How to Build a Responsive Image Component in Flutter\"}]},{\"@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\":\"https:\\\/\\\/cloudinary.com\\\/blog\\\/#\\\/schema\\\/person\\\/0d5ad601e4c3b5be89245dfb14be42d9\",\"name\":\"melindapham\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/e6f989fa97fe94be61596259d8629c3df65aec4c7da5c0000f90d810f313d4f4?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/e6f989fa97fe94be61596259d8629c3df65aec4c7da5c0000f90d810f313d4f4?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/e6f989fa97fe94be61596259d8629c3df65aec4c7da5c0000f90d810f313d4f4?s=96&d=mm&r=g\",\"caption\":\"melindapham\"}}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"How to Build a Responsive Image Component in Flutter","description":"Build a ResponsiveImage widget in Flutter using the Cloudinary SDK. Serve optimized, dynamically resized images based on device type with automatic format and quality selection.","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\/flutter-responsive-images-cloudinary","og_locale":"en_US","og_type":"article","og_title":"How to Build a Responsive Image Component in Flutter","og_description":"Build a ResponsiveImage widget in Flutter using the Cloudinary SDK. Serve optimized, dynamically resized images based on device type with automatic format and quality selection.","og_url":"https:\/\/cloudinary.com\/blog\/flutter-responsive-images-cloudinary","og_site_name":"Cloudinary Blog","article_published_time":"2026-08-18T14:00:00+00:00","og_image":[{"width":2000,"height":1100,"url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1784752829\/Web_Assets\/blog\/Blog_Building_a_Responsive_Image_Component_in_Flutter\/Blog_Building_a_Responsive_Image_Component_in_Flutter.jpg?_i=AA","type":"image\/jpeg"}],"author":"melindapham","twitter_card":"summary_large_image","schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/cloudinary.com\/blog\/flutter-responsive-images-cloudinary#article","isPartOf":{"@id":"https:\/\/cloudinary.com\/blog\/flutter-responsive-images-cloudinary"},"author":{"name":"melindapham","@id":"https:\/\/cloudinary.com\/blog\/#\/schema\/person\/0d5ad601e4c3b5be89245dfb14be42d9"},"headline":"How to Build a Responsive Image Component in Flutter","datePublished":"2026-08-18T14:00:00+00:00","mainEntityOfPage":{"@id":"https:\/\/cloudinary.com\/blog\/flutter-responsive-images-cloudinary"},"wordCount":1438,"publisher":{"@id":"https:\/\/cloudinary.com\/blog\/#organization"},"image":{"@id":"https:\/\/cloudinary.com\/blog\/flutter-responsive-images-cloudinary#primaryimage"},"thumbnailUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1784752829\/Web_Assets\/blog\/Blog_Building_a_Responsive_Image_Component_in_Flutter\/Blog_Building_a_Responsive_Image_Component_in_Flutter.jpg?_i=AA","keywords":["Image","Responsive Images"],"inLanguage":"en-US","copyrightYear":"2026","copyrightHolder":{"@id":"https:\/\/cloudinary.com\/#organization"}},{"@type":"WebPage","@id":"https:\/\/cloudinary.com\/blog\/flutter-responsive-images-cloudinary","url":"https:\/\/cloudinary.com\/blog\/flutter-responsive-images-cloudinary","name":"How to Build a Responsive Image Component in Flutter","isPartOf":{"@id":"https:\/\/cloudinary.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/cloudinary.com\/blog\/flutter-responsive-images-cloudinary#primaryimage"},"image":{"@id":"https:\/\/cloudinary.com\/blog\/flutter-responsive-images-cloudinary#primaryimage"},"thumbnailUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1784752829\/Web_Assets\/blog\/Blog_Building_a_Responsive_Image_Component_in_Flutter\/Blog_Building_a_Responsive_Image_Component_in_Flutter.jpg?_i=AA","datePublished":"2026-08-18T14:00:00+00:00","description":"Build a ResponsiveImage widget in Flutter using the Cloudinary SDK. Serve optimized, dynamically resized images based on device type with automatic format and quality selection.","breadcrumb":{"@id":"https:\/\/cloudinary.com\/blog\/flutter-responsive-images-cloudinary#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/cloudinary.com\/blog\/flutter-responsive-images-cloudinary"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/cloudinary.com\/blog\/flutter-responsive-images-cloudinary#primaryimage","url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1784752829\/Web_Assets\/blog\/Blog_Building_a_Responsive_Image_Component_in_Flutter\/Blog_Building_a_Responsive_Image_Component_in_Flutter.jpg?_i=AA","contentUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1784752829\/Web_Assets\/blog\/Blog_Building_a_Responsive_Image_Component_in_Flutter\/Blog_Building_a_Responsive_Image_Component_in_Flutter.jpg?_i=AA","width":2000,"height":1100},{"@type":"BreadcrumbList","@id":"https:\/\/cloudinary.com\/blog\/flutter-responsive-images-cloudinary#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/cloudinary.com\/blog\/"},{"@type":"ListItem","position":2,"name":"How to Build a Responsive Image Component in Flutter"}]},{"@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":"https:\/\/cloudinary.com\/blog\/#\/schema\/person\/0d5ad601e4c3b5be89245dfb14be42d9","name":"melindapham","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/e6f989fa97fe94be61596259d8629c3df65aec4c7da5c0000f90d810f313d4f4?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/e6f989fa97fe94be61596259d8629c3df65aec4c7da5c0000f90d810f313d4f4?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/e6f989fa97fe94be61596259d8629c3df65aec4c7da5c0000f90d810f313d4f4?s=96&d=mm&r=g","caption":"melindapham"}}]}},"parsely":{"version":"1.1.0","canonical_url":"https:\/\/cloudinary.com\/blog\/flutter-responsive-images-cloudinary","smart_links":{"inbound":0,"outbound":0},"traffic_boost_suggestions_count":0,"meta":{"@context":"https:\/\/schema.org","@type":"NewsArticle","headline":"How to Build a Responsive Image Component in Flutter","url":"https:\/\/cloudinary.com\/blog\/flutter-responsive-images-cloudinary","mainEntityOfPage":{"@type":"WebPage","@id":"https:\/\/cloudinary.com\/blog\/flutter-responsive-images-cloudinary"},"thumbnailUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1784752829\/Web_Assets\/blog\/Blog_Building_a_Responsive_Image_Component_in_Flutter\/Blog_Building_a_Responsive_Image_Component_in_Flutter.jpg?_i=AA&w=150&h=150&crop=1","image":{"@type":"ImageObject","url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1784752829\/Web_Assets\/blog\/Blog_Building_a_Responsive_Image_Component_in_Flutter\/Blog_Building_a_Responsive_Image_Component_in_Flutter.jpg?_i=AA"},"articleSection":"Uncategorized","author":[{"@type":"Person","name":"melindapham"}],"creator":["melindapham"],"publisher":{"@type":"Organization","name":"Cloudinary Blog","logo":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/v1649718331\/Web_Assets\/blog\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877.png?_i=AA"},"keywords":["image","responsive images"],"dateCreated":"2026-08-18T14:00:00Z","datePublished":"2026-08-18T14:00:00Z","dateModified":"2026-08-18T14:00:00Z"},"rendered":"<meta name=\"parsely-title\" content=\"How to Build a Responsive Image Component in Flutter\" \/>\n<meta name=\"parsely-link\" content=\"https:\/\/cloudinary.com\/blog\/flutter-responsive-images-cloudinary\" \/>\n<meta name=\"parsely-type\" content=\"post\" \/>\n<meta name=\"parsely-image-url\" content=\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1784752829\/Web_Assets\/blog\/Blog_Building_a_Responsive_Image_Component_in_Flutter\/Blog_Building_a_Responsive_Image_Component_in_Flutter.jpg?_i=AA&w=150&amp;h=150&amp;crop=1\" \/>\n<meta name=\"parsely-pub-date\" content=\"2026-08-18T14:00:00Z\" \/>\n<meta name=\"parsely-section\" content=\"Uncategorized\" \/>\n<meta name=\"parsely-tags\" content=\"image,responsive images\" \/>\n<meta name=\"parsely-author\" content=\"melindapham\" \/>","tracker_url":"https:\/\/cdn.parsely.com\/keys\/cloudinary.com\/p.js"},"jetpack_featured_media_url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1784752829\/Web_Assets\/blog\/Blog_Building_a_Responsive_Image_Component_in_Flutter\/Blog_Building_a_Responsive_Image_Component_in_Flutter.jpg?_i=AA","_links":{"self":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts\/40265","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\/87"}],"replies":[{"embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/comments?post=40265"}],"version-history":[{"count":9,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts\/40265\/revisions"}],"predecessor-version":[{"id":40369,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts\/40265\/revisions\/40369"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/media\/40276"}],"wp:attachment":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/media?parent=40265"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/categories?post=40265"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/tags?post=40265"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}