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) {