diff --git a/core/themes/claro/claro.theme b/core/themes/claro/claro.theme
index d7783105181fa85de03029a52a9982e1ca91522a..5f772396ef1d08f46ce068569bfa5b8d3f6c90f7 100644
--- a/core/themes/claro/claro.theme
+++ b/core/themes/claro/claro.theme
@@ -17,6 +17,7 @@
 use Drupal\Core\Template\Attribute;
 use Drupal\Core\Url;
 use Drupal\media\MediaForm;
+use Drupal\file\FileInterface;
 
 /**
  * Implements hook_theme_suggestions_HOOK_alter() for form_element.
@@ -1088,23 +1089,13 @@ function claro_preprocess_links__action_links(&$variables) {
  * Implements hook_preprocess_HOOK() for file_managed_file.
  */
 function claro_preprocess_file_managed_file(&$variables) {
-  $element = $variables['element'];
-
-  // Calculate helper values for the template.
-  $upload_is_accessible = !isset($element['upload']['#access']) || $element['upload']['#access'] !== FALSE;
-  $is_multiple = !empty($element['#cardinality']) && $element['#cardinality'] !== 1;
-  $has_value = isset($element['#value']['fids']) && !empty($element['#value']['fids']);
-  $display_can_be_displayed = !empty($element['#display_field']);
-  // Display is rendered in a separate table cell for multiple value widgets.
-  $display_is_visible = $display_can_be_displayed && !$is_multiple && isset($element['display']['#type']) && $element['display']['#type'] !== 'hidden';
-  $description_can_be_displayed = !empty($element['#description_field']);
-  $description_is_visible = $description_can_be_displayed && isset($element['description']);
+  // Produce the same renderable element structure as image widget has.
+  $child_keys = Element::children($variables['element']);
+  foreach ($child_keys as $child_key) {
+    $variables['data'][$child_key] = $variables['element'][$child_key];
+  }
 
-  $variables['multiple'] = $is_multiple;
-  $variables['upload'] = $upload_is_accessible;
-  $variables['has_value'] = $has_value;
-  $variables['has_meta'] = $display_is_visible || $description_is_visible;
-  $variables['display'] = $display_is_visible;
+  _claro_preprocess_file_and_image_widget($variables);
 }
 
 /**
@@ -1183,8 +1174,6 @@ function claro_preprocess_file_widget_multiple(&$variables) {
  * Implements hook_preprocess_HOOK() for image_widget.
  */
 function claro_preprocess_image_widget(&$variables) {
-  $element = $variables['element'];
-
   // Stable adds the file size as #suffix for image file_link renderable array.
   // We have to remove that because we will render it in our file_link template
   // for every kind of files, and not just for images.
@@ -1193,10 +1182,37 @@ function claro_preprocess_image_widget(&$variables) {
     unset($variables['data']['file_' . $file->id()]['filename']['#suffix']);
   }
 
+  _claro_preprocess_file_and_image_widget($variables);
+}
+
+/**
+ * Helper pre-process callback for file_managed_file and image_widget.
+ *
+ * @param array $variables
+ *   The renderable array of image and file widgets, with 'element' and 'data'
+ *   keys.
+ */
+function _claro_preprocess_file_and_image_widget(array &$variables) {
+  $element = $variables['element'];
+  $main_item_keys = [
+    'upload',
+    'upload_button',
+    'remove_button',
+  ];
+
   // Calculate helper values for the template.
   $upload_is_accessible = !isset($element['upload']['#access']) || $element['upload']['#access'] !== FALSE;
   $is_multiple = !empty($element['#cardinality']) && $element['#cardinality'] !== 1;
   $has_value = isset($element['#value']['fids']) && !empty($element['#value']['fids']);
+
+  // File widget properties.
+  $display_can_be_displayed = !empty($element['#display_field']);
+  // Display is rendered in a separate table cell for multiple value widgets.
+  $display_is_visible = $display_can_be_displayed && !$is_multiple && isset($element['display']['#type']) && $element['display']['#type'] !== 'hidden';
+  $description_can_be_displayed = !empty($element['#description_field']);
+  $description_is_visible = $description_can_be_displayed && isset($element['description']);
+
+  // Image widget properties.
   $alt_can_be_displayed = !empty($element['#alt_field']);
   $alt_is_visible = $alt_can_be_displayed && (!isset($element['alt']['#access']) || $element['alt']['#access'] !== FALSE);
   $title_can_be_displayed = !empty($element['#title_field']);
@@ -1205,5 +1221,25 @@ function claro_preprocess_image_widget(&$variables) {
   $variables['multiple'] = $is_multiple;
   $variables['upload'] = $upload_is_accessible;
   $variables['has_value'] = $has_value;
-  $variables['has_meta'] = $alt_is_visible || $title_is_visible;
+  $variables['has_meta'] = $alt_is_visible || $title_is_visible || $display_is_visible || $description_is_visible;
+  $variables['display'] = $display_is_visible;
+
+  // Render file upload input and upload button (or file name and remove button,
+  // if the field is not empty) in an emphasized div.
+  foreach ($variables['data'] as $key => $item) {
+    $item_is_filename = isset($item['filename']['#file']) && $item['filename']['#file'] instanceof FileInterface;
+
+    // Move filename to main items.
+    if ($item_is_filename) {
+      $variables['main_items']['filename'] = $item;
+      unset($variables['data'][$key]);
+      continue;
+    }
+
+    // Move buttons, upload input and hidden items to main items.
+    if (in_array($key, $main_item_keys)) {
+      $variables['main_items'][$key] = $item;
+      unset($variables['data'][$key]);
+    }
+  }
 }
diff --git a/core/themes/claro/css/components/form--managed-file.css b/core/themes/claro/css/components/form--managed-file.css
index 698ce0b73950a33db22a824aa8f4cba4e7cdeb46..4fa4b2ea4118325629be78bb98986a19f565acd1 100644
--- a/core/themes/claro/css/components/form--managed-file.css
+++ b/core/themes/claro/css/components/form--managed-file.css
@@ -266,15 +266,6 @@ td .form-managed-file.no-meta .form-managed-file__image-preview {
   }
 }
 
