diff --git a/packages/base-styles/_animations.scss b/packages/base-styles/_animations.scss
index 87e5f035f46a6c..e5bbf863757356 100644
--- a/packages/base-styles/_animations.scss
+++ b/packages/base-styles/_animations.scss
@@ -36,11 +36,6 @@
@include reduce-motion("animation");
}
-@mixin editor-canvas-resize-animation() {
- transition: all 0.4s cubic-bezier(0.46, 0.03, 0.52, 0.96);
- @include reduce-motion("transition");
-}
-
// Deprecated
@mixin edit-post__fade-in-animation($speed: 0.08s, $delay: 0s) {
@warn "The `edit-post__fade-in-animation` mixin is deprecated. Use `animation__fade-in` instead.";
diff --git a/packages/block-editor/src/components/block-canvas/style.scss b/packages/block-editor/src/components/block-canvas/style.scss
index 1395b5c0a437d3..9e924cb79bace1 100644
--- a/packages/block-editor/src/components/block-canvas/style.scss
+++ b/packages/block-editor/src/components/block-canvas/style.scss
@@ -4,5 +4,4 @@ iframe[name="editor-canvas"] {
height: 100%;
display: block;
background-color: transparent;
- @include editor-canvas-resize-animation;
}
diff --git a/packages/block-editor/src/components/iframe/content.scss b/packages/block-editor/src/components/iframe/content.scss
index e884de1e6f2573..47eac022bf52ac 100644
--- a/packages/block-editor/src/components/iframe/content.scss
+++ b/packages/block-editor/src/components/iframe/content.scss
@@ -3,28 +3,23 @@
border: 0.01px solid transparent;
}
-.block-editor-iframe__container {
- width: 100%;
- height: 100%;
- overflow-x: hidden;
-}
-
-.block-editor-iframe__scale-container {
- width: 100%;
- height: 100%;
- display: flex;
-}
-
-.block-editor-iframe__scale-container.is-zoomed-out {
- $container-width: var(--wp-block-editor-iframe-zoom-out-container-width, 100vw);
- $prev-container-width: var(--wp-block-editor-iframe-zoom-out-prev-container-width, 100vw);
- width: $prev-container-width;
- margin-left: calc(-1 * (#{$prev-container-width} - #{$container-width}) / 2);
-}
-
.block-editor-iframe__html {
transform-origin: top center;
- @include editor-canvas-resize-animation;
+ // 400ms should match the animation speed used in iframe/index.js
+ $zoomOutAnimation: all 400ms cubic-bezier(0.46, 0.03, 0.52, 0.96);
+
+ // We don't want to animate the transform of the translateX because it is used
+ // to "center" the canvas. Leaving it on causes the canvas to slide around in
+ // odd ways.
+ transition: $zoomOutAnimation, transform 0s scale 0s;
+ @include reduce-motion("transition");
+
+ &.zoom-out-animation {
+ // we only want to animate the scaling when entering zoom out. When sidebars
+ // are toggled, the resizing of the iframe handles scaling the canvas as well,
+ // and the doubled animations cause very odd animations.
+ transition: $zoomOutAnimation, transform 0s;
+ }
}
.block-editor-iframe__html.is-zoomed-out {
@@ -32,10 +27,11 @@
$frame-size: var(--wp-block-editor-iframe-zoom-out-frame-size);
$inner-height: var(--wp-block-editor-iframe-zoom-out-inner-height);
$content-height: var(--wp-block-editor-iframe-zoom-out-content-height);
- $prev-container-width: var(--wp-block-editor-iframe-zoom-out-prev-container-width);
-
- transform: scale(#{$scale});
-
+ $scale-container-width: var(--wp-block-editor-iframe-zoom-out-scale-container-width);
+ $container-width: var(--wp-block-editor-iframe-zoom-out-container-width, 100vw);
+ // Apply an X translation to center the scaled content within the available space.
+ transform: translateX(calc((#{$scale-container-width} - #{$container-width}) / 2 / #{$scale}));
+ scale: #{$scale};
background-color: $gray-300;
// Chrome seems to respect that transform scale shouldn't affect the layout size of the element,
diff --git a/packages/block-editor/src/components/iframe/index.js b/packages/block-editor/src/components/iframe/index.js
index 92c66f954704e3..b14514f934fb3e 100644
--- a/packages/block-editor/src/components/iframe/index.js
+++ b/packages/block-editor/src/components/iframe/index.js
@@ -122,7 +122,7 @@ function Iframe( {
}, [] );
const { styles = '', scripts = '' } = resolvedAssets;
const [ iframeDocument, setIframeDocument ] = useState();
- const prevContainerWidthRef = useRef();
+ const initialContainerWidth = useRef( 0 );
const [ bodyClasses, setBodyClasses ] = useState( [] );
const clearerRef = useBlockSelectionClearer();
const [ before, writingFlowRef, after ] = useWritingFlow();
@@ -243,10 +243,15 @@ function Iframe( {
useEffect( () => {
if ( ! isZoomedOut ) {
- prevContainerWidthRef.current = containerWidth;
+ initialContainerWidth.current = containerWidth;
}
}, [ containerWidth, isZoomedOut ] );
+ const scaleContainerWidth = Math.max(
+ initialContainerWidth.current,
+ containerWidth
+ );
+
const disabledRef = useDisabled( { isDisabled: ! readonly } );
const bodyRef = useMergeRefs( [
useBubbleEvents( iframeDocument ),
@@ -298,14 +303,52 @@ function Iframe( {
useEffect( () => cleanup, [ cleanup ] );
+ const zoomOutAnimationClassnameRef = useRef( null );
+
+ // Toggle zoom out CSS Classes only when zoom out mode changes. We could add these into the useEffect
+ // that controls settings the CSS variables, but then we would need to do more work to ensure we're
+ // only toggling these when the zoom out mode changes, as that useEffect is also triggered by a large
+ // number of dependencies.
useEffect( () => {
if ( ! iframeDocument || ! isZoomedOut ) {
return;
}
+ const handleZoomOutAnimationClassname = () => {
+ clearTimeout( zoomOutAnimationClassnameRef.current );
+
+ iframeDocument.documentElement.classList.add(
+ 'zoom-out-animation'
+ );
+
+ zoomOutAnimationClassnameRef.current = setTimeout( () => {
+ iframeDocument.documentElement.classList.remove(
+ 'zoom-out-animation'
+ );
+ }, 400 ); // 400ms should match the animation speed used in components/iframe/content.scss
+ };
+
+ handleZoomOutAnimationClassname();
iframeDocument.documentElement.classList.add( 'is-zoomed-out' );
+ return () => {
+ handleZoomOutAnimationClassname();
+ iframeDocument.documentElement.classList.remove( 'is-zoomed-out' );
+ };
+ }, [ iframeDocument, isZoomedOut ] );
+
+ // Calculate the scaling and CSS variables for the zoom out canvas
+ useEffect( () => {
+ if ( ! iframeDocument || ! isZoomedOut ) {
+ return;
+ }
+
const maxWidth = 750;
+ // Note: When we initialize the zoom out when the canvas is smaller (sidebars open),
+ // initialContainerWidth will be smaller than the full page, and reflow will happen
+ // when the canvas area becomes larger due to sidebars closing. This is a known but
+ // minor divergence for now.
+
// This scaling calculation has to happen within the JS because CSS calc() can
// only divide and multiply by a unitless value. I.e. calc( 100px / 2 ) is valid
// but calc( 100px / 2px ) is not.
@@ -314,7 +357,7 @@ function Iframe( {
scale === 'default'
? ( Math.min( containerWidth, maxWidth ) -
parseInt( frameSize ) * 2 ) /
- prevContainerWidthRef.current
+ scaleContainerWidth
: scale
);
@@ -336,13 +379,11 @@ function Iframe( {
`${ containerWidth }px`
);
iframeDocument.documentElement.style.setProperty(
- '--wp-block-editor-iframe-zoom-out-prev-container-width',
- `${ prevContainerWidthRef.current }px`
+ '--wp-block-editor-iframe-zoom-out-scale-container-width',
+ `${ scaleContainerWidth }px`
);
return () => {
- iframeDocument.documentElement.classList.remove( 'is-zoomed-out' );
-
iframeDocument.documentElement.style.removeProperty(
'--wp-block-editor-iframe-zoom-out-scale'
);
@@ -359,7 +400,7 @@ function Iframe( {
'--wp-block-editor-iframe-zoom-out-container-width'
);
iframeDocument.documentElement.style.removeProperty(
- '--wp-block-editor-iframe-zoom-out-prev-container-width'
+ '--wp-block-editor-iframe-zoom-out-scale-container-width'
);
};
}, [
@@ -371,6 +412,7 @@ function Iframe( {
containerWidth,
windowInnerWidth,
isZoomedOut,
+ scaleContainerWidth,
] );
// Make sure to not render the before and after focusable div elements in view
@@ -386,6 +428,7 @@ function Iframe( {
style={ {
...props.style,
height: props.style?.height,
+ border: 0,
} }
ref={ useMergeRefs( [ ref, setRef ] ) }
tabIndex={ tabIndex }
@@ -459,10 +502,8 @@ function Iframe( {
isZoomedOut && 'is-zoomed-out'
) }
style={ {
- '--wp-block-editor-iframe-zoom-out-container-width':
- isZoomedOut && `${ containerWidth }px`,
- '--wp-block-editor-iframe-zoom-out-prev-container-width':
- isZoomedOut && `${ prevContainerWidthRef.current }px`,
+ '--wp-block-editor-iframe-zoom-out-scale-container-width':
+ isZoomedOut && `${ scaleContainerWidth }px`,
} }
>
{ iframe }
diff --git a/packages/block-editor/src/components/iframe/style.scss b/packages/block-editor/src/components/iframe/style.scss
index dcddcdf0950a45..5dd30c338057e2 100644
--- a/packages/block-editor/src/components/iframe/style.scss
+++ b/packages/block-editor/src/components/iframe/style.scss
@@ -9,9 +9,10 @@
}
.block-editor-iframe__scale-container.is-zoomed-out {
- $container-width: var(--wp-block-editor-iframe-zoom-out-container-width, 100vw);
- $prev-container-width: var(--wp-block-editor-iframe-zoom-out-prev-container-width, 100vw);
- width: $prev-container-width;
- // This is to offset the movement of the iframe when we open sidebars
- margin-left: calc(-1 * (#{$prev-container-width} - #{$container-width}) / 2);
+ $scale-container-width: var(--wp-block-editor-iframe-zoom-out-scale-container-width, 100vw);
+ width: $scale-container-width;
+ // Position the iframe so that it is always aligned with the right side so that
+ // the scrollbar is always visible on the right side
+ position: absolute;
+ right: 0;
}
diff --git a/packages/block-editor/src/style.scss b/packages/block-editor/src/style.scss
index e6ec77b55a0ec5..512169351fe1fb 100644
--- a/packages/block-editor/src/style.scss
+++ b/packages/block-editor/src/style.scss
@@ -30,6 +30,7 @@
@import "./components/global-styles/style.scss";
@import "./components/grid/style.scss";
@import "./components/height-control/style.scss";
+@import "./components/iframe/style.scss";
@import "./components/image-size-control/style.scss";
@import "./components/inserter-list-item/style.scss";
@import "./components/inspector-controls-tabs/style.scss";
diff --git a/storybook/stories/playground/box/index.js b/storybook/stories/playground/box/index.js
index 3fb3c3b5862c47..cca522a90c1441 100644
--- a/storybook/stories/playground/box/index.js
+++ b/storybook/stories/playground/box/index.js
@@ -37,7 +37,7 @@ export default function EditorBox() {
} }
>
-
+
);