From 057370466263e7c697efd039c17d8b0bb648c7a5 Mon Sep 17 00:00:00 2001 From: jasmussen Date: Thu, 5 Jul 2018 12:09:37 +0200 Subject: [PATCH] Revisit image floats. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This adds a wrapping `aside` element to any image block that's floated left or right. From the spec, https://www.w3.org/TR/html52/grouping-content.html#the-figure-element: > For content that is only tangentially related, or that serves a separate purpose than the surrounding flow, the aside element should be used (and can itself wrap a figure). For example, a pull quote that repeats content from an article would be more appropriate in an aside than in a figure, because it isn’t part of the content, it’s a repetition of the content for the purposes of enticing readers or highlighting key topics. The above is the reasoning for using the `aside` element to wrap the figure. But why wrap the figure at all? Because due to issues surfaced in https://github.com/WordPress/gutenberg/pull/7624#issuecomment-402114247, it seems our current implmeentation isn't responsive. The challenge is — what if you float a very small image to the left, and write a giant caption. Even if we apply `width: fit-content;` on the `figure`, the caption will expand the `figure` to accommodate as much text as the parent wrapping element will allow. `min-content` doesn't work either, because this will make the `figure` only as wide as the smallest word. What we have in master works in most cases, through dark magic, but it also only works because we remove the `max-width` from the nested image. This means the image won't resize with the viewport, and is therefore not responsive. I have explored so many many options for fixing this, and after all this time, what it boils down to is this: - We can either set a fixed size on floated captions, say 33%, and hope it works for the image that's floated. Not ideal, and you can see the end result here: https://codepen.io/joen/pen/wXbqwN - We can add a wrapping element around the `figure`, so that it and the `figcaption` can be sized using table rules, as in this PR. Why not just set the width on the figure element and float that? Because then we can't accommodate wide images, which rely on an unbounded main column. It's not ideal that we have to add an extra wrapping element, but it can be semantic, and it feels like the simplest to work with for themers implementing wide images coexisting with floats. --- core-blocks/image/editor.scss | 33 +++++++++++++ core-blocks/image/index.js | 49 ++++++++++++++++++- core-blocks/image/style.scss | 29 ++++++----- .../src/components/block-list/style.scss | 4 +- 4 files changed, 101 insertions(+), 14 deletions(-) diff --git a/core-blocks/image/editor.scss b/core-blocks/image/editor.scss index 48f3de5183881..bd8ded9fb0995 100644 --- a/core-blocks/image/editor.scss +++ b/core-blocks/image/editor.scss @@ -103,3 +103,36 @@ margin: -$border-width; } } + +// 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"] { + .editor-block-list__block-edit { + figure { + margin: 0; + display: table; + } + + // This maps to the figcaption on the frontend. + .editor-rich-text { + display: table-caption; + caption-side: bottom; + } + } +} + +// This is similar to above but for resized unfloated images only, where the markup is different. +[data-type="core/image"] .editor-block-list__block-edit figure.is-resized { + margin: 0; + display: table; + + // This maps to the figcaption on the frontend. + .editor-rich-text { + display: table-caption; + caption-side: bottom; + } +} diff --git a/core-blocks/image/index.js b/core-blocks/image/index.js index 3cf3ff04e6c93..1dae48c7095ae 100644 --- a/core-blocks/image/index.js +++ b/core-blocks/image/index.js @@ -6,6 +6,7 @@ import classnames from 'classnames'; /** * WordPress dependencies */ +import { Fragment } from '@wordpress/element'; import { __ } from '@wordpress/i18n'; import { createBlock, @@ -217,15 +218,59 @@ export const settings = { /> ); - return ( -
+ const figure = ( + { href ? { image } : image } { caption && caption.length > 0 && } + + ); + + if ( 'left' === align || 'right' === align ) { + return ( +
+
+ { figure } +
+
+ ); + } + + return ( +
+ { figure }
); }, deprecated: [ + { + attributes: blockAttributes, + save( { attributes } ) { + const { url, alt, caption, align, href, width, height, id } = attributes; + + const classes = classnames( { + [ `align${ align }` ]: align, + 'is-resized': width || height, + } ); + + const image = ( + { + ); + + return ( +
+ { href ? { image } : image } + { caption && caption.length > 0 && } +
+ ); + }, + }, { attributes: blockAttributes, save( { attributes } ) { diff --git a/core-blocks/image/style.scss b/core-blocks/image/style.scss index 321fc30504bc3..84c5539829a3e 100644 --- a/core-blocks/image/style.scss +++ b/core-blocks/image/style.scss @@ -1,5 +1,4 @@ .wp-block-image { - width: fit-content; max-width: 100%; img { @@ -13,20 +12,28 @@ text-align: center; } + // Floats get an extra wrapping aside element, so the figure becomes a child. + // Resized images that are not floated, need the caption trick too. + .alignleft, + .alignright, &.is-resized { - width: min-content; + display: table; + margin: 0; - // Emulate min-content for Edge and IE11 - display: -ms-inline-grid; - -ms-grid-columns: min-content; - - figcaption { - -ms-grid-row: 2; + > figcaption { + display: table-caption; + caption-side: bottom; } + } - img { - max-width: none; - } + .alignleft { + float: left; + margin-right: 1em; + } + + .alignright { + float: right; + margin-left: 1em; } // Supply caption styles to images, even if the theme hasn't opted in. diff --git a/packages/editor/src/components/block-list/style.scss b/packages/editor/src/components/block-list/style.scss index 4f86b9100d7b2..8af2d5498da63 100644 --- a/packages/editor/src/components/block-list/style.scss +++ b/packages/editor/src/components/block-list/style.scss @@ -346,7 +346,6 @@ width: 100%; // When images are floated, the block itself should collapse to zero height. - margin-bottom: 0; height: 0; // Hide block outline when an image is floated. @@ -354,6 +353,9 @@ &:before { content: none; } + + // This margin won't collapse on its own, so zero it out. + margin-top: 0; } // Keep a 1px margin to compensate for the border/outline.