diff --git a/packages/base-styles/_z-index.scss b/packages/base-styles/_z-index.scss index 9a3f207b6be01..1fd953b16667c 100644 --- a/packages/base-styles/_z-index.scss +++ b/packages/base-styles/_z-index.scss @@ -46,8 +46,8 @@ $z-layers: ( ".components-drop-zone": 40, ".components-drop-zone__content": 50, - // The block mover for floats should overlap the controls of adjacent blocks. - ".block-editor-block-list__block {core/image aligned left or right}": 21, + // The flotaed blocks should be higher than regular blocks + ".wp-block {aligned left or right}": 21, // Small screen inner blocks overlay must be displayed above drop zone, // settings menu, and movers. diff --git a/packages/block-editor/src/components/block-list/block-wrapper.js b/packages/block-editor/src/components/block-list/block-wrapper.js index 964bef9008420..6912a9eaaac1c 100644 --- a/packages/block-editor/src/components/block-list/block-wrapper.js +++ b/packages/block-editor/src/components/block-list/block-wrapper.js @@ -19,6 +19,7 @@ import { focus, isTextField, placeCaretAtHorizontalEdge } from '@wordpress/dom'; import { BACKSPACE, DELETE, ENTER } from '@wordpress/keycodes'; import { __, sprintf } from '@wordpress/i18n'; import { useSelect, useDispatch } from '@wordpress/data'; +import { hasBlockSupport } from '@wordpress/blocks'; /** * Internal dependencies @@ -49,7 +50,9 @@ const BlockComponent = forwardRef( mode, blockTitle, wrapperProps, + attributes, } = useContext( BlockContext ); + const supportAlignments = hasBlockSupport( name, 'align', false ); const { initialPosition } = useSelect( ( select ) => { if ( ! isSelected ) { @@ -190,7 +193,7 @@ const BlockComponent = forwardRef( const blockElementId = `block-${ clientId }${ htmlSuffix }`; const Animated = animated[ tagName ]; - return ( + const blockContentElement = ( ); + + if ( supportAlignments ) { + return ( +
+ { blockContentElement } +
+ ); + } + + return blockContentElement; } ); diff --git a/packages/block-editor/src/components/block-list/block.js b/packages/block-editor/src/components/block-list/block.js index a78254858437e..a8e32517b6a68 100644 --- a/packages/block-editor/src/components/block-list/block.js +++ b/packages/block-editor/src/components/block-list/block.js @@ -99,7 +99,7 @@ function BlockListBlock( { // Generate the wrapper class names handling the different states of the // block. const wrapperClassName = classnames( - 'wp-block block-editor-block-list__block', + 'block-editor-block-list__block', { 'has-selected-ui': hasSelectedUI, 'has-warning': ! isValid || !! hasError || isUnregisteredBlock, @@ -164,6 +164,7 @@ function BlockListBlock( { mode, blockTitle: blockType.title, wrapperProps, + attributes, }; const memoizedValue = useMemo( () => value, Object.values( value ) ); diff --git a/packages/block-editor/src/components/block-list/style.scss b/packages/block-editor/src/components/block-list/style.scss index 5efdafd8d365c..69818c9f2cae9 100644 --- a/packages/block-editor/src/components/block-list/style.scss +++ b/packages/block-editor/src/components/block-list/style.scss @@ -247,56 +247,6 @@ cursor: default; } - // Alignments. - &[data-align="left"], - &[data-align="right"] { - // Without z-index, won't be clickable as "above" adjacent content. - z-index: z-index(".block-editor-block-list__block {core/image aligned left or right}"); - width: 100%; - - // When images are floated, the block itself should collapse to zero height. - height: 0; - - &::before { - content: none; - } - } - - // Left. - &[data-align="left"] > .is-block-content { - // This is in the editor only; the image should be floated on the frontend. - /*!rtl:begin:ignore*/ - float: left; - margin-right: 2em; - /*!rtl:end:ignore*/ - } - - // Right. - &[data-align="right"] > .is-block-content { - // Right: This is in the editor only; the image should be floated on the frontend. - /*!rtl:begin:ignore*/ - float: right; - margin-left: 2em; - /*!rtl:end:ignore*/ - } - - // Wide and full-wide. - &[data-align="full"], - &[data-align="wide"] { - clear: both; - } - - // Full-wide. - &[data-align="full"] { - margin-left: -$block-padding; - margin-right: -$block-padding; - - @include break-small() { - margin-left: -$block-padding - $block-padding - $block-side-ui-width - $border-width - $border-width; - margin-right: -$block-padding - $block-padding - $block-side-ui-width - $border-width - $border-width; - } - } - // Clear floats. &[data-clear="true"] { float: none; diff --git a/packages/block-editor/src/hooks/align.js b/packages/block-editor/src/hooks/align.js index 8ff4b5232c9f6..ada2948011105 100644 --- a/packages/block-editor/src/hooks/align.js +++ b/packages/block-editor/src/hooks/align.js @@ -88,7 +88,10 @@ export function addAttribute( settings ) { if ( has( settings.attributes, [ 'align', 'type' ] ) ) { return settings; } - if ( hasBlockSupport( settings, 'align' ) ) { + if ( + hasBlockSupport( settings, 'align' ) && + ! hasBlockSupport( settings, 'lightBlockWrapper' ) + ) { // Use Lodash's assign to gracefully handle if attributes are undefined settings.attributes = assign( settings.attributes, { align: { @@ -124,7 +127,8 @@ export const withToolbarControls = createHigherOrderComponent( const validAlignments = isEmbedButton ? [] : getValidAlignments( - getBlockSupport( blockName, 'align' ), + getBlockSupport( blockName, 'align' ) && + ! hasBlockSupport( blockName, 'lightBlockWrapper' ), hasBlockSupport( blockName, 'alignWide', true ) ); @@ -182,7 +186,8 @@ export const withDataAlign = createHigherOrderComponent( } const validAlignments = getValidAlignments( - getBlockSupport( name, 'align' ), + getBlockSupport( name, 'align' ) && + ! hasBlockSupport( name, 'lightBlockWrapper' ), hasBlockSupport( name, 'alignWide', true ), hasWideEnabled ); @@ -207,7 +212,9 @@ export const withDataAlign = createHigherOrderComponent( */ export function addAssignedAlign( props, blockType, attributes ) { const { align } = attributes; - const blockAlign = getBlockSupport( blockType, 'align' ); + const blockAlign = + getBlockSupport( blockType, 'align' ) && + ! hasBlockSupport( blockType, 'lightBlockWrapper' ); const hasWideBlockSupport = hasBlockSupport( blockType, 'alignWide', true ); const isAlignValid = includes( // Compute valid alignments without taking into account, diff --git a/packages/block-editor/src/style.scss b/packages/block-editor/src/style.scss index 14030fb1b1fa5..8ef5a86ac4785 100644 --- a/packages/block-editor/src/style.scss +++ b/packages/block-editor/src/style.scss @@ -56,3 +56,65 @@ @import "./components/editor-skeleton/style.scss"; @import "./components/inserter/style.scss"; + +// Default styles for alignments in case the theme doesn't provide them. +.wp-block { + max-width: $content-width; + margin-left: auto; + margin-right: auto; + margin-top: $default-block-margin; + margin-bottom: $default-block-margin; + + // Floated blocks shouldn't have margins + &[data-align="left"], + &[data-align="right"] { + margin-top: 0; + margin-bottom: 0; + + & > * { + // z-index should be higher than regular blocks to allow selection on click + z-index: z-index(".wp-block {aligned left or right}"); + } + } + + // Left. + &[data-align="left"] > * { + // This is in the editor only; the image should be floated on the frontend. + /*!rtl:begin:ignore*/ + float: left; + margin-right: 2em; + /*!rtl:end:ignore*/ + } + + // Right. + &[data-align="right"] > * { + // Right: This is in the editor only; the image should be floated on the frontend. + /*!rtl:begin:ignore*/ + float: right; + margin-left: 2em; + /*!rtl:end:ignore*/ + } + + &[data-align="full"] { + max-width: none; + clear: both; + + // Leave room for the UI + margin-left: -$block-padding; + margin-right: -$block-padding; + @include break-small() { + margin-left: -$block-padding - $block-padding - $block-side-ui-width - $border-width - $border-width; + margin-right: -$block-padding - $block-padding - $block-side-ui-width - $border-width - $border-width; + } + } + + &[data-align="wide"] { + max-width: 1100px; + clear: both; + } + + &[data-align="center"] { + display: flex; + justify-content: center; + } +} diff --git a/packages/block-library/src/editor.scss b/packages/block-library/src/editor.scss index 6dc247b6d744a..a4aa0f785f274 100644 --- a/packages/block-library/src/editor.scss +++ b/packages/block-library/src/editor.scss @@ -58,13 +58,6 @@ * This allows us to create normalization styles that are easily overridden by editor styles. */ -// Provide every block with a default base margin. This margin provides a consistent spacing -// between blocks in the editor. -.editor-styles-wrapper .block-editor-block-list__block { - margin-top: $default-block-margin; - margin-bottom: $default-block-margin; -} - // This tag marks the end of the styles that apply to editing canvas contents and need to be manipulated when we resize the editor. #end-resizable-editor-section { display: none; diff --git a/packages/block-library/src/image/edit.js b/packages/block-library/src/image/edit.js index 2b065e5cd90ac..13526c34c5171 100644 --- a/packages/block-library/src/image/edit.js +++ b/packages/block-library/src/image/edit.js @@ -426,11 +426,9 @@ export class ImageEdit extends Component { return ( <> { controls } -
- - { mediaPlaceholder } - -
+ + { mediaPlaceholder } + ); } @@ -508,186 +506,183 @@ export class ImageEdit extends Component { return ( <> { controls } -
- - - { ( sizes ) => { - const { - imageWidthWithinContainer, - imageHeightWithinContainer, - imageWidth, - imageHeight, - } = sizes; - - const filename = this.getFilename( url ); - let defaultedAlt; - if ( alt ) { - defaultedAlt = alt; - } else if ( filename ) { - defaultedAlt = sprintf( - __( - 'This image has an empty alt attribute; its file name is %s' - ), - filename - ); - } else { - defaultedAlt = __( - 'This image has an empty alt attribute' - ); - } - - const img = ( - // Disable reason: Image itself is not meant to be interactive, but - // should direct focus to block. - /* eslint-disable jsx-a11y/no-noninteractive-element-interactions */ - <> - { - this.onImageError( url ) - } - /> - { isBlobURL( url ) && } - - /* eslint-enable jsx-a11y/no-noninteractive-element-interactions */ + + + { ( sizes ) => { + const { + imageWidthWithinContainer, + imageHeightWithinContainer, + imageWidth, + imageHeight, + } = sizes; + + const filename = this.getFilename( url ); + let defaultedAlt; + if ( alt ) { + defaultedAlt = alt; + } else if ( filename ) { + defaultedAlt = sprintf( + __( + 'This image has an empty alt attribute; its file name is %s' + ), + filename ); + } else { + defaultedAlt = __( + 'This image has an empty alt attribute' + ); + } - if ( - ! isResizable || - ! imageWidthWithinContainer - ) { - return ( - <> - { getInspectorControls( - imageWidth, - imageHeight - ) } -
- { img } -
- - ); - } - - const currentWidth = - width || imageWidthWithinContainer; - const currentHeight = - height || imageHeightWithinContainer; - - const ratio = imageWidth / imageHeight; - const minWidth = - imageWidth < imageHeight - ? MIN_SIZE - : MIN_SIZE * ratio; - const minHeight = - imageHeight < imageWidth - ? MIN_SIZE - : MIN_SIZE / ratio; - - // With the current implementation of ResizableBox, an image needs an explicit pixel value for the max-width. - // In absence of being able to set the content-width, this max-width is currently dictated by the vanilla editor style. - // The following variable adds a buffer to this vanilla style, so 3rd party themes have some wiggleroom. - // This does, in most cases, allow you to scale the image beyond the width of the main column, though not infinitely. - // @todo It would be good to revisit this once a content-width variable becomes available. - const maxWidthBuffer = maxWidth * 2.5; - - let showRightHandle = false; - let showLeftHandle = false; - - /* eslint-disable no-lonely-if */ - // See https://github.com/WordPress/gutenberg/issues/7584. - if ( align === 'center' ) { - // When the image is centered, show both handles. - showRightHandle = true; - showLeftHandle = true; - } else if ( isRTL ) { - // In RTL mode the image is on the right by default. - // Show the right handle and hide the left handle only when it is aligned left. - // Otherwise always show the left handle. - if ( align === 'left' ) { - showRightHandle = true; - } else { - showLeftHandle = true; - } - } else { - // Show the left handle and hide the right handle only when the image is aligned right. - // Otherwise always show the right handle. - if ( align === 'right' ) { - showLeftHandle = true; - } else { - showRightHandle = true; - } - } - /* eslint-enable no-lonely-if */ + const img = ( + // Disable reason: Image itself is not meant to be interactive, but + // should direct focus to block. + /* eslint-disable jsx-a11y/no-noninteractive-element-interactions */ + <> + { + this.onImageError( url ) + } + /> + { isBlobURL( url ) && } + + /* eslint-enable jsx-a11y/no-noninteractive-element-interactions */ + ); + if ( + ! isResizable || + ! imageWidthWithinContainer + ) { return ( <> { getInspectorControls( imageWidth, imageHeight ) } - { - onResizeStop(); - setAttributes( { - width: parseInt( - currentWidth + - delta.width, - 10 - ), - height: parseInt( - currentHeight + - delta.height, - 10 - ), - } ); - } } - > +
{ img } - +
); - } } -
- { ( ! RichText.isEmpty( caption ) || isSelected ) && ( - - setAttributes( { caption: value } ) + } + + const currentWidth = + width || imageWidthWithinContainer; + const currentHeight = + height || imageHeightWithinContainer; + + const ratio = imageWidth / imageHeight; + const minWidth = + imageWidth < imageHeight + ? MIN_SIZE + : MIN_SIZE * ratio; + const minHeight = + imageHeight < imageWidth + ? MIN_SIZE + : MIN_SIZE / ratio; + + // With the current implementation of ResizableBox, an image needs an explicit pixel value for the max-width. + // In absence of being able to set the content-width, this max-width is currently dictated by the vanilla editor style. + // The following variable adds a buffer to this vanilla style, so 3rd party themes have some wiggleroom. + // This does, in most cases, allow you to scale the image beyond the width of the main column, though not infinitely. + // @todo It would be good to revisit this once a content-width variable becomes available. + const maxWidthBuffer = maxWidth * 2.5; + + let showRightHandle = false; + let showLeftHandle = false; + + /* eslint-disable no-lonely-if */ + // See https://github.com/WordPress/gutenberg/issues/7584. + if ( align === 'center' ) { + // When the image is centered, show both handles. + showRightHandle = true; + showLeftHandle = true; + } else if ( isRTL ) { + // In RTL mode the image is on the right by default. + // Show the right handle and hide the left handle only when it is aligned left. + // Otherwise always show the left handle. + if ( align === 'left' ) { + showRightHandle = true; + } else { + showLeftHandle = true; } - isSelected={ this.state.captionFocused } - inlineToolbar - /> - ) } - { mediaPlaceholder } -
-
+ } else { + // Show the left handle and hide the right handle only when the image is aligned right. + // Otherwise always show the right handle. + if ( align === 'right' ) { + showLeftHandle = true; + } else { + showRightHandle = true; + } + } + /* eslint-enable no-lonely-if */ + + return ( + <> + { getInspectorControls( + imageWidth, + imageHeight + ) } + { + onResizeStop(); + setAttributes( { + width: parseInt( + currentWidth + delta.width, + 10 + ), + height: parseInt( + currentHeight + + delta.height, + 10 + ), + } ); + } } + > + { img } + + + ); + } } + + { ( ! RichText.isEmpty( caption ) || isSelected ) && ( + + setAttributes( { caption: value } ) + } + isSelected={ this.state.captionFocused } + inlineToolbar + /> + ) } + { mediaPlaceholder } + ); /* eslint-enable jsx-a11y/click-events-have-key-events */ diff --git a/packages/block-library/src/image/editor.scss b/packages/block-library/src/image/editor.scss index e23efffc0eb4d..bf1a1bf7b5041 100644 --- a/packages/block-library/src/image/editor.scss +++ b/packages/block-library/src/image/editor.scss @@ -1,10 +1,6 @@ .wp-block-image { position: relative; - // This resets the intrinsic margin on the figure in non-floated, wide, and full-wide alignments. - margin-left: 0; - margin-right: 0; - &.is-transient img { opacity: 0.3; } @@ -39,18 +35,6 @@ display: block; } -.block-editor-block-list__block[data-type="core/image"][data-align="center"] { - .wp-block-image { - margin-left: auto; - margin-right: auto; - } - - &[data-resized="false"] .wp-block-image > div { - margin-left: auto; - margin-right: auto; - } -} - .block-editor-block-list__block[data-type="core/image"] .block-editor-block-toolbar .block-editor-url-input__button-modal { position: absolute; left: 0; @@ -62,26 +46,9 @@ } } -// Although the float markup is different in the editor compared to the frontend, -// this CSS uses the same technique to allow floats in a wide images context. -// That is, the block retains its centering and max-width, and a child inside -// is floated instead of the block itself. -[data-type="core/image"][data-align="center"], -[data-type="core/image"][data-align="left"], -[data-type="core/image"][data-align="right"] { - figure { - margin: 0; - } -} - -[data-type="core/image"][data-align="wide"], -[data-type="core/image"][data-align="full"] { - figure img { +.wp-block[data-align="wide"], +.wp-block[data-align="full"] { + .wp-block-image img { width: 100%; } } - -// This is similar to above but for resized unfloated images only, where the markup is different. -[data-type="core/image"] figure.is-resized { - margin: 0; -} diff --git a/packages/block-library/src/image/index.js b/packages/block-library/src/image/index.js index 4d855ca15cd10..53a8fe040f4cb 100644 --- a/packages/block-library/src/image/index.js +++ b/packages/block-library/src/image/index.js @@ -27,6 +27,7 @@ export const settings = { ], supports: { lightBlockWrapper: true, + align: true, }, example: { attributes: { diff --git a/packages/block-library/src/image/style.scss b/packages/block-library/src/image/style.scss index 98620035a445e..316f116956caa 100644 --- a/packages/block-library/src/image/style.scss +++ b/packages/block-library/src/image/style.scss @@ -1,7 +1,5 @@ .wp-block-image { - // The image block is in a `figure` element, and many themes zero this out. - // This rule explicitly sets it, to ensure at least some bottom-margin in the flow. - margin-bottom: 1em; + margin: 0; img { max-width: 100%; @@ -23,11 +21,6 @@ &.is-resized { display: table; - // The figure is born with left and right margin. - // We remove this by default, and then customize it for left, right, and center. - margin-left: 0; - margin-right: 0; - > figcaption { display: table-caption; caption-side: bottom; diff --git a/packages/edit-post/src/components/visual-editor/style.scss b/packages/edit-post/src/components/visual-editor/style.scss index b29292d18308a..120b69e9adae3 100644 --- a/packages/edit-post/src/components/visual-editor/style.scss +++ b/packages/edit-post/src/components/visual-editor/style.scss @@ -36,13 +36,6 @@ height: 0; } -// The base width of blocks -.edit-post-visual-editor .block-editor-block-list__block { - margin-left: auto; - margin-right: auto; -} - - // The base width of the title should match that of blocks even if it isn't a block. // @todo: This duplicates CSS from line 49 in block-list/style.scss, and should be // removed when the Title field becomes an actual block. diff --git a/packages/edit-post/src/style.scss b/packages/edit-post/src/style.scss index 89e97d1c32b5d..e757b6f45a227 100644 --- a/packages/edit-post/src/style.scss +++ b/packages/edit-post/src/style.scss @@ -98,62 +98,3 @@ body.block-editor-page { height: 100%; } } - - -// These are default block editor styles in case the theme doesn't provide them. -.wp-block { - max-width: $content-width; - - &[data-align="wide"] { - max-width: 1100px; - } - - &[data-align="full"] { - max-width: none; - } -} - -.wp-align-wrapper { - max-width: $content-width; - margin-left: auto; - margin-right: auto; - - > .wp-block, - &.wp-align-full { - max-width: none; - } - - &.wp-align-full { - margin-left: -$block-padding; - margin-right: -$block-padding; - - @include break-small() { - margin-left: -$block-padding - $block-padding - $block-side-ui-width - $border-width - $border-width; - margin-right: -$block-padding - $block-padding - $block-side-ui-width - $border-width - $border-width; - } - } - - &.wp-align-wide { - max-width: 1100px; - } - - &.wp-align-left > * { - float: left; - margin-right: 2em; - } - - &.wp-align-right > * { - float: right; - margin-left: 2em; - } - - &.wp-align-left > *, - &.wp-align-right > * { - // Without z-index, won't be clickable as "above" adjacent content. - z-index: z-index(".block-editor-block-list__block {core/image aligned left or right}"); - } - - &.wp-align-center { - // Same as no alignment? - } -} diff --git a/storybook/stories/playground/editor-styles.scss b/storybook/stories/playground/editor-styles.scss index d920ea8de5ba0..dbb99f9b45621 100644 --- a/storybook/stories/playground/editor-styles.scss +++ b/storybook/stories/playground/editor-styles.scss @@ -33,21 +33,4 @@ ol ul { list-style-type: circle; } - - // These are default editor styles - .wp-block { - max-width: 700px; - - // TODO: the default padding/margin of the block editor content are not set properly - margin-left: auto; - margin-right: auto; - } - .wp-block[data-align="wide"], - .wp-block.alignwide { - max-width: 1100px; - } - .wp-block[data-align="full"], - .wp-block.alignfull { - max-width: none; - } }