diff --git a/packages/block-editor/src/hooks/font-size.js b/packages/block-editor/src/hooks/font-size.js
new file mode 100644
index 0000000000000..ee85b19ae80c1
--- /dev/null
+++ b/packages/block-editor/src/hooks/font-size.js
@@ -0,0 +1,150 @@
+/**
+ * External dependencies
+ */
+import classnames from 'classnames';
+
+/**
+ * WordPress dependencies
+ */
+import { addFilter } from '@wordpress/hooks';
+import { hasBlockSupport } from '@wordpress/blocks';
+import { compose, createHigherOrderComponent } from '@wordpress/compose';
+import { PanelBody } from '@wordpress/components';
+import { __ } from '@wordpress/i18n';
+
+/**
+ * Internal dependencies
+ */
+import {
+ getFontSizeClass,
+ FontSizePicker,
+ withFontSizes,
+} from '../components/font-sizes';
+import InspectorControls from '../components/inspector-controls';
+
+const FONT_SIZE_SUPPORT_KEY = '__experimentalFontSize';
+
+/**
+ * Filters registered block settings, extending attributes to include
+ * `fontSize` and `fontWeight` attributes.
+ *
+ * @param {Object} settings Original block settings
+ * @return {Object} Filtered block settings
+ */
+function addAttributes( settings ) {
+ if ( ! hasBlockSupport( settings, FONT_SIZE_SUPPORT_KEY ) ) {
+ return settings;
+ }
+
+ // Allow blocks to specify a default value if needed.
+ if ( ! settings.attributes.fontSize ) {
+ Object.assign( settings.attributes, {
+ fontSize: {
+ type: 'string',
+ },
+ } );
+ }
+
+ return settings;
+}
+
+/**
+ * Override props assigned to save component to inject font size.
+ *
+ * @param {Object} props Additional props applied to save element
+ * @param {Object} blockType Block type
+ * @param {Object} attributes Block attributes
+ * @return {Object} Filtered props applied to save element
+ */
+function addSaveProps( props, blockType, attributes ) {
+ if ( ! hasBlockSupport( blockType, FONT_SIZE_SUPPORT_KEY ) ) {
+ return props;
+ }
+
+ const { fontSize } = attributes;
+
+ const fontSizeClass = getFontSizeClass( fontSize );
+
+ props.className = classnames( props.className, fontSizeClass );
+
+ return props;
+}
+
+/**
+ * Filters registered block settings to expand the block edit wrapper
+ * by applying the desired styles and classnames.
+ *
+ * @param {Object} settings Original block settings
+ * @return {Object} Filtered block settings
+ */
+function addEditProps( settings ) {
+ if ( ! hasBlockSupport( settings, FONT_SIZE_SUPPORT_KEY ) ) {
+ return settings;
+ }
+
+ const existingGetEditWrapperProps = settings.getEditWrapperProps;
+ settings.getEditWrapperProps = ( attributes ) => {
+ let props = {};
+ if ( existingGetEditWrapperProps ) {
+ props = existingGetEditWrapperProps( attributes );
+ }
+ return addSaveProps( props, settings, attributes );
+ };
+
+ return settings;
+}
+
+const FontSizeInspectorControl = ( { fontSize, setFontSize } ) => (
+
+
+
+
+
+);
+
+/**
+ * Override the default edit UI to include inspector controls
+ * for font size, if block defines support.
+ *
+ * @param {Function} BlockEdit Original component
+ * @return {Function} Wrapped component
+ */
+const withBlockControls = createHigherOrderComponent(
+ ( BlockEdit ) => ( props ) => {
+ const { name: blockName, fontSize, setFontSize } = props;
+
+ if ( ! hasBlockSupport( blockName, FONT_SIZE_SUPPORT_KEY ) ) {
+ return ;
+ }
+
+ return [
+ ,
+ ,
+ ];
+ },
+ 'withFontSizeControlsTest'
+);
+
+addFilter(
+ 'blocks.registerBlockType',
+ 'core/font/addAttribute',
+ addAttributes
+);
+
+addFilter(
+ 'blocks.getSaveContent.extraProps',
+ 'core/font/addSaveProps',
+ addSaveProps
+);
+
+addFilter( 'blocks.registerBlockType', 'core/font/addEditProps', addEditProps );
+
+addFilter(
+ 'editor.BlockEdit',
+ 'core/font/with-block-controls',
+ compose( [ withFontSizes( 'fontSize' ), withBlockControls ] )
+);
diff --git a/packages/block-editor/src/hooks/index.js b/packages/block-editor/src/hooks/index.js
index 76897c0966921..5d9b2f5393a8d 100644
--- a/packages/block-editor/src/hooks/index.js
+++ b/packages/block-editor/src/hooks/index.js
@@ -7,5 +7,6 @@ import './custom-class-name';
import './generated-class-name';
import './style';
import './color';
+import './font-size';
export { AlignmentHookSettingsProvider };
diff --git a/packages/block-library/src/paragraph/block.json b/packages/block-library/src/paragraph/block.json
index 4f1d668b7c4d5..22d1cac167312 100644
--- a/packages/block-library/src/paragraph/block.json
+++ b/packages/block-library/src/paragraph/block.json
@@ -30,12 +30,6 @@
"customBackgroundColor": {
"type": "string"
},
- "fontSize": {
- "type": "string"
- },
- "customFontSize": {
- "type": "number"
- },
"direction": {
"type": "string",
"enum": [ "ltr", "rtl" ]
diff --git a/packages/block-library/src/paragraph/edit.js b/packages/block-library/src/paragraph/edit.js
index 105b1a502c763..7415ab8d7b478 100644
--- a/packages/block-library/src/paragraph/edit.js
+++ b/packages/block-library/src/paragraph/edit.js
@@ -11,15 +11,12 @@ import { PanelBody, ToggleControl, ToolbarGroup } from '@wordpress/components';
import {
AlignmentToolbar,
BlockControls,
- FontSizePicker,
InspectorControls,
RichText,
- withFontSizes,
__experimentalUseColors,
__experimentalBlock as Block,
} from '@wordpress/block-editor';
import { createBlock } from '@wordpress/blocks';
-import { compose } from '@wordpress/compose';
import { useSelect } from '@wordpress/data';
import { useEffect, useState, useRef } from '@wordpress/element';
import { formatLtr } from '@wordpress/icons';
@@ -79,7 +76,6 @@ function ParagraphBlock( {
mergeBlocks,
onReplace,
setAttributes,
- setFontSize,
} ) {
const { align, content, dropCap, placeholder, direction } = attributes;
@@ -127,10 +123,6 @@ function ParagraphBlock( {
-