diff --git a/typo3/sysext/core/Classes/Configuration/Richtext.php b/typo3/sysext/core/Classes/Configuration/Richtext.php
index 8634fc9f0585f3dd601985ee162cb9b00c7c5c5c..77bd51346c33649447834c56f1618c11792a2b68 100644
--- a/typo3/sysext/core/Classes/Configuration/Richtext.php
+++ b/typo3/sysext/core/Classes/Configuration/Richtext.php
@@ -55,60 +55,19 @@ class Richtext
         // together with pageTS, this way it can be overridden and understood in RteHtmlParser.
         // However, all other parts of the core will depend on the non-dotted syntax (coming from Yaml directly)
 
-        if (!isset($tcaFieldConf['richtextConfiguration'])) {
-            $tcaFieldConf['richtextConfiguration'] = 'default';
-        }
-        $usePreset = $tcaFieldConf['richtextConfiguration'];
-        $configuration = $this->loadConfigurationFromPreset($tcaFieldConf['richtextConfiguration']);
+        $pageTs = $this->getPageTsConfiguration($table, $field, $pid, $recordType);
 
-        // Overload with PageTSconfig configuration
-        // First use RTE.*
-        // Then overload with RTE.default
-        // Then overload with RTE.config.tt_content.bodytext
-        // Then overload with RTE.config.tt_content.bodytext.types.textmedia
-        $fullPageTsConfig = $this->getRtePageTsConfigOfPid($pid);
-        $fullPageTsConfig = !empty($fullPageTsConfig['properties']) ? $fullPageTsConfig['properties'] : [];
-        $defaultPageTsConfigOverrides = isset($fullPageTsConfig['default.']) ? $fullPageTsConfig['default.'] : null;
-        $fieldSpecificPageTsConfigOverrides = isset($fullPageTsConfig['config.'][$table . '.'][$field . '.']) ? $fullPageTsConfig['config.'][$table . '.'][$field . '.'] : null;
-        unset($fullPageTsConfig['default.'], $fullPageTsConfig['config.']);
-        // RTE.* (used for RTE.classesAnchor or similar in RTEHtmlArea)
-        if (!empty($fullPageTsConfig)) {
-            ArrayUtility::mergeRecursiveWithOverrule(
-                $configuration,
-                $this->cleanDotsFromEditorConfigKeys($fullPageTsConfig)
-            );
-        }
-        // RTE.default.*
-        if (is_array($defaultPageTsConfigOverrides)) {
-            ArrayUtility::mergeRecursiveWithOverrule(
-                $configuration,
-                $this->cleanDotsFromEditorConfigKeys($defaultPageTsConfigOverrides)
-            );
-        }
-        // RTE.config.tt_content.bodytext and based on type as well
-        if (is_array($fieldSpecificPageTsConfigOverrides)) {
-            $fieldSpecificPageTsConfigOverridesWithoutType = $fieldSpecificPageTsConfigOverrides;
-            unset($fieldSpecificPageTsConfigOverridesWithoutType['types.']);
-            ArrayUtility::mergeRecursiveWithOverrule(
-                $configuration,
-                $this->cleanDotsFromEditorConfigKeys($fieldSpecificPageTsConfigOverridesWithoutType)
-            );
-            if ($recordType
-                && isset($fieldSpecificPageTsConfigOverrides['types.'][$recordType . '.'])
-                && is_array($fieldSpecificPageTsConfigOverrides['types.'][$recordType . '.'])) {
-                ArrayUtility::mergeRecursiveWithOverrule(
-                    $configuration,
-                    $this->cleanDotsFromEditorConfigKeys($fieldSpecificPageTsConfigOverrides['types.'][$recordType . '.'])
-                );
-            }
-        }
+        // determine which preset to use
+        $usePreset = $pageTs['preset'] ?? $tcaFieldConf['richtextConfiguration'] ?? 'default';
 
-        // Reload the base configuration, if overridden via PageTS "RTE.default.preset = Minimal" for instance
-        // However, if a preset is chosen via TSconfig, then it is not possible to override anything else again
-        // via TSconfig (endless loop).
-        if (isset($configuration['preset']) && $usePreset !== $configuration['preset']) {
-            $configuration = $this->loadConfigurationFromPreset($configuration['preset']);
-        }
+        // load configuration from preset
+        $configuration = $this->loadConfigurationFromPreset($usePreset);
+
+        // overlay preset configuration with pageTs
+        ArrayUtility::mergeRecursiveWithOverrule(
+            $configuration,
+            $this->cleanDotsFromEditorConfigKeys($pageTs)
+        );
 
         // Handle "mode" / "transformation" config when overridden
         if (!isset($configuration['proc.']['mode']) && !isset($configuration['proc.']['overruleMode'])) {
@@ -201,4 +160,54 @@ class Richtext
 
         return $typoScriptArray;
     }
