Updated: Comment #0

Problem/Motivation

In #2014895: Image captions & alignment (for inline images), we introduced aligning and captioning of images in Drupal 8 — at long last Drupal will finally ship with that!

Currently, I'm collaborating with the CKEditor developers on getting Drupal to use CKEditor 4.3, including its leap forward in image handling (which will allow us to get rid of a whole bunch of custom code). That's what's blocking #2039163: Update CKEditor library to 4.4: some upstream changes.

We — or rather, they, because they're doing all the hard work! — are very close to a patch that will solve that issue. However, in doing so, they encountered a fundamental flaw in the code that was introduced in #2014895.

The problem is this:

filter_caption always transforms <img>s into <figure><img><figcaption</figure>, as long as the image has either a data-caption or a data-align attribute.
In other words: even an aligned image will get wrapped in a figure tag, even if no caption is set. This is beneficial for the designer/themer: the same CSS handles both captioned and aligned images. If desired, (s)he can special case the "there's no caption" case, but out of the box, but that's optional. Simple.
But what about images aligned in the middle of text?
The above wraps all images that have either a caption or an alignment in a <figure> tag. Which means we turn them into block-level elements… even if they're in fact an inline image and not a block image! This results in invalid HTML, and may break styling too.
That's what we failed to see/address/support. However infrequent on most sites, there are valid use cases for aligning images. Not to mention that this is how image alignment is demonstrated/explained in many if not most tutorials.

In other words: CKEditor 4.3's image2 plugin does things correctly, filter_caption does things incorrectly, resulting both in a mismatch between what the user sees in CKEditor and what the end result looks like, as well as invalid HTML with the corresponding consequences.

Proposed resolution

The solution is simple:

  1. stop filter_caption from transforming images that only have the data-align attribute into <figure><img></figure>
  2. add CSS to handle left/center/right aligned images, which we can do very elegantly since we dropped IE8 support: img[data-align="(left|center|right)" { … }

Remaining tasks

None.

User interface changes

None, other than that the output of <img src="cat.jpg" data-align="right" /> will now look differently. In the third example in this screenshot, you would now see just the llama, not the gray background + border.

API changes

None.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

Wim Leers’s picture

Status: Active » Needs review
FileSize
5 KB
jessebeach’s picture

I'd prefer to use classes for alignment rather than attributes. Functionally they're the same (other than selector weight), but in terms of DX, themers are going to recognize a class over an attr-based selector more readily and especially for these types of themer/content editor facing elements we should stick with easier patterns.

Wim, do we expect the image in the editor to be wrapped in a figure tag even when the caption option is disabled?

The image started off un-captioned; I didn't just uncheck the box in the image above. All images are rendered as being "captioned" in the WYSIWYG. Is that just to get the affordance of the caption-wrapping visual chrome?

The last submitted patch, 2: filter_align_fix-2170085-2.patch, failed testing.

Wim Leers’s picture

FileSize
10.4 KB
11.39 KB

Great review, thanks Jesse!

Wim, do we expect the image in the editor to be wrapped in a <figure> tag even when the caption option is disabled?

Ugh, excellent point: I updated the PHP code, but not our current, custom CKEditor plugin that mimicks the current PHP's behavior.
It's going to be fixed soon, in #2039163: Update CKEditor library to 4.4, when we get to throw away our custom drupalimagecaption plugin and use CKEditor's official image2 plugin instead. I've updated the code to deal with the new reality for now.

  1. +++ b/core/modules/filter/css/filter.caption.css
    @@ -60,13 +60,19 @@
    +[dir="rtl"] .align-left {
    ...
    +[dir="rtl"] .align-right {
    

    I removed these. "left" must mean "left", always.

    Many epic calls have been had about this issue. It's a trap. If you want to know why, see #1907418: Make CKEditor's alignment + underline buttons available (but not enabled by default) to understand why RTL-dependent alignment is problematic.

  2. +++ b/core/modules/filter/css/filter.caption.css
    @@ -60,13 +60,19 @@
    +.align-left {
    ...
    +.align-right {
    ...
    +.align-center {
    

    These class names are already taken for the generic text alignment classes, see system.module.css and #1907418. However… considering that those are for text alignment and the class being used here must work to align HTML elements of any kind, I think these names are fine.

    I kept these, and updated the tests.

  3. +++ b/core/modules/filter/lib/Drupal/filter/Plugin/Filter/FilterCaption.php
    @@ -51,8 +51,11 @@ public function process($text, $langcode, $cache, $cache_id) {
    +            $node->setAttribute('class', implode(' ', $classes));
    

    This always sets the alignment class on the image, but doesn't remove it if the image is captioned, which then causes both the caption and the captioned image to be floated. That's bad.

    The other changes also break the "no valid alignment" case, so the assertions testing that will fail.

jessebeach’s picture

I see what you did there with the text-align classes. Clever stuff:

-      'justifyClasses' => array('align-left', 'align-center', 'align-right', 'align-justify'),
+      'justifyClasses' => array('text-align-left', 'text-align-center', 'text-align-right', 'text-align-justify'),
jessebeach’s picture

Status: Needs review » Reviewed & tested by the community
FileSize
110.26 KB
114.23 KB
117.85 KB

Great changes. Love this patch. Here are a couple screenshots from my testing.

An image without a caption. The "figure" chrome is no longer rendered.

An image with a caption. The "figure" chrome is rendered.

Centered text

Screenshot of the CKEditor editing frame. The center text button is pressed and the highlighted text is centered in the editing window.

I like the move of the 'align-*' classes to the system css as well. These really are general-use classes. WordPress has almost the same set, if not exactly the same selector names.

webchick’s picture

Status: Reviewed & tested by the community » Fixed

Committed and pushed to 8.x. Thanks!

Wim Leers’s picture

Issue tags: -sprint

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.