diff --git a/config/schema/ui_patterns_settings.sources.schema.yml b/config/schema/ui_patterns_settings.sources.schema.yml
index d26b260542288cc9d019e564e3711165b7ac59df..fd940831072bb980feab1ff73781cd6ad24a1920 100644
--- a/config/schema/ui_patterns_settings.sources.schema.yml
+++ b/config/schema/ui_patterns_settings.sources.schema.yml
@@ -8,3 +8,14 @@ ui_patterns_source.media:
       mapping:
         media_library_selection:
           type: string
+
+ui_patterns_source.media_image_url:
+  type: mapping
+  label: 'Source: Media image URL'
+  mapping:
+    media:
+      type: string
+      label: 'Media ID'
+    image_style:
+      type: string
+      label: 'Image style'
diff --git a/src/Plugin/UiPatterns/Source/MediaImageUrl.php b/src/Plugin/UiPatterns/Source/MediaImageUrl.php
new file mode 100644
index 0000000000000000000000000000000000000000..1d49bad0222fadd266233807d75a5464a485ee11
--- /dev/null
+++ b/src/Plugin/UiPatterns/Source/MediaImageUrl.php
@@ -0,0 +1,219 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Drupal\ui_patterns_settings\Plugin\UiPatterns\Source;
+
+use Drupal\Core\Entity\EntityTypeManagerInterface;
+use Drupal\Core\File\FileUrlGeneratorInterface;
+use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\StringTranslation\TranslatableMarkup;
+use Drupal\file\FileInterface;
+use Drupal\image\ImageStyleInterface;
+use Drupal\media\MediaInterface;
+use Drupal\ui_patterns\Attribute\Source;
+use Drupal\ui_patterns\SourcePluginBase;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * Plugin implementation of the source.
+ */
+#[Source(
+  id: 'media_image_url',
+  label: new TranslatableMarkup('Media: image URL'),
+  description: new TranslatableMarkup('Get an image URL from a media'),
+  prop_types: ['url']
+)]
+class MediaImageUrl extends SourcePluginBase {
+
+  /**
+   * The entity type manager.
+   *
+   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
+   */
+  protected EntityTypeManagerInterface $entityTypeManager;
+
+  /**
+   * The file URL generator.
+   *
+   * @var \Drupal\Core\File\FileUrlGeneratorInterface
+   */
+  protected FileUrlGeneratorInterface $fileUrlGenerator;
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition): static {
+    $plugin = parent::create($container, $configuration, $plugin_id, $plugin_definition);
+    $plugin->entityTypeManager = $container->get('entity_type.manager');
+    $plugin->fileUrlGenerator = $container->get('file_url_generator');
+    return $plugin;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function defaultSettings(): array {
+    return [
+      'media' => NULL,
+      'image_style' => '',
+    ];
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getPropValue(): string {
+    if (!$this->moduleHandler->moduleExists('media')) {
+      return '';
+    }
+
+    $mediaId = $this->getMediaId();
+    if (!$mediaId) {
+      return '';
+    }
+
+    /** @var \Drupal\media\MediaStorage $mediaStorage */
+    $mediaStorage = $this->entityTypeManager->getStorage('media');
+    $media = $mediaStorage->load($mediaId);
+    if (!($media instanceof MediaInterface)) {
+      return '';
+    }
+
+    $fileUri = $this->getFileUri($media);
+    if (!$fileUri) {
+      return '';
+    }
+
+    $imageStyle = $this->getSetting('image_style') ?? '';
+    $style = NULL;
+    if ($imageStyle !== '') {
+      $style = $this->entityTypeManager->getStorage('image_style')
+        ->load($imageStyle);
+    }
+
+    if ($style instanceof ImageStyleInterface) {
+      return $this->fileUrlGenerator->transformRelative($style->buildUrl($fileUri));
+    }
+    else {
+      return $this->fileUrlGenerator->transformRelative($this->fileUrlGenerator->generateString($fileUri));
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function settingsForm(array $form, FormStateInterface $form_state): array {
+    $form = parent::settingsForm($form, $form_state);
+    if (!$this->moduleHandler->moduleExists('media_library_form_element')) {
+      $form['warning'] = [
+        '#theme' => 'status_messages',
+        '#message_list' => [
+          'error' => [
+            $this->t('You need to enable the Media Library Form Element module to use this source.'),
+          ],
+        ],
+      ];
+      return $form;
+    }
+
+    $bundles = $this->getAllowedMediaBundles();
+    if (empty($bundles)) {
+      return $form;
+    }
+
+    $form['media'] = [
+      '#type' => 'media_library',
+      '#allowed_bundles' => $bundles,
+      '#default_value' => $this->getSetting('media') ?? NULL,
+    ];
+    $this->addRequired($form['media']);
+
+    $imageStyles = $this->getAllowedImageStyles();
+    if (empty($imageStyles)) {
+      $form['image_style'] = [
+        '#type' => 'value',
+        '#value' => '',
+      ];
+    }
+    else {
+      $form['image_style'] = [
+        '#type' => 'select',
+        '#title' => $this->t('Image style'),
+        '#options' => $imageStyles,
+        '#default_value' => $this->getSetting('image_style') ?? NULL,
+        '#empty_value' => '',
+        '#empty_option' => $this->t('None'),
+      ];
+    }
+
+    return $form;
+  }
+
+  /**
+   * Get the file URI of the background image.
+   *
+   * @param \Drupal\media\MediaInterface $media
+   *   The referenced media.
+   *
+   * @return string
+   *   The file URI or empty string of not found.
+   */
+  protected function getFileUri(MediaInterface $media): string {
+    foreach ($media->referencedEntities() as $file) {
+      if ($file instanceof FileInterface) {
+        $fileUri = $file->getFileUri();
+        if (is_string($fileUri)) {
+          return $fileUri;
+        }
+      }
+    }
+    return '';
+  }
+
+  /**
+   * Get the allowed media bundles.
+   *
+   * @return array
+   *   The media bundles.
+   */
+  protected function getAllowedMediaBundles(): array {
+    $bundles = [];
+    foreach ($this->entityTypeManager->getStorage('media_type')->loadMultiple() as $mediaType) {
+      $bundles[] = $mediaType->id();
+    }
+    return $bundles;
+  }
+
+  /**
+   * Get the allowed image styles.
+   *
+   * @return array
+   *   The image styles.
+   */
+  protected function getAllowedImageStyles(): array {
+    $imageStyles = [];
+    foreach ($this->entityTypeManager->getStorage('image_style')->loadMultiple() as $style) {
+      $imageStyles[$style->id()] = $style->label();
+    }
+    return $imageStyles;
+  }
+
+  /**
+   * The referenced media ID.
+   *
+   * @return string
+   *   The media ID. Empty string if not found.
+   */
+  protected function getMediaId(): string {
+    $mediaId = $this->getSetting('media') ?? '';
+    if (isset($mediaId['media_library_selection']) && !empty($mediaId['media_library_selection'])) {
+      $mediaId = $mediaId['media_library_selection'];
+    }
+    elseif (!is_string($mediaId)) {
+      $mediaId = '';
+    }
+    return $mediaId;
+  }
+
+}