diff --git a/core/modules/responsive_image/src/ResponsiveImageStyleForm.php b/core/modules/responsive_image/src/ResponsiveImageStyleForm.php
index 04241fd..789bbcf 100644
--- a/core/modules/responsive_image/src/ResponsiveImageStyleForm.php
+++ b/core/modules/responsive_image/src/ResponsiveImageStyleForm.php
@@ -114,22 +114,53 @@ public function form(array $form, FormStateInterface $form_state) {
       foreach ($breakpoint->getMultipliers() as $multiplier) {
         $label = $multiplier . ' ' . $breakpoint->getLabel() . ' [' . $breakpoint->getMediaQuery() . ']';
         $form['keyed_styles'][$breakpoint_id][$multiplier] = array(
-          '#type' => 'container',
+          '#type' => 'details',
+          '#title' => $label,
         );
         $image_style_mapping = $responsive_image_style->getImageStyleMapping($breakpoint_id, $multiplier);
-        // @todo The image_mapping_type is only temporarily hardcoded, until
-        // support for the other responsive image mapping type ('sizes') is
-        // added in https://www.drupal.org/node/2334387.
         $form['keyed_styles'][$breakpoint_id][$multiplier]['image_mapping_type'] = array(
-          '#type' => 'value',
-          '#value' => 'image_style',
+          '#title' => $this->t('Type'),
+          '#type' => 'radios',
+          '#options' => array(
+            '_none' => $this->t('Do not use this breakpoint'),
+            'image_style' => $this->t('Use image styles'),
+            'sizes' => $this->t('Use the sizes attribute'),
+          ),
+          '#default_value' => isset($image_style_mapping['image_mapping_type']) ? $image_style_mapping['image_mapping_type'] : '_none',
         );
-        $form['keyed_styles'][$breakpoint_id][$multiplier]['image_mapping'] = array(
+        $form['keyed_styles'][$breakpoint_id][$multiplier]['image_style'] = array(
           '#type' => 'select',
-          '#title' => $label,
+          '#title' => $this->t('Image style'),
           '#options' => $image_styles,
-          '#default_value' => isset($image_style_mapping['image_mapping']) ? $image_style_mapping['image_mapping'] : array(),
+          '#default_value' => isset($image_style_mapping['image_mapping']) && is_string($image_style_mapping['image_mapping']) ? $image_style_mapping['image_mapping'] : '',
           '#description' => $this->t('Select an image style for this breakpoint.'),
+          '#states' => array(
+            'visible' => array(
+              ':input[name="keyed_styles[' . $breakpoint_id . '][' . $multiplier . '][image_mapping_type]"]' => array('value' => 'image_style'),
+            ),
+          ),
+        );
+        $form['keyed_styles'][$breakpoint_id][$multiplier]['sizes'] = array(
+          '#type' => 'textfield',
+          '#title' => $this->t('Sizes'),
+          '#default_value' => isset($image_style_mapping['image_mapping']['sizes']) ? $image_style_mapping['image_mapping']['sizes'] : '',
+          '#description' => $this->t('Enter the value for the sizes attribute (e.g. "(min-width:700px) 700px, 100vw").'),
+          '#states' => array(
+            'visible' => array(
+              ':input[name="keyed_styles[' . $breakpoint_id . '][' . $multiplier . '][image_mapping_type]"]' => array('value' => 'sizes'),
+            ),
+          ),
+        );
+        $form['keyed_styles'][$breakpoint_id][$multiplier]['sizes_image_styles'] = array(
+          '#title' => $this->t('Image styles'),
+          '#type' => 'checkboxes',
+          '#options' => array_diff_key($image_styles, array('' => '')),
+          '#default_value' => isset($image_style_mapping['image_mapping']['sizes_image_styles']) ? $image_style_mapping['image_mapping']['sizes_image_styles'] : array(),
+          '#states' => array(
+            'visible' => array(
+              ':input[name="keyed_styles[' . $breakpoint_id . '][' . $multiplier . '][image_mapping_type]"]' => array('value' => 'sizes'),
+            ),
+          ),
         );
       }
     }
@@ -150,9 +181,6 @@ public function validate(array $form, FormStateInterface $form_state) {
         // Remove the image style mappings since the breakpoint ID has changed.
         $form_state->unsetValue('keyed_styles');
       }
-      // @todo Filter 'sizes_image_styles' to a normal array in
-      // https://www.drupal.org/node/2334387. For an example see
-      // \Drupal\Core\Block\BlockBase::validateConfigurationForm().
     }
   }
 