+
+    /**
+     * Load PageTS configuration for the RTE
+     *
+     * Return RTE section of page TS, taking into account overloading via table, field and record type
+     *
+     * @param string $table The table the field is in
+     * @param string $field Field name
+     * @param int $pid Real page id
+     * @param string $recordType Record type value
+     * @return array
+     */
+    protected function getPageTsConfiguration(string $table, string $field, int $pid, string $recordType) : array
+    {
+        // Load PageTSconfig configuration
+        $fullPageTsConfig = $this->getRtePageTsConfigOfPid($pid);
+        $fullPageTsConfig = !empty($fullPageTsConfig['properties']) ? $fullPageTsConfig['properties'] : [];
+        $defaultPageTsConfigOverrides = isset($fullPageTsConfig['default.']) ? $fullPageTsConfig['default.'] : null;
+        $fieldSpecificPageTsConfigOverrides = isset($fullPageTsConfig['config.'][$table . '.'][$field . '.']) ? $fullPageTsConfig['config.'][$table . '.'][$field . '.'] : null;
+        unset($fullPageTsConfig['default.'], $fullPageTsConfig['config.']);
+
+        // First use RTE.*
+        $rtePageTsConfiguration = $fullPageTsConfig;
+
+        // Then overload with RTE.default.*
+        if (is_array($defaultPageTsConfigOverrides)) {
+            ArrayUtility::mergeRecursiveWithOverrule($rtePageTsConfiguration, $defaultPageTsConfigOverrides);
+        }
+
+        // Then overload with RTE.config.tt_content.bodytext
+        if (is_array($fieldSpecificPageTsConfigOverrides)) {
+            $fieldSpecificPageTsConfigOverridesWithoutType = $fieldSpecificPageTsConfigOverrides;
+            unset($fieldSpecificPageTsConfigOverridesWithoutType['types.']);
+            ArrayUtility::mergeRecursiveWithOverrule($rtePageTsConfiguration, $fieldSpecificPageTsConfigOverridesWithoutType);
+
+            // Then overload with RTE.config.tt_content.bodytext.types.textmedia
+            if (
+                $recordType
+                && isset($fieldSpecificPageTsConfigOverrides['types.'][$recordType . '.'])
+                && is_array($fieldSpecificPageTsConfigOverrides['types.'][$recordType . '.'])
+            ) {
+                ArrayUtility::mergeRecursiveWithOverrule(
+                    $rtePageTsConfiguration,
+                    $fieldSpecificPageTsConfigOverrides['types.'][$recordType . '.']
+                );
+            }
+        }
+
+        return $rtePageTsConfiguration;
+    }
 }
diff --git a/typo3/sysext/core/Tests/Unit/Configuration/RichtextTest.php b/typo3/sysext/core/Tests/Unit/Configuration/RichtextTest.php
index 4ddd30b19ad781c399d16bfb9d03a1360917d62c..6f05c11c18e71f6ab632dea1c777c47a220cb1bd 100644
--- a/typo3/sysext/core/Tests/Unit/Configuration/RichtextTest.php
+++ b/typo3/sysext/core/Tests/Unit/Configuration/RichtextTest.php
@@ -324,4 +324,57 @@ class RichtextTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase
         $output = $subject->getConfiguration('aTable', 'aField', 42, 'textmedia', $fieldConfig);
         $this->assertSame($expected, $output);
     }
+
+    /**
+     * @test
+     */
+    public function getConfigurationPageTsOverridesPreset()
+    {
+        $pageId = 42;
+        $presetKey = 'default';
+
+        $preset = [
+            'editor' => [
+                'config' => [
+                    'width' => 100
+                ],
+            ],
+        ];
+
+        $pageTsConfigArray = [
+            'properties' => [
+                'preset' => $presetKey,
+                'editor.' => [
+                    'config.' => [
+                        'width' => 200
+                    ],
+                ],
+            ],
+        ];
+
+        $subject = $this->getAccessibleMock(Richtext::class,
+            ['loadConfigurationFromPreset', 'getRtePageTsConfigOfPid'],
+            [],
+            '',
+            false
+            );
+        $subject->expects($this->once())->method('loadConfigurationFromPreset')->with($presetKey)->willReturn($preset);
+        $subject->expects($this->once())->method('getRtePageTsConfigOfPid')->with($pageId)->willReturn($pageTsConfigArray);
+
+        $output = $subject->getConfiguration('tt_content', 'bodytext', $pageId, 'textmedia', $pageTsConfigArray);
+
+        $expected = [
+            'editor' => [
+                'config' => [
+                    'width' => 200
+                ],
+            ],
+            'preset' => 'default',
+            'proc.' => [
+                'overruleMode' => 'default',
+            ],
+        ];
+
+        $this->assertSame($expected, $output);
+    }
 }