diff --git a/docs/reference-guides/core-blocks.md b/docs/reference-guides/core-blocks.md index 9c5fb95fb89e7..265de4140c006 100644 --- a/docs/reference-guides/core-blocks.md +++ b/docs/reference-guides/core-blocks.md @@ -248,7 +248,7 @@ Display multiple images in a rich gallery. ([Source](https://github.com/WordPres - **Name:** core/gallery - **Category:** media -- **Supports:** align, anchor, ~~html~~ +- **Supports:** align, anchor, spacing (blockGap), units (em, px, rem, vh, vw), ~~html~~ - **Attributes:** allowResize, caption, columns, fixedHeight, ids, imageCrop, images, linkTarget, linkTo, shortCodeTransforms, sizeSlug ## Group diff --git a/packages/block-library/src/gallery/block.json b/packages/block-library/src/gallery/block.json index e44a88747ca15..f241135b76b25 100644 --- a/packages/block-library/src/gallery/block.json +++ b/packages/block-library/src/gallery/block.json @@ -107,7 +107,22 @@ "supports": { "anchor": true, "align": true, - "html": false + "html": false, + "units": [ "px", "em", "rem", "vh", "vw" ], + "spacing": { + "blockGap": true, + "__experimentalDefaultControls": { + "blockGap": true + } + }, + "__experimentalLayout": { + "allowSwitching": false, + "allowInheriting": false, + "allowEditing": false, + "default": { + "type": "flex" + } + } }, "editorStyle": "wp-block-gallery-editor", "style": "wp-block-gallery" diff --git a/packages/block-library/src/gallery/deprecated.scss b/packages/block-library/src/gallery/deprecated.scss index 489af92a8cb0f..b85a49181c7f7 100644 --- a/packages/block-library/src/gallery/deprecated.scss +++ b/packages/block-library/src/gallery/deprecated.scss @@ -1,7 +1,7 @@ // Deprecated gallery styles pre refactoring to use nested image blocks. // https://github.com/WordPress/gutenberg/pull/25940. -.wp-block-gallery, -.blocks-gallery-grid { +.wp-block-gallery:not(.has-nested-images), +.blocks-gallery-grid:not(.has-nested-images) { display: flex; flex-wrap: wrap; list-style-type: none; diff --git a/packages/block-library/src/gallery/edit.js b/packages/block-library/src/gallery/edit.js index e3fc0e2210fa8..a0b342fdc3e69 100644 --- a/packages/block-library/src/gallery/edit.js +++ b/packages/block-library/src/gallery/edit.js @@ -54,6 +54,7 @@ import useImageSizes from './use-image-sizes'; import useShortCodeTransform from './use-short-code-transform'; import useGetNewImages from './use-get-new-images'; import useGetMedia from './use-get-media'; +import GapStyles from './gap-styles'; const MAX_COLUMNS = 8; const linkOptions = [ @@ -548,6 +549,12 @@ function GalleryEdit( props ) { /> { noticeUI } + { Platform.isWeb && ( + + ) } { ) } > { children } - - - { mediaPlaceholder } - + { isSelected && ! children && ( + + { mediaPlaceholder } + + ) } { + return ; + }; + + return gap && styleElement + ? createPortal( , styleElement ) + : null; +} diff --git a/packages/block-library/src/gallery/index.php b/packages/block-library/src/gallery/index.php index 027d54590e04f..e3a95085a6711 100644 --- a/packages/block-library/src/gallery/index.php +++ b/packages/block-library/src/gallery/index.php @@ -32,12 +32,53 @@ function block_core_gallery_data_id_backcompatibility( $parsed_block ) { add_filter( 'render_block_data', 'block_core_gallery_data_id_backcompatibility' ); +/** + * Adds a style tag for the --wp--style--unstable-gallery-gap var. + * + * The Gallery block needs to recalculate Image block width based on + * the current gap setting in order to maintain the number of flex columns + * so a css var is added to allow this. + * + * @param array $attributes Attributes of the block being rendered. + * @param string $content Content of the block being rendered. + * @return string The content of the block being rendered. + */ +function block_core_gallery_render( $attributes, $content ) { + $gap = _wp_array_get( $attributes, array( 'style', 'spacing', 'blockGap' ) ); + // Skip if gap value contains unsupported characters. + // Regex for CSS value borrowed from `safecss_filter_attr`, and used here + // because we only want to match against the value, not the CSS attribute. + $gap = preg_match( '%[\\\(&=}]|/\*%', $gap ) ? null : $gap; + $id = uniqid(); + $class = 'wp-block-gallery-' . $id; + $content = preg_replace( + '/' . preg_quote( 'class="', '/' ) . '/', + 'class="' . $class . ' ', + $content, + 1 + ); + $gap_value = $gap ? $gap : 'var( --wp--style--block-gap, 0.5em )'; + $style = '.' . $class . '{ --wp--style--unstable-gallery-gap: ' . $gap_value . '}'; + // Ideally styles should be loaded in the head, but blocks may be parsed + // after that, so loading in the footer for now. + // See https://core.trac.wordpress.org/ticket/53494. + add_action( + 'wp_footer', + function () use ( $style ) { + echo ''; + } + ); + return $content; +} /** * Registers the `core/gallery` block on server. */ function register_block_core_gallery() { register_block_type_from_metadata( - __DIR__ . '/gallery' + __DIR__ . '/gallery', + array( + 'render_callback' => 'block_core_gallery_render', + ) ); } diff --git a/packages/block-library/src/gallery/style.scss b/packages/block-library/src/gallery/style.scss index e2cf42ba2cf56..70b6c5e70d1c6 100644 --- a/packages/block-library/src/gallery/style.scss +++ b/packages/block-library/src/gallery/style.scss @@ -1,25 +1,18 @@ // Import styles for rendering the static content of deprecated gallery versions. @import "./deprecated.scss"; +// The following is a temporary override until flex layout supports +// an align items setting of normal. +figure.wp-block-gallery.has-nested-images { + align-items: normal; +} // Styles for current version of gallery block. .wp-block-gallery.has-nested-images { - display: flex; - flex-wrap: wrap; // Need bogus :not(#individual-image) to override long :not() // specificity chain on default image block on front end. figure.wp-block-image:not(#individual-image) { - // Add space between thumbnails, and unset right most thumbnails later. - margin: 0 var(--gallery-block--gutter-size, #{$grid-unit-20}) var(--gallery-block--gutter-size, #{$grid-unit-20}) 0; - - &:last-of-type:not(#individual-image) { - margin-right: 0; - } - - width: calc(50% - (var(--gallery-block--gutter-size, #{$grid-unit-20}) / 2)); - - &:nth-of-type(even) { - margin-right: 0; - } + width: calc(50% - (var(--wp--style--unstable-gallery-gap, #{$grid-unit-20}) / 2)); + margin: 0; } figure.wp-block-image { @@ -27,8 +20,6 @@ flex-grow: 1; justify-content: center; position: relative; - margin-top: auto; - margin-bottom: auto; flex-direction: column; max-width: 100%; @@ -96,17 +87,9 @@ // Non cropped images. &:not(.is-cropped) { - figure.wp-block-image:not(#individual-image) { margin-top: 0; margin-bottom: auto; - img { - margin-bottom: var(--gallery-block--gutter-size, #{$grid-unit-20}); - } - - figcaption { - bottom: var(--gallery-block--gutter-size, #{$grid-unit-20}); - } } } @@ -128,7 +111,6 @@ } &.columns-1 figure.wp-block-image:not(#individual-image) { - margin-right: 0; width: 100%; } @@ -136,35 +118,20 @@ @include break-small { @for $i from 3 through 8 { &.columns-#{ $i } figure.wp-block-image:not(#individual-image) { - margin-right: var(--gallery-block--gutter-size, #{$grid-unit-20}); - width: calc(#{math.div(100%, $i)} - (var(--gallery-block--gutter-size, #{$grid-unit-20}) * #{math.div($i - 1, $i)})); - - } + width: calc(#{math.div(100%, $i)} - (var(--wp--style--unstable-gallery-gap, #{$grid-unit-20}) * #{math.div($i - 1, $i)})); - // Prevent collapsing margin while sibling is being dragged. - &.columns-#{$i} figure.wp-block-image:not(#individual-image).is-dragging ~ figure.wp-block-image:not(#individual-image) { - margin-right: var(--gallery-block--gutter-size, #{$grid-unit-20}); - } - } - // Unset the right margin on every rightmost gallery item to ensure center balance. - @for $column-count from 1 through 8 { - &.columns-#{$column-count} figure.wp-block-image:not(#individual-image):nth-of-type(#{ $column-count }n) { - margin-right: 0; } } // If number of columns not explicitly set default to 3 columns if 3 or more images. &.columns-default { figure.wp-block-image:not(#individual-image) { - margin-right: var(--gallery-block--gutter-size, #{$grid-unit-20}); - width: calc(33.33% - (var(--gallery-block--gutter-size, 16px) * #{math.div(2, 3)})); - } - figure.wp-block-image:not(#individual-image):nth-of-type(3n+3) { - margin-right: 0; + + width: calc(33.33% - (var(--wp--style--unstable-gallery-gap, 16px) * #{math.div(2, 3)})); } // If only 2 child images use 2 columns. figure.wp-block-image:not(#individual-image):first-child:nth-last-child(2), figure.wp-block-image:not(#individual-image):first-child:nth-last-child(2) ~ figure.wp-block-image:not(#individual-image) { - width: calc(50% - (var(--gallery-block--gutter-size, 16px) * 0.5)); + width: calc(50% - (var(--wp--style--unstable-gallery-gap, 16px) * 0.5)); } // For a single image set to 100%. figure.wp-block-image:not(#individual-image):first-child:nth-last-child(1) {