-/**
- * Remove the default margins of buttons.
- * The '.button' selector is doubled for RTL layouts.
- */
-
-.form-managed-file .button.button {
-  margin: 0;
-}
-
 /**
  * The file upload input.
  */
@@ -285,12 +276,14 @@ td .form-managed-file.no-meta .form-managed-file__image-preview {
 }
 
 /**
- * This applies both on the 'no-js' upload button and the remove button.
- * We don't want to let these to be shrinked.
+ * Remove the default button margins and prevent shrinking or growing buttons.
+ * This applies both on the 'no-js' upload button and the remove button. The
+ * weight of this ruleset has been increase for this to take effect on RTL.
  */
 
-.form-managed-file__main .button {
+.form-managed-file__main .button.button {
   flex: 0 0 auto;
+  margin: 0;
 }
 
 /**
diff --git a/core/themes/claro/css/components/form--managed-file.pcss.css b/core/themes/claro/css/components/form--managed-file.pcss.css
index dfd0f8c34e474f93b52a0b54203d4f0298837003..ae181f469c4cfbc46f385762ef3f07a317418d04 100644
--- a/core/themes/claro/css/components/form--managed-file.pcss.css
+++ b/core/themes/claro/css/components/form--managed-file.pcss.css
@@ -203,14 +203,6 @@ td .form-managed-file.no-meta .form-managed-file__image-preview {
   }
 }
 
-/**
- * Remove the default margins of buttons.
- * The '.button' selector is doubled for RTL layouts.
- */
-.form-managed-file .button.button {
-  margin: 0;
-}
-
 /**
  * The file upload input.
  */
@@ -220,11 +212,13 @@ td .form-managed-file.no-meta .form-managed-file__image-preview {
 }
 
 /**
- * This applies both on the 'no-js' upload button and the remove button.
- * We don't want to let these to be shrinked.
+ * Remove the default button margins and prevent shrinking or growing buttons.
+ * This applies both on the 'no-js' upload button and the remove button. The
+ * weight of this ruleset has been increase for this to take effect on RTL.
  */
-.form-managed-file__main .button {
+.form-managed-file__main .button.button {
   flex: 0 0 auto;
+  margin: 0;
 }
 
 /**
diff --git a/core/themes/claro/css/components/table--file-multiple-widget.css b/core/themes/claro/css/components/table--file-multiple-widget.css
index e24cb0185abf3c6d38d59d598d0b8d0453ae244a..4f3f3558b6fcbaef49579b3504c23e39c3e7bbac 100644
--- a/core/themes/claro/css/components/table--file-multiple-widget.css
+++ b/core/themes/claro/css/components/table--file-multiple-widget.css
@@ -101,7 +101,7 @@
   margin-bottom: 0;
 }
 
-.table-file-multiple-widget .button.button {
+.table-file-multiple-widget .button.button:only-child {
   margin: 0;
 }
 
diff --git a/core/themes/claro/css/components/table--file-multiple-widget.pcss.css b/core/themes/claro/css/components/table--file-multiple-widget.pcss.css
index 436719ec60755e8641529cd62400df49d19fb9b4..d01cabc0570d8224ee9bd13ef8bec046746816a8 100644
--- a/core/themes/claro/css/components/table--file-multiple-widget.pcss.css
+++ b/core/themes/claro/css/components/table--file-multiple-widget.pcss.css
@@ -49,7 +49,7 @@
   margin-bottom: 0;
 }
 
-.table-file-multiple-widget .button.button {
+.table-file-multiple-widget .button.button:only-child {
   margin: 0;
 }
 
diff --git a/core/themes/claro/templates/content-edit/file-managed-file.html.twig b/core/themes/claro/templates/content-edit/file-managed-file.html.twig
index c8341156ee0458324af3d7ec2b813fddbd2a89aa..61826e7a0af5dcaf0c1933d431b1e30fa323f7ab 100644
--- a/core/themes/claro/templates/content-edit/file-managed-file.html.twig
+++ b/core/themes/claro/templates/content-edit/file-managed-file.html.twig
@@ -4,14 +4,18 @@
  * Theme override to display a file form widget.
  *
  * Available variables:
- * - element: Form element for the file upload.
+ * - main_items: Main render elements of the file or image widget:
+ *   file name, upload input, upload and remove buttons and hidden inputs.
+ * - data: Other render elements of the image widget like preview, alt or title,
+ *   or the description input and the display checkbox of the file widget.
+ * - display: A flag indicating whether the display field is visible.
  * - attributes: HTML attributes for the containing element.
  * - multiple: Whether this widget is the part of a multi-value file widget or
  *   not.
  * - upload: Whether the file upload input is displayed or not.
  * - has_value: true if the widget already contains a file.
- * - has_meta: true when the display checkbox or the description input are
- *   enabled and and are visible.
+ * - has_meta: true when the display checkbox or the description, alt or title
+ *   inputs are enabled and at least one of them is visible.
  *
  * @see template_preprocess_file_managed_file()
  * @see claro_preprocess_file_managed_file()
@@ -27,21 +31,37 @@
     has_meta ? 'has-meta' : 'no-meta',
   ]
 %}
-<div{{ attributes.addClass(classes) }}>
+<div{{ attributes.addClass(classes).removeClass('clearfix') }}>
   <div class="form-managed-file__main">
-    {{ element|without('display', 'description')}}
+    {{ main_items.filename }}
+    {{ main_items|without('filename') }}
   </div>
 
-  {% if has_meta %}
-    <div class="form-managed-file__meta-wrapper">
-      <div class="form-managed-file__meta">
+  {% if has_meta or data.preview %}
+  <div class="form-managed-file__meta-wrapper">
+    <div class="form-managed-file__meta">
+      {% if data.preview %}
+        <div class="form-managed-file__image-preview image-preview">
+          <div class="image-preview__img-wrapper">
+            {{ data.preview }}
+          </div>
+        </div>
+      {% endif %}
+
+      {% if data.description or display or data.alt or data.title %}
         <div class="form-managed-file__meta-items">
-          {{ element.description }}
+          {{ data.description }}
           {% if display %}
-            {{ element.display }}
+            {{ data.display }}
           {% endif %}
+          {{ data.alt }}
+          {{ data.title }}
         </div>
-      </div>
+      {% endif %}
     </div>
+  </div>
   {% endif %}
+
+  {# Every third-party addition will be rendered here. #}
+  {{ data|without('preview', 'alt', 'title', 'description', 'display') }}
 </div>
diff --git a/core/themes/claro/templates/content-edit/image-widget.html.twig b/core/themes/claro/templates/content-edit/image-widget.html.twig
index 87fa3b4a218df77bb4e472d293eb8a0039f4bde7..c0189c2c8cad5472ca9a37013d91ca29532cd11d 100644
--- a/core/themes/claro/templates/content-edit/image-widget.html.twig
+++ b/core/themes/claro/templates/content-edit/image-widget.html.twig
@@ -4,56 +4,24 @@
  * Theme override for an image field widget.
  *
  * Available variables:
+ * - main_items: Main render elements of the image widget:
+ *   file name, upload input, upload and remove buttons and hidden inputs.
+ * - data: Other render elements of the image widget like preview, alt or title.
+ * - display: A flag indicating whether the display field is visible.
  * - attributes: HTML attributes for the containing element.
- * - data: Render elements of the image widget.
  * - multiple: Whether this widget is the part of a multi-value file widget or
  *   not.
  * - upload: Whether the file upload input is displayed or not.
- * - has_value: true if the widget already contains an image.
- * - has_meta: true when one of the title or alt inputs are enabled and visible.
+ * - has_value: true if the widget already contains a file.
+ * - has_meta: true when at least one of the alt or title inputs is enabled and
+ *   visible.
  *
  * @see template_preprocess_image_widget()
  * @see stable_preprocess_image_widget()
  * @see claro_preprocess_image_widget()
  */
 #}
-{%
-  set classes = [
-    'form-managed-file--image',
-    multiple ? 'is-multiple' : 'is-single',
-    upload ? 'has-upload' : 'no-upload',
-    has_value ? 'has-value' : 'no-value',
-    has_meta ? 'has-meta' : 'no-meta',
-    data.preview ? 'has-preview' : 'no-preview',
-  ]
-%}
-<div{{ attributes.addClass(classes).removeClass('clearfix') }}>
-  <div class="form-managed-file__main">
-    {{ data|without('preview', 'alt', 'title')}}
-  </div>
 
-  {% if has_meta or data.preview %}
-  <div class="form-managed-file__meta-wrapper">
-    <div class="form-managed-file__meta">
-      {% if data.preview %}
-        <div class="form-managed-file__image-preview image-preview">
-          <div class="image-preview__img-wrapper">
-            {{ data.preview }}
-          </div>
-        </div>
-      {% endif %}
+{% extends '@claro/content-edit/file-managed-file.html.twig' %}
 
-      {% if data.alt or data.title %}
-        <div class="form-managed-file__meta-items">
-      {% endif %}
-
-      {{ data.alt }}
-      {{ data.title }}
-
-      {% if data.alt or data.title %}
-        </div>
-      {% endif %}
-    </div>
-  </div>
-  {% endif %}
-</div>
+{% set attributes = attributes.addClass('form-managed-file--image') %}