@@ -167,7 +195,23 @@ public function save(array $form, FormStateInterface $form_state) {
     if ($form_state->hasValue('keyed_styles')) {
       foreach ($form_state->getValue('keyed_styles') as $breakpoint_id => $multipliers) {
         foreach ($multipliers as $multiplier => $image_style_mapping) {
-          $responsive_image_style->addImageStyleMapping($breakpoint_id, $multiplier, $image_style_mapping);
+          if ($image_style_mapping['image_mapping_type'] === 'sizes') {
+            $mapping = array(
+              'image_mapping_type' => 'sizes',
+              'image_mapping' => array(
+                'sizes' => $image_style_mapping['sizes'],
+                'sizes_image_styles' => array_keys(array_filter($image_style_mapping['sizes_image_styles'])),
+              )
+            );
+            $responsive_image_style->addImageStyleMapping($breakpoint_id, $multiplier, $mapping);
+          }
+          else if ($image_style_mapping['image_mapping_type'] === 'image_style') {
+            $mapping = array(
+              'image_mapping_type' => 'image_style',
+              'image_mapping' => $image_style_mapping['image_style'],
+            );
+            $responsive_image_style->addImageStyleMapping($breakpoint_id, $multiplier, $mapping);
+          }
         }
       }
     }
diff --git a/core/modules/responsive_image/src/Tests/ResponsiveImageAdminUITest.php b/core/modules/responsive_image/src/Tests/ResponsiveImageAdminUITest.php
index fae8cf8..5498e2a 100644
--- a/core/modules/responsive_image/src/Tests/ResponsiveImageAdminUITest.php
+++ b/core/modules/responsive_image/src/Tests/ResponsiveImageAdminUITest.php
@@ -79,7 +79,15 @@ public function testResponsiveImageAdmin() {
 
     foreach ($cases as $case) {
       // Check if the radio buttons are present.
-      $this->assertFieldByName('keyed_styles[responsive_image_test_module.' . $case[0] . '][' . $case[1] . '][image_mapping]', '');
+      $this->assertFieldByName('keyed_styles[responsive_image_test_module.' . $case[0] . '][' . $case[1] . '][image_mapping_type]', '');
+      // Check if the image style dropdowns are present.
+      $this->assertFieldByName('keyed_styles[responsive_image_test_module.' . $case[0] . '][' . $case[1] . '][image_style]', '');
+      // Check if the sizes textfields are present.
+      $this->assertFieldByName('keyed_styles[responsive_image_test_module.' . $case[0] . '][' . $case[1] . '][sizes]', '');
+      // Check if the image styles checkboxes are present.
+      foreach (array_keys(image_style_options(FALSE)) as $image_style_name) {
+        $this->assertFieldByName('keyed_styles[responsive_image_test_module.' . $case[0] . '][' . $case[1] . '][sizes_image_styles][' . $image_style_name . ']');
+      }
     }
 
     // Save styles for 1x variant only.
@@ -87,24 +95,35 @@ public function testResponsiveImageAdmin() {
       'label' => 'Style One',
       'breakpoint_group' => 'responsive_image_test_module',
       'fallback_image_style' => 'thumbnail',
-      'keyed_styles[responsive_image_test_module.mobile][1x][image_mapping]' => 'thumbnail',
-      'keyed_styles[responsive_image_test_module.narrow][1x][image_mapping]' => 'medium',
-      'keyed_styles[responsive_image_test_module.wide][1x][image_mapping]' => 'large',
+      'keyed_styles[responsive_image_test_module.mobile][1x][image_mapping_type]' => 'image_style',
+      'keyed_styles[responsive_image_test_module.mobile][1x][image_style]' => 'thumbnail',
+      'keyed_styles[responsive_image_test_module.narrow][1x][image_mapping_type]' => 'sizes',
+      'keyed_styles[responsive_image_test_module.narrow][1x][sizes]' => '(min-width: 700px) 700px, 100vw',
+      'keyed_styles[responsive_image_test_module.narrow][1x][sizes_image_styles][large]' => 'large',
+      'keyed_styles[responsive_image_test_module.narrow][1x][sizes_image_styles][medium]' => 'medium',
+      'keyed_styles[responsive_image_test_module.wide][1x][image_mapping_type]' => 'image_style',
+      'keyed_styles[responsive_image_test_module.wide][1x][image_style]' => 'large',
     );
     $this->drupalPostForm('admin/config/media/responsive-image-style/style_one', $edit, t('Save'));
     $this->drupalGet('admin/config/media/responsive-image-style/style_one');
 
-    // Check the style for multipliers 1x and 2x for the mobile breakpoint.
-    $this->assertFieldByName('keyed_styles[responsive_image_test_module.mobile][1x][image_mapping]', 'thumbnail');
-    $this->assertFieldByName('keyed_styles[responsive_image_test_module.mobile][2x][image_mapping]', '');
-
-    // Check the style for multipliers 1x and 2x for the narrow breakpoint.
-    $this->assertFieldByName('keyed_styles[responsive_image_test_module.narrow][1x][image_mapping]', 'medium');
-    $this->assertFieldByName('keyed_styles[responsive_image_test_module.narrow][2x][image_mapping]', '');
-
-    // Check the style for multipliers 1x and 2x for the wide breakpoint.
-    $this->assertFieldByName('keyed_styles[responsive_image_test_module.wide][1x][image_mapping]', 'large');
-    $this->assertFieldByName('keyed_styles[responsive_image_test_module.wide][2x][image_mapping]', '');
+    // Check the mapping for multipliers 1x and 2x for the mobile breakpoint.
+    $this->assertFieldByName('keyed_styles[responsive_image_test_module.mobile][1x][image_style]', 'thumbnail');
+    $this->assertFieldByName('keyed_styles[responsive_image_test_module.mobile][1x][image_mapping_type]', 'image_style');
+    $this->assertFieldByName('keyed_styles[responsive_image_test_module.mobile][2x][image_mapping_type]', '_none');
+
+    // Check the mapping for multipliers 1x and 2x for the narrow breakpoint.
+    $this->assertFieldByName('keyed_styles[responsive_image_test_module.narrow][1x][image_mapping_type]', 'sizes');
+    $this->assertFieldByName('keyed_styles[responsive_image_test_module.narrow][1x][sizes]', '(min-width: 700px) 700px, 100vw');
+    $this->assertFieldChecked('edit-keyed-styles-responsive-image-test-modulenarrow-1x-sizes-image-styles-large');
+    $this->assertFieldChecked('edit-keyed-styles-responsive-image-test-modulenarrow-1x-sizes-image-styles-medium');
+    $this->assertNoFieldChecked('edit-keyed-styles-responsive-image-test-modulenarrow-1x-sizes-image-styles-thumbnail');
+    $this->assertFieldByName('keyed_styles[responsive_image_test_module.narrow][2x][image_mapping_type]', '_none');
+
+    // Check the mapping for multipliers 1x and 2x for the wide breakpoint.
+    $this->assertFieldByName('keyed_styles[responsive_image_test_module.wide][1x][image_style]', 'large');
+    $this->assertFieldByName('keyed_styles[responsive_image_test_module.wide][1x][image_mapping_type]', 'image_style');
+    $this->assertFieldByName('keyed_styles[responsive_image_test_module.wide][2x][image_mapping_type]', '_none');
 
     // Delete the style.
     $this->drupalGet('admin/config/media/responsive-image-style/style_one/delete');
