Last active
March 17, 2026 12:58
-
-
Save isuke01/38506fb250c7e9d3245c9e26440eb17b to your computer and use it in GitHub Desktop.
Wordpress Gutenberg: Media and text extend with mobile controls for media part.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| .wp-block-media-text.is-stacked-on-mobile .wp-block-media-text__media, | |
| .wp-block-media-text.is-stacked-on-mobile.has-media-on-the-right .wp-block-media-text__media { | |
| width: var(--mobile-media--width, 100%) !important; | |
| } | |
| .wp-block-media-text.has-mobile-centered-media .wp-block-media-text__media { | |
| align-items: center; | |
| justify-content: center; | |
| margin-left: auto; | |
| margin-right: auto; | |
| } | |
| .wp-block-media-text.has-mobile-centered-media .wp-block-media-text__media img { | |
| margin-left: auto; | |
| margin-right: auto; | |
| } | |
| .wp-block-media-text.has-mobile-top-media.is-stacked-on-mobile .wp-block-media-text__media, | |
| .wp-block-media-text.has-mobile-top-media.is-stacked-on-mobile.has-media-on-the-right .wp-block-media-text__media { | |
| grid-row: 1; | |
| order: -1; | |
| } | |
| .wp-block-media-text.has-mobile-top-media.is-stacked-on-mobile .wp-block-media-text__content, | |
| .wp-block-media-text.has-mobile-top-media.is-stacked-on-mobile.has-media-on-the-right .wp-block-media-text__content { | |
| grid-row: 2; | |
| } | |
| /* OPTIONAL EDITOR STYLES: Add % after the numer in range selector. */ | |
| .mobile-media-width-range-control .components-input-control__container { | |
| position: relative; | |
| } | |
| .mobile-media-width-range-control .components-input-control__container:not(:hover)::after { | |
| color: #757575; | |
| content: "%"; | |
| pointer-events: none; | |
| position: absolute; | |
| right: 10px; | |
| top: 50%; | |
| transform: translateY(-50%); | |
| } | |
| .mobile-media-width-range-control .components-input-control__input { | |
| padding-right: 20px; | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| * WordPress dependencies | |
| */ | |
| import { addFilter } from '@wordpress/hooks'; | |
| import { __ } from '@wordpress/i18n'; | |
| import { createHigherOrderComponent } from '@wordpress/compose'; | |
| import { Fragment } from '@wordpress/element'; | |
| import { InspectorControls } from '@wordpress/block-editor'; | |
| import { PanelBody, RangeControl, ToggleControl } from '@wordpress/components'; | |
| const MOBILE_MEDIA_WIDTH_ATTRIBUTE = 'mobileMediaWidth'; | |
| const MOBILE_CENTER_MEDIA_ATTRIBUTE = 'mobile_center_media'; | |
| const MOBILE_TOP_MEDIA_ATTRIBUTE = 'mobile_top_media'; | |
| const TARGET_BLOCK = 'core/media-text'; | |
| const MOBILE_CENTER_MEDIA_CLASS = 'has-mobile-centered-media'; | |
| const MOBILE_TOP_MEDIA_CLASS = 'has-mobile-top-media'; | |
| /** | |
| * Add custom attribute for mobile media width. | |
| * | |
| * @param {Object} settings Block settings. | |
| * @param {string} name Block name. | |
| * @return {Object} Updated block settings. | |
| */ | |
| function addMobileMediaWidthAttribute(settings, name) { | |
| if (name !== TARGET_BLOCK) { | |
| return settings; | |
| } | |
| return { | |
| ...settings, | |
| attributes: { | |
| ...settings.attributes, | |
| [MOBILE_MEDIA_WIDTH_ATTRIBUTE]: { | |
| type: 'number', | |
| }, | |
| [MOBILE_CENTER_MEDIA_ATTRIBUTE]: { | |
| type: 'boolean', | |
| }, | |
| [MOBILE_TOP_MEDIA_ATTRIBUTE]: { | |
| type: 'boolean', | |
| }, | |
| }, | |
| }; | |
| } | |
| /** | |
| * Add inspector control for mobile media width. | |
| */ | |
| const withMobileMediaWidthControl = createHigherOrderComponent( | |
| (BlockEdit) => (props) => { | |
| if (props.name !== TARGET_BLOCK) { | |
| return <BlockEdit {...props} />; | |
| } | |
| const { attributes, setAttributes } = props; | |
| const { | |
| mobileMediaWidth, | |
| isStackedOnMobile, | |
| [MOBILE_CENTER_MEDIA_ATTRIBUTE]: mobileCenterMedia, | |
| [MOBILE_TOP_MEDIA_ATTRIBUTE]: mobileTopMedia, | |
| } = attributes; | |
| const controlValue = | |
| typeof mobileMediaWidth === 'number' ? mobileMediaWidth : 100; | |
| return ( | |
| <Fragment> | |
| <BlockEdit {...props} /> | |
| <InspectorControls> | |
| <PanelBody | |
| title={__('Mobile media settings', 'block-theme')} | |
| initialOpen={true} | |
| > | |
| <RangeControl | |
| className="mobile-media-width-range-control" | |
| label={__('Mobile media width', 'block-theme')} | |
| value={controlValue} | |
| renderTooltipContent={(value) => `${value}%`} | |
| onChange={(value) => | |
| setAttributes({ | |
| [MOBILE_MEDIA_WIDTH_ATTRIBUTE]: value, | |
| }) | |
| } | |
| min={1} | |
| max={100} | |
| allowReset={false} | |
| /> | |
| <ToggleControl | |
| label={__('Center media', 'block-theme')} | |
| checked={!!mobileCenterMedia} | |
| onChange={(value) => | |
| setAttributes({ | |
| [MOBILE_CENTER_MEDIA_ATTRIBUTE]: value, | |
| }) | |
| } | |
| /> | |
| {isStackedOnMobile && ( | |
| <ToggleControl | |
| label={__('Show image on top', 'block-theme')} | |
| checked={!!mobileTopMedia} | |
| onChange={(value) => | |
| setAttributes({ | |
| [MOBILE_TOP_MEDIA_ATTRIBUTE]: value, | |
| }) | |
| } | |
| /> | |
| )} | |
| </PanelBody> | |
| </InspectorControls> | |
| </Fragment> | |
| ); | |
| }, | |
| 'withMobileMediaWidthControl', | |
| ); | |
| /** | |
| * Persist CSS custom property on saved block markup. | |
| * | |
| * @param {Object} extraProps Block save props. | |
| * @param {Object} blockType Block type object. | |
| * @param {Object} attributes Block attributes. | |
| * @return {Object} Updated save props. | |
| */ | |
| function addMobileMediaWidthStyle(extraProps, blockType, attributes) { | |
| if (blockType?.name !== TARGET_BLOCK) { | |
| return extraProps; | |
| } | |
| const mobileMediaWidth = attributes?.[MOBILE_MEDIA_WIDTH_ATTRIBUTE]; | |
| const isStackedOnMobile = !!attributes?.isStackedOnMobile; | |
| const classes = [extraProps.className || '']; | |
| if (attributes?.[MOBILE_CENTER_MEDIA_ATTRIBUTE]) { | |
| classes.push(MOBILE_CENTER_MEDIA_CLASS); | |
| } | |
| if (isStackedOnMobile && attributes?.[MOBILE_TOP_MEDIA_ATTRIBUTE]) { | |
| classes.push(MOBILE_TOP_MEDIA_CLASS); | |
| } | |
| const nextExtraProps = { | |
| ...extraProps, | |
| className: classes.join(' ').trim(), | |
| }; | |
| if (typeof mobileMediaWidth !== 'number') { | |
| return nextExtraProps; | |
| } | |
| return { | |
| ...nextExtraProps, | |
| style: { | |
| ...(extraProps.style || {}), | |
| '--mobile-media--width': `${mobileMediaWidth}%`, | |
| }, | |
| }; | |
| } | |
| /** | |
| * Apply CSS custom property in editor preview wrapper. | |
| */ | |
| const withMobileMediaWidthEditorStyle = createHigherOrderComponent( | |
| (BlockListBlock) => (props) => { | |
| if (props.name !== TARGET_BLOCK) { | |
| return <BlockListBlock {...props} />; | |
| } | |
| const mobileMediaWidth = | |
| props.attributes?.[MOBILE_MEDIA_WIDTH_ATTRIBUTE]; | |
| const isStackedOnMobile = !!props.attributes?.isStackedOnMobile; | |
| const mobileCenterMedia = | |
| props.attributes?.[MOBILE_CENTER_MEDIA_ATTRIBUTE]; | |
| const mobileTopMedia = props.attributes?.[MOBILE_TOP_MEDIA_ATTRIBUTE]; | |
| const classNames = [props.wrapperProps?.className || '']; | |
| if (mobileCenterMedia) { | |
| classNames.push(MOBILE_CENTER_MEDIA_CLASS); | |
| } | |
| if (isStackedOnMobile && mobileTopMedia) { | |
| classNames.push(MOBILE_TOP_MEDIA_CLASS); | |
| } | |
| const wrapperProps = { | |
| ...(props.wrapperProps || {}), | |
| className: classNames.join(' ').trim(), | |
| }; | |
| if (typeof mobileMediaWidth !== 'number') { | |
| return <BlockListBlock {...props} wrapperProps={wrapperProps} />; | |
| } | |
| wrapperProps.style = { | |
| ...(props.wrapperProps?.style || {}), | |
| '--mobile-media--width': `${mobileMediaWidth}%`, | |
| }; | |
| return <BlockListBlock {...props} wrapperProps={wrapperProps} />; | |
| }, | |
| 'withMobileMediaWidthEditorStyle', | |
| ); | |
| addFilter( | |
| 'blocks.registerBlockType', | |
| 'block-theme/media-text-mobile-media-width-attribute', | |
| addMobileMediaWidthAttribute, | |
| ); | |
| addFilter( | |
| 'editor.BlockEdit', | |
| 'block-theme/media-text-mobile-media-width-control', | |
| withMobileMediaWidthControl, | |
| ); | |
| addFilter( | |
| 'editor.BlockListBlock', | |
| 'block-theme/media-text-mobile-media-width-editor-style', | |
| withMobileMediaWidthEditorStyle, | |
| ); | |
| addFilter( | |
| 'blocks.getSaveContent.extraProps', | |
| 'block-theme/media-text-mobile-media-width-style', | |
| addMobileMediaWidthStyle, | |
| ); |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
It adds mobile media settings: