Problem/Motivation

Given that alignable elements are:

  • Media Embeds aligned-left or aligned-right
  • Media Embeds with captions aligned-left or aligned-right
  • Images aligned-left or aligned-right
  • Images with captions aligned-left or aligned-right
  • Blockquote text aligned-left or aligned-right

Alignable elements can be aligned-right or align-left (as well as aligned-center or not aligned). When align-right or aligned-left, there is an implicit assumption that there will be space opposite of the alignment.

  • If aligned-right, it makes sense to allow space to the left of the alignable element.
  • If aligned-left, it makes sense to allow space to the right of the alignable element.

This is arguable essential within the text editor to allow:

  • a visual representation of the alignment
  • space to edit the text wrapping around the aligned embed
  • to prevent bizarre squished text

Text without much horizontal space for editing:
bizarrely squished text

Text with the words exploded into letters:
bizarrely squished text 2

This from feedback from @effulgentsia here #2801307-54: [META] Support WYSIWYG embedding of media entities:

[...] add CSS along the lines of max-width: 75% on media that's aligned left or right. It's fine for the media to be smaller. It's just that if you're explicitly choosing to align it left or right, then you're choosing to put something else beside it, which means leaving some amount of room for that something else.

Proposed resolution

  • Must-have: Add a max-width for embedded media in CKEditor when aligned-left or aligned-right (only).

Additional suggested improvements:

  • Add a max-width for alignable elements when aligned-left or aligned-right in Classy theme and themes that extend Classy.
  • Add some margin between alignable elements and the elements opposite in the CKEditor.
  • Add some margin between alignable elements and the elements opposite in the Classy theme and themes that extend Classy.

Remaining tasks

  1. Review
  2. Test coverage
  3. Commit.

User interface changes

TBD

API changes

None.

Data model changes

None.

Release notes snippet

Draft Change record:
https://www.drupal.org/node/3085749

CommentFileSizeAuthor
#121 3078287-nr-bot.txt145 bytesneeds-review-queue-bot
#113 space.png64.36 KBchris matthews
#108 without-the-patch-10-10-2019.mov7.38 MBoknate
#108 snake-river-10-10-2019-standard-480.mov6.64 MBoknate
#104 3078287-104.patch11.41 KBwim leers
#104 interdiff.txt3.15 KBwim leers
#101 3078287-100.patch14.29 KBoknate
#101 3078287-interdiff--99-100.txt645 bytesoknate
#99 3078287-99.patch14.62 KBwim leers
#99 interdiff.txt2.33 KBwim leers
#96 3078287-96.patch9.53 KBwim leers
#96 interdiff.txt5.54 KBwim leers
#88 3078287-88.patch10.27 KBoknate
#88 3078287-interdiff--85-88.txt753 bytesoknate
#85 3078287-85.patch10.29 KBoknate
#85 3078287--interdiff-75-85.txt814 bytesoknate
#75 3078287-75.patch10.81 KBoknate
#75 3078287--interdiff-61-75.txt8.84 KBoknate
#61 aligned-width-constraint-black-cat.mov10.49 MBoknate
#61 align-center-doesnt-work.png828.76 KBoknate
#61 align-right-CKEditor.png918.01 KBoknate
#61 align-left-CKEditor.png916.08 KBoknate
#61 align-right.png906.98 KBoknate
#61 align-left.png909.53 KBoknate
#61 3078287-61.patch17.42 KBoknate
#57 constrain-width-test-low-res.mov14.24 MBoknate
#56 3078287-56--combined-w-3072279-10.patch26.89 KBoknate
#56 3078287-56--do-not-test.patch17.42 KBoknate
#56 3078287--interdiff-55-56.txt881 bytesoknate
#55 3078287-55.patch17.92 KBoknate
#55 3078287--interdiff-50-55.txt7.72 KBoknate
#55 3078287--interdiff-54-55.txt1.84 KBoknate
#54 3078287-54.patch16.09 KBoknate
#54 3078287--interdiff-50-54.txt5.88 KBoknate
#53 3078287-53.patch14.12 KBoknate
#53 3078287--interdiff-50-53.txt3.92 KBoknate
#52 3078287-52.patch14.12 KBoknate
#52 3078287--interdiff-50-52.txt3.92 KBoknate
#50 3078287-50.patch11.64 KBoknate
#50 3078287-interdiff--48-50.txt790 bytesoknate
#48 3078287-48.patch11.49 KBoknate
#48 3078287-interdiff--46-48.txt906 bytesoknate
#46 3078287-44.patch11.32 KBoknate
#46 3078287-interdiff--43-44.txt2.71 KBoknate
#44 3078287-44.patch10.71 KBoknate
#44 3078287-interdiff--43-44.txt374 bytesoknate
#43 3078287-43.patch10.71 KBoknate
#43 3078287--interdiff-40-43.txt8.24 KBoknate
#39 filter.align-added-twice-in-ckeditor.png1013.45 KBoknate
#39 3078287--interdiff-35-39.txt39.07 KBoknate
#39 3078287--interdiff-28-39.txt33.86 KBoknate
#39 3078287-39.patch11.01 KBoknate
#35 figure-umami-with-margin-on-figure-2.png824.9 KBoknate
#35 figure-umami-with-margin-on-figure.png914.84 KBoknate
#35 figure-umami-2.png865.64 KBoknate
#35 figure-umami.png369.36 KBoknate
#35 3078287-35.patch5.83 KBoknate
#35 3078287--interdiff-32-35.txt2.43 KBoknate
#32 3078287-32.patch6.07 KBoknate
#32 3078287--interdiff-29-32.txt1017 bytesoknate
#31 3078287-29.patch5.08 KBoknate
#31 3078287--interdiff-28-29.txt8.78 KBoknate
#28 blockquote-preview-WYWIWYG-doesnt-work.png323.44 KBoknate
#28 drupal-media-drupal-image-blockquote-left-aligned.png389.93 KBoknate
#28 drupal-media-drupal-image-blockquote-right-aligned.png376.12 KBoknate
#28 media-embed-and-image-embed-WYSIWYG-right-align.png341.97 KBoknate
#28 media-embed-and-image-embed-WYWISYG-left-align.png342.52 KBoknate
#28 3078287-28.patch6.5 KBoknate
#28 3078287-interdiff--25-28.txt2.23 KBoknate
#25 alignment-css.png486.9 KBoknate
#25 3078287-25.patch12.41 KBoknate
#25 3078287--interdiff-23-25.txt11.22 KBoknate
#23 3078287-23.patch12.58 KBoknate
#23 3078287--interdiff-19-23.txt3.3 KBoknate
#21 demo-umami-after.mov6.62 MBoknate
#21 demo-umami-before.mov12.65 MBoknate
#19 logged-out-constrained.mov10.7 MBoknate
#19 constrained.mov17.84 MBoknate
#19 3078287-19.patch2.68 KBoknate
#18 exploded-letters.png458.14 KBoknate
#18 before-behavior-outside-WYSIWYG.mov10.53 MBoknate
#17 data-align-right-outside-wysiwyg.png351.33 KBoknate
#17 data-align-right-in-wysiwyg.png145.16 KBoknate
#8 3078287-8.patch763 byteswim leers
#6 3078287-6.patch768 bytesoknate
#3 3078287-3.patch796 bytesoknate

Comments

oknate created an issue. See original summary.

oknate’s picture

Issue summary: View changes
oknate’s picture

StatusFileSize
new796 bytes

I don't know what happened to the images here, removing them since they no longer display.

phenaproxima’s picture

Status: Active » Needs review
Issue tags: +Needs screenshots, +Needs issue summary update

Looks okay to me. Will manually test it, but otherwise we should add some A/B screenshots to the issue summary and get this in.

wim leers’s picture

Title: Constrain the size of media image to a max of 75% of WYSIWYG » Constrain the width of embedded media to a max of 75% of the text editor's viewport
Category: Feature request » Task
Priority: Normal » Major
Status: Needs review » Needs work
Issue tags: +Media Initiative, +Usability

Per #2801307-110: [META] Support WYSIWYG embedding of media entities:

Note that we need to handle this not only for images, but for any media. But that's a mere/simple selector problem, so I'm not worried. :)

  1. +++ b/core/modules/media/css/plugins/drupalmedia/ckeditor.drupalmedia.css
    @@ -20,3 +20,20 @@ drupal-media {
    +.cke_widget_drupalmedia.align-right,
    

    This is already a selector that works for all embedded media, yay! 👍

  2. +++ b/core/modules/media/css/plugins/drupalmedia/ckeditor.drupalmedia.css
    @@ -20,3 +20,20 @@ drupal-media {
    + * When aligning left or right, there should be something beside the embed, so
    + * allow room for that in the CKEditor.
    

    I think this language needs refining. Something like the updated issue title would be better.

oknate’s picture

Status: Needs work » Needs review
StatusFileSize
new768 bytes

Updating the comment.

seanb’s picture

Issue summary: View changes
Status: Needs review » Reviewed & tested by the community
Issue tags: -Needs screenshots, -Needs issue summary update

Updated the IS, we have screenshots, patch looks good. I think we are done here. Nice improvement!

wim leers’s picture

StatusFileSize
new763 bytes

HEAD changed, causing the patch to no longer apply. Rebased.

lauriii’s picture

Status: Reviewed & tested by the community » Needs review

Would be great if we could get a usability expert to look at this issue. I'm not sure if this will actually improve the UX or have the opposite effect. If the max-width doesn't exist on the actual page, this will further divide the look and feel of content in CKEditor from what is on an actual page. If we set a 75% max-width in CKEditor, I'd expect that to exist on the actual page as well. I don't know what is the right solution to fixing this, but I'd assume it would be something similar to what we have for CKEditor uploaded images - users can decide what's the width of the element.

Moving back to needs review for input from a usability expert.

phenaproxima’s picture

Issue tags: +Needs usability review
webchick’s picture

Yeah, the front-end/back-end mismatch points are definitely valid. The CKEditor iframe is smaller than the page content, so it's not a true WYSIWYG experience anyway, which is why it felt ok to get away with it, and definitely preferable to not being able to edit the text at all (or functionally so).

I did originally suggest the ability to add a width attribute in the dialog at first (as you can do with images), but that got shot down, I guess because it's not transferable between media types? There was talk of instead adding the ability to select image styles (#2061377: [drupalImage] Optionally apply image style to images uploaded in CKEditor 5), but that's a much bigger lift. (And also is fraught with a lot of "pogo-sticking" UX problems unless it comes with a visual preview of some kind, which is a DRAGON style lift. ;))

However, somehow, Image images don't let you do this. The width is constrained to the largest word, so you can't physically get into an uneditable situation:

So if the max-width: 75% is contentious, I guess we could just copy/paste whatever is happening over there.

lauriii’s picture

I'm wondering if we could just make the max-width configurable in percentages or pixels? Or do we actually need a layout builder like tool in the CKEditor that allows adjusting more complex layout rules? Anyway, this feels like different issue than choosing image style.

webchick’s picture

We also talked about that (like a 25%/50%/75% selector), but that *also* seemed like a much bigger lift than hard-coding something for now (to prevent you from being unable to edit your content at all) and making it configurable later in a follow-up.

effulgentsia’s picture

If the max-width doesn't exist on the actual page

I think we should add it to the actual page as well. Any reason not to add it to a library attached by MediaEmbed?

We also talked about that (like a 25%/50%/75% selector)

Right. See #2801307-106: [META] Support WYSIWYG embedding of media entities. Let's open an issue for that if there isn't one already.

effulgentsia’s picture

25%/50%/75% selector...Let's open an issue for that

By the way, when configuring a 2 column section in Layout Builder, the choices are: 25%, 33%, 50%, 67%, 75%, so maybe in that new issue, we want to expand to that same list for consistency (and cause 1/3 and 2/3 are nice layouts).

oknate’s picture

Here's a follow-up for making the width constraint configurable: #3081303: Allow media embed width constraint to be configurable

oknate’s picture

Status: Needs review » Needs work
StatusFileSize
new145.16 KB
new351.33 KB

Updating this comment, as I was confused and had forgotten to turn on Filter Align which adds the css to the embed to allow the alignment to work.

There is an inconsistency where alignments works in the WYSIWYG when Filter Align is turned off.

Here's a follow-up for the inconsistency:

#3081357: Media alignment mismatch between the WYSIWYG and rendered media -- drupalmedia.js shouldn't convert data-align properties when Filter Align disabled

oknate’s picture

StatusFileSize
new10.53 MB
new458.14 KB

Here's a bizarre side effect of the fixed image size. In the "Lorem ipsum" example text the letters within words separate:
exploded letters

Here's a video of the "before" behavior outside the WYSIWYG with a fixed image size. It shows the text getting squashed when the browser size isn't wide enough to support the full width of the image and allow full words to display.
Video:
https://www.drupal.org/files/issues/2019-09-15/before-behavior-outside-W...

oknate’s picture

Status: Needs work » Needs review
StatusFileSize
new2.68 KB
new17.84 MB
new10.7 MB

Here's a patch that adds the width constraint outside the WYSIWYG. Note, it requires Filter Align to be turned on in order for the css classes "align-right" or "align-left" to be added to the media. We could potentially fix it with the un-ingested data-align="right" and data-align="left", but I think that might be going too far, so leaving that out for now.

Here's a demonstration, using the standard profile:

With this patch, when logged in:
https://www.drupal.org/files/issues/2019-09-15/constrained.mov

With this patch, when logged out:
https://www.drupal.org/files/issues/2019-09-15/logged-out-constrained.mov

It's worth noting that the Demo Umami profile turns on Filter Align by default. I think maybe we should do that. Or else this fix won't work out of the box.

oknate’s picture

@todo - We need to check that this works with Demo Umami profile.

oknate’s picture

StatusFileSize
new12.65 MB
new6.62 MB

Here's a demonstration of the fix in Demo Umami. It also fixes a margin bug where there was no margin between the text and the image.

Demo Umami without the fix:
https://www.drupal.org/files/issues/2019-09-15/demo-umami-before.mov

Demo Umami with the fix:
https://www.drupal.org/files/issues/2019-09-15/demo-umami-after.mov

Status: Needs review » Needs work

The last submitted patch, 19: 3078287-19.patch, failed testing. View results

oknate’s picture

Status: Needs work » Needs review
StatusFileSize
new3.3 KB
new12.58 KB

Fixing MediaEmbedFilterTest, its expected libraries needs to change with the change in #19.

lauriii’s picture

Status: Needs review » Needs work
Issue tags: +Needs change record

This seems like a nice improvement generally. I like the fact that the CKEditor and public-facing site renders the same way.

  1. +++ b/core/modules/media/css/filter.media_embed.css
    @@ -18,3 +18,20 @@
    + * Constrain the width of embedded media to a max of 75% when left or right
    + * aligned.
    
    +++ b/core/modules/media/css/plugins/drupalmedia/ckeditor.drupalmedia.css
    @@ -30,3 +30,20 @@ drupal-media {
    + * Constrain the width of embedded media to a max of 75% of the text editor's
    + * viewport.
    

    We should explain relation between these styles.

  2. +++ b/core/modules/media/css/filter.media_embed.css
    @@ -18,3 +18,20 @@
    +.media.align-right,
    +.media.align-left {
    

    Does this actually have to be specific to media? Wouldn't it make sense to apply this rule more globally?

  3. +++ b/core/modules/media/src/Plugin/Filter/MediaEmbed.php
    index f3486bcc8b..78ba7c76a6 100644
    --- a/core/themes/stable/css/media/filter.media_embed.css
    
    --- a/core/themes/stable/css/media/filter.media_embed.css
    +++ b/core/themes/stable/css/media/filter.media_embed.css
    

    1. I'm not sure if we can actually do this in stable theme since this will affect how a lot of themes render media. What if someone expects the previous behavior to be the correct behavior 🤷‍♂️ We should open at least a change record for this.

    2. This doesn't feel like this belongs to Stable. This seems more like something that should be in Classy. However, concern 1 is applicable to Classy as well.

oknate’s picture

StatusFileSize
new11.22 KB
new12.41 KB
new486.9 KB

Exploring #25.2:

Does this actually have to be specific to media? Wouldn't it make sense to apply this rule more globally?

Here's a test creating a new alignment css that attaches to FilterAlign and works for both DrupalMedia and DrupalImage. Here's demo image of this patch with a 5 MB image of Snake River for the DrupalImage embed.

alignment example, both look good

I can confirm that without generalizing this outside of embedded media, the second image wouldn't look aligned right, its width would fill 100% of the container.

There's still some work needed. Since the DrupalMedia.js adds the align-right or align-left style to the wrapper, you get a nested .align-right or nested .align-left. So I have added css to overcome that.

diff --git a/core/modules/media/css/plugins/drupalmedia/ckeditor.drupalmedia.css b/core/modules/media/css/plugins/drupalmedia/ckeditor.drupalmedia.css
index d89050b69e..c772599de6 100644
--- a/core/modules/media/css/plugins/drupalmedia/ckeditor.drupalmedia.css
+++ b/core/modules/media/css/plugins/drupalmedia/ckeditor.drupalmedia.css
@@ -35,15 +35,15 @@ drupal-media .media-library-item__edit {
  * Constrain the width of embedded media to a max of 75% of the text editor's
  * viewport.
  */
-.cke_widget_drupalmedia.align-right,
-.cke_widget_drupalmedia.align-left {
-  max-width: 75%;
+.cke_widget_drupalmedia.align-right .align-right,
+.cke_widget_drupalmedia.align-left .align-left {
+  max-width: unset;
 }
 
-.cke_widget_drupalmedia.align-left {
-  margin-right: 1em;
+.cke_widget_drupalmedia.align-left .align-left {
+  margin-right: unset;
 }
 
-.cke_widget_drupalmedia.align-right {
-  margin-left: 1em;
+.cke_widget_drupalmedia.align-right .align-right {
+  margin-right: unset;
 }

I'm not a front-end specialist, so I could use some guidance on the best way to do that. We could use javascript to remove it from the preview, but that seems pretty brittle.

wim leers’s picture

Title: Constrain the width of embedded media to a max of 75% of the text editor's viewport » Constrain the width of aligned images, media, blockquotes etc to a max of 75%
Component: media system » filter.module
  1. #9:
    this will further divide the look and feel of content in CKEditor from what is on an actual page.

    The goal never was nor is to have a perfect preview. That's impossible anyway. It's an approximation. If the preview itself is getting in the way of text editor usability, which is the case here, then making the preview "less pixel perfect" is perfectly reasonable IMO.

  2. #9:
    it would be something similar to what we have for CKEditor uploaded images - users can decide what's the width of the element.

    We definitely cannot do that — that's a problem with the existing CKEditor + Drupal 8 + image uploading integration actually: the in-place resizing ability gives the user the illusion of control and precision, yet the place where it will actually be viewed by end users is completely different.

  3. #14: but a percentage max-width is relative to the container element. On the actual page, that element may have margins that the CKEditor <iframe> body does not have. So I'm concerned about restricting it to 75% also on the front end (via the filter), rather than only in CKEditor <iframe> instances.
  4. #17: that does look odd — thanks for opening a new issue, reviewed that.
  5. #18 + #19: I bet you can also do this with Drupal <=8.7's image uploads plus data-align. We need to verify that, it impacts how we solve this. #25 did investigate this 🥳
  6. #25 contains changes from another issue.

Updating issue title per changed direction. The issue summary still needs an update.

lauriii’s picture

I like the direction #25 is going to.

I'm still concerned about the backwards compatibility of this change. I'm wondering if we should just ship this as part of the modules and remove it in Stable. AFAIK, we haven't provided Stable overrides for CKEditor CSS files. This would mean that themes extending Stable wouldn't receive this change in the frontend but could still benefit from the CKEditor improvement. This would lead into inconsistency but maybe we could recommend themes extending stable to copy this CSS file to their theme.

  1. #26.1 I understand that the CKEditor cannot have a perfect preview. Setting this type of rules change the way the content gets rendered. If we make this type of deviations, in my opinion, the preview would no longer be even a close approximation. It would be particularly confusing in scenarios where the CKEditor is narrower, but the media is still rendered more nicely in the preview than on the page.
  2. #26.2 Should we open issue to try to come up with a better solution?
  3. +++ b/core/modules/ckeditor/src/Plugin/CKEditorPlugin/DrupalImage.php
    --- /dev/null
    +++ b/core/modules/filter/css/filter.align.css
    

    👍 We should ship this in the module since this is needed for the module functionality.

  4. +++ b/core/modules/media/css/plugins/drupalmedia/ckeditor.drupalmedia.css
    @@ -30,3 +30,20 @@ drupal-media {
    +.cke_widget_drupalmedia.align-right .align-right,
    

    Would be awesome if we could fix the JavaScript so that we don't need these CSS overrides.

  5. +++ b/core/modules/ckeditor/src/Plugin/CKEditorPlugin/DrupalImage.php
    @@ -85,4 +125,14 @@ public function validateImageUploadSettings(array $element, FormStateInterface $
    +  public function getCssFiles(Editor $editor) {
    +    return [
    +      $this->moduleExtensionList->getPath('filter') . '/css/filter.align.css',
    +    ];
    +  }
    
    +++ b/core/modules/media/src/Plugin/CKEditorPlugin/DrupalMedia.php
    @@ -121,6 +121,7 @@ public function isEnabled(Editor $editor) {
    +      $this->moduleExtensionList->getPath('filter') . '/css/filter.align.css',
    

    🤔We should probably open a follow-up to discuss if we should provide Stable override for CKEditor CSS files.

oknate’s picture

Still working on this. I haven't gotten a chance to fully respond, but appreciate the feedback and will respond in detail. Since both Wim Leers and Lauriii are encouraging with the wider scope, I have been working towards that. Here's a new patch and some screenshots.

left-aligned

right-aligned

right aligned in WYSIWYG

left-aligned in WYSIWYG

Blockquote preview in WYSIWYG doesn't work. This is expected:

blockquote preview

Running to lunch, but I'll update this comment more detail later today.

oknate’s picture

I'm concerned about restricting it to 75% also on the front end (via the filter), rather than only in CKEditor

instances.
I'm concerned about this too. But I think that this is supposed to be a stop-gap measure and a default. A stop-gap measure in that, if you have chosen to align it right or left, you presumably want some space for what your aligning it right of, or left of. I'd like to see if we can move this out of filter align and put it in the default themes. If it's attached to filter-align, it will be hard to override at the theme level.
oknate’s picture

Issue summary: View changes

Updating the Remaining tasks to "TBD", since the scope of this has changed.

oknate’s picture

StatusFileSize
new8.78 KB
new5.08 KB

This accomplishes the same thing as #28 but does so without altering the constructors on all the plugins. It does so by adding the classes to the classy theme and the umami theme.

Thoughts?

oknate’s picture

Status: Needs work » Needs review
StatusFileSize
new1017 bytes
new6.07 KB

Same as #31, just fixing the Kernel test's expected css.

lauriii’s picture

+++ b/core/modules/ckeditor/tests/src/Kernel/CKEditorTest.php
--- /dev/null
+++ b/core/profiles/demo_umami/themes/umami/css/components/filter/filter.align.css

Why are we duplicating these rules to Umami? Umami is extending Classy so it should receive these styles from there.

oknate’s picture

Status: Needs review » Needs work

Ah, good point. I missed that that was the case. I'll remove that and retest umami theme.

oknate’s picture

Status: Needs work » Needs review
StatusFileSize
new2.43 KB
new5.83 KB
new369.36 KB
new865.64 KB
new914.84 KB
new824.9 KB

I removed the duplicate rules from umami. I ended up keeping the stylesheet in umami for one override. The figure element had some excessive margin on it.

See the screenshots:

Here's some screenshots demonstrated the visual issue (IMHO):
https://www.drupal.org/files/issues/2019-09-19/figure-umami.png
https://www.drupal.org/files/issues/2019-09-19/figure-umami-2.png

And here's with some margin rule to set the right margin to zero when aligning right, and left margin to zero when aligning left.
https://www.drupal.org/files/issues/2019-09-19/figure-umami-with-margin-...
https://www.drupal.org/files/issues/2019-09-19/figure-umami-with-margin-...

The top margin on the figure I felt if I set it to zero it looked like it was too high, so I set it at .4em in umami. Since in standard the figure has a border box thingy around it, I set at 0 in standard. This is why I kept the demo umami style sheet. Just for this difference in the top margin.

lauriii’s picture

I think we should create a change record and then ask for input from a release manager on whether they think this would be too disruptive.

+++ b/core/themes/classy/css/components/filter.align.css
@@ -0,0 +1,52 @@
+ * Within the WYSIWYG, if the alignment class is applied within a widget,
+ * unset the rules.
...
+.cke_widget_wrapper.align-right .align-right {
...
+.cke_widget_wrapper.align-left .align-left {
...
+.cke_widget_wrapper.align-right .align-right {

This still seems like a bug to me. Would it be possible to solve it so that this wouldn't be necessary?

lauriii’s picture

Discussed this issue with @Wim Leers, @oknate, and @phenaproxima. We focused on discussing where to ship this improvement.
The current solution fixes the bug in Classy because, for example, Umami renders some media so that text becomes hard to read. The bug fix is made of layout level CSS which we don't generally ship as part of Stable theme or modules, and therefore we felt that Classy was a natural place to ship this.

This goes against what @Wim Leers was recommending in his role as subsystem maintainer of the Text Editor and CKEditor modules. He was recommending this to be fixed only in CKEditor because CKEditor preview is only an approximation of how the actual page will render. He also wanted to fix this for sites running themes not extending Classy.

We came with a compromise to ship the max-width in CKEditor globally so that all themes will receive this improvement. Besides this, we want to ship the same styles for frontend themes extending Classy as a default value. We don’t want to ship the default frontend styles in Stable or modules since they are supposed to be unopinionated.

We also agreed that #36 could be moved to a follow-up, since it's a pre-existing issue with the media embed markup. Since the media embed has conceptually only one element that should be aligned, the class should be only set on the wrapper. The latest patch already includes a workaround for this, but it has some potential side effects.

phenaproxima’s picture

Status: Needs review » Needs work

I quickly talked to @lauriii to hash out the implementation details. Here's what we'll do:

  • We will add a new library to the Filter module, called filter/align. (This was previously implemented in #25.)
  • Since this is a new library, it will also be copied into Stable.
  • The DrupalImage and DrupalMedia CKEditor plugins will always attach this library, by referencing its CSS file directly. (The one that ships with filter.module, that is.)
  • Whether the library is attached on the front end is going to vary by theme. The Stable theme will not do anything. Classy, on the other hand, will need to implement hook_element_info_alter() and give the processed_text element a new pre-render function (ideally at the beginning of the pre-render stack) which attaches the filter/align library to the element if the format being used has filter_align enabled.
oknate’s picture

Status: Needs work » Needs review
StatusFileSize
new11.01 KB
new33.86 KB
new39.07 KB
new1013.45 KB

Here's #38 implemented.

  • Combines #28 and #35
  • Removed the ckeditor stylesheet rules from demo_umami and classy themes.
  • Adds preprocess hook in hook_element_info_alter()

I noticed one bit of weirdness due to this:

The DrupalImage and DrupalMedia CKEditor plugins will always attach this library

It looks like the css gets added twice if they're both enabled:
https://www.drupal.org/files/issues/2019-09-24/filter.align-added-twice-...

I'm thinking we can use hook_ckeditor_css_alter instead, and then we don't need to add a constructor to the DrupalImage plugin. I'll try this in another patch.

phenaproxima’s picture

Status: Needs review » Needs work
Issue tags: +Needs tests
  1. +++ b/core/modules/ckeditor/src/Plugin/CKEditorPlugin/DrupalImage.php
    @@ -16,7 +20,43 @@
    +   * @param string $plugin_id
    +   *   The plugin_id for the plugin instance.
    

    Nit: This can just be "The plugin ID".

  2. +++ b/core/modules/ckeditor/src/Plugin/CKEditorPlugin/DrupalImage.php
    @@ -16,7 +20,43 @@
    +   * @param \Drupal\Core\Extension\ModuleExtensionList $extension_list_module
    +   *   The module extension list.
    

    Total nitpick: Can the variable be named $module_extension_list? It's just jarring to see its grammar shift around in the same line.

  3. +++ b/core/modules/filter/css/filter.align.css
    @@ -0,0 +1,52 @@
    +/**
    + * Add space between embed and surrounding element (such as a paragraph).
    + */
    

    "Embed" is presuming that we're embedding something. I think this should be "Add space between the aligned element and whatever might surround it (such as a paragraph)."

  4. +++ b/core/modules/filter/css/filter.align.css
    @@ -0,0 +1,52 @@
    +/**
    + * Within the WYSIWYG, if the alignment class is applied within a widget,
    + * unset the rules.
    + */
    +.cke_widget_wrapper.align-left .align-left,
    +.cke_widget_wrapper.align-right .align-right {
    +  max-width: unset;
    +}
    +
    +.cke_widget_wrapper.align-left .align-left {
    +  margin-right: unset;
    +}
    +
    +.cke_widget_wrapper.align-right .align-right {
    +  margin-left: unset;
    +}
    

    As @oknate pointed out, this can have undesirable edge-case side effects if there are descendant elements which have alignment. I think we might want to open a follow-up, at the very least, and reference it here with a @todo.

    Whether we want to fix it here, now, is up to @lauriii.

  5. +++ b/core/modules/filter/css/filter.align.css
    @@ -0,0 +1,52 @@
    +/**
    + * Set the margin on figure element to override user agent style sheet.
    + */
    +figure.align-right {
    +  margin: 0 0 1.2em 1em;
    +}
    +
    +figure.align-left {
    +  margin: 0 1em 1.2em 0;
    +}
    

    This feels like it could use a @see here...are we accounting for this kind of thing (i.e., default margins on a figure element) anywhere else in core?

  6. +++ b/core/profiles/demo_umami/themes/umami/css/components/filter/filter.align.css
    @@ -0,0 +1,18 @@
    +/**
    + * @file
    + * Align filter: default styling for displaying aligned images, media, etc.
    + */
    

    Wouldn't we also want to copy the rest of the styles from the original filter.align.css into this style sheet as well? Unless I'm misunderstanding how libraries-extend works (which I probably am).

  7. +++ b/core/profiles/demo_umami/themes/umami/css/components/filter/filter.align.css
    @@ -0,0 +1,18 @@
    + * filter.align.css in classy.  We're adding a bit of top margin to align
    

    Supernit: 'classy' should be 'Classy'.

  8. +++ b/core/themes/classy/classy.theme
    @@ -0,0 +1,40 @@
    +  if (array_key_exists('text_format', $info)) {
    +    $info['text_format']['#pre_render'][] = 'classy_pre_render_text_format';
    +  }
    

    I'm not sure this is what we want...we want to apply the library any time processed text with filter_align is rendered out in any context. The text_format element produces a CKEditor instance, which will bring in the appropriate CSS by way of the CKEditor plugins we're using. All of this is why we need to alter the processed_text element instead. This means we are going to need test coverage, I think.

  9. +++ b/core/themes/classy/classy.theme
    @@ -0,0 +1,40 @@
    +function classy_pre_render_text_format($element) {
    +
    +  $format = \Drupal::entityTypeManager()
    

    There's an extra blank line here, and $element should be type hinted.

phenaproxima’s picture

+++ b/core/modules/ckeditor/src/Plugin/CKEditorPlugin/DrupalImage.php
@@ -85,4 +125,14 @@ public function validateImageUploadSettings(array $element, FormStateInterface $
+  /**
+   * {@inheritdoc}
+   *
+   */
+  public function getCssFiles(Editor $editor) {
+    return [
+      $this->moduleExtensionList->getPath('filter') . '/css/filter.align.css',
+    ];
+  }

I didn't even consider this before, but @oknate reminded me that hook_ckeditor_css_alter() exists, and IMHO it is what we should use to add this CSS (assuming the format associated with the editor has filter_align enabled). That way, alignment stuff can be used without needing to add it to specific plugins; I think that will be both cleaner and more flexible for non-core code.

But that said, I think we need to really test four overall things here:

  1. When CKEditor is loaded for an input format that uses filter_align, the CSS should always be present. (We can determine this by checking for the presence of filter.align.css, rather than any specific rules.)
  2. But, if that format doesn't have filter_align, it shouldn't be.
  3. Conversely, when formatted text is rendered out (using the processed_text render element), the filter_align CSS should be added as well, if the format is using it...and only if we're using Classy as the front-end theme, or anything derived from it.
  4. Which means that, if the front-end theme is not Classy-based, then the CSS should not be added.
oknate’s picture

See next comment.

oknate’s picture

Status: Needs work » Needs review
StatusFileSize
new8.24 KB
new10.71 KB

Responding to #40:
1. This is out of scope, but a worthy change. I created a separate issue for it: #3083507: Standardize "plugin ID" in doc comments instead of "plugin_id"
2. Refactored away, skipping.
3. ✅ Updated.
4. Here's a follow-up for the css side-effect of fixing nested alignment for the widget: #3083510: Fix side-effect of nested alignment override css
5. Added @see to a few popular user agent style sheets.
6. ✅ Updated. It took 30 seconds to read the documentation and see you are right. The way I’m using libraries-override it replaces the library, it’s not extending it.
7. ✅ Capitalized “Classy”
8. Oops, yes processed_text, not text_format.

For the image height and width problem I mentioned yesterday, I just included a new ckeditor stylesheet in umami. Bartik has this:

ckeditor_stylesheets:
  - css/base/elements.css

which has this rule:

img {
  max-width: 100%;
  height: auto;
}

The umami theme has this rule too, but it’s not added to the CKEditor.

So I added a ckeditor.css for this theme. For now, I’m only adding this one rule. This allows the fix to work in the CKEditor using the Umami theme.

oknate’s picture

StatusFileSize
new374 bytes
new10.71 KB

This should fix most of the 3,444 failures.

Status: Needs review » Needs work

The last submitted patch, 44: 3078287-44.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

oknate’s picture

Status: Needs work » Needs review
StatusFileSize
new2.71 KB
new11.32 KB

I ran into the new security feature requiring TrustedCallbackInterface or anonymous function. I talked with @phenaproxima and he suggested testing if it's possible to add a class to Classy. Here's the answer. It works locally! It's unprecedented, but it seems the best solution, given the situation.

Status: Needs review » Needs work

The last submitted patch, 46: 3078287-44.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

oknate’s picture

Status: Needs work » Needs review
StatusFileSize
new906 bytes
new11.49 KB

It looks like the text format isn't being loaded in the prerender method in some cases. Drupal\filter\Element\ProcessedText::preRenderText() has code like this:

$format_id = $element['#format'];
...
if (!isset($format_id)) {

So we need to handle when the text format isn't set. Although it's not a real-world situation, we should also handle when the format doesn't have filter_align at all. (The real-world situation is it's added when the filter module is enabled, so most of the time, if you're hitting code loading a filter format, it will have filter_align, but it may be disabled. You would have to create it programmatically to exclude the filter_align filter. Some of the Kernel tests have examples of this.)

Status: Needs review » Needs work

The last submitted patch, 48: 3078287-48.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

oknate’s picture

Status: Needs work » Needs review
StatusFileSize
new790 bytes
new11.64 KB

The following error is turning out to be a very valuable bit of regression testing. I think I've broken this three times in the last month or so. It verifies that when selecting an editor at /admin/config/content/formats/add, there's no dependencies on the editor being able to load a filter format, since neither entity exists yet. The ::getFilterFormat() throws a fatal error if the filter format id isn't set on the Editor object.

) Drupal\Tests\media_library\FunctionalJavascript\CKEditorIntegrationTest::testConfigurationValidation
Failed asserting that a NULL is not empty.

/var/www/html/core/modules/media_library/tests/src/FunctionalJavascript/CKEditorIntegrationTest.php:151

Since I've created brittle code so many times based on this misunderstanding, I'm creating an issue about the ::getFilterFormat() method: #3083746: Editor::getFilterFormat() should throw domain error if Editor::format not set. I think it's not transparent that it will throw an error. The interface says it can return NULL, but that's not the case.

oknate’s picture

I'm thinking filter_ckeditor_css_alter() should be combined with ckeditor_ckeditor_css_alter(). They are very similar. The code in filter_ckeditor_css_alter() should be moved into ckeditor_ckeditor_css_alter().

Also the code in DrupalMedia::isEnabled() is more elegant than what's in filter_ckeditor_css_alter(). So I think we should refactor it to be more like that.

oknate’s picture

StatusFileSize
new3.92 KB
new14.12 KB

Addressing #51 and adding test coverage for ckeditor_ckeditor_css_alter().

oknate’s picture

StatusFileSize
new3.92 KB
new14.12 KB

Ignore this one, failed to update the patch. It was late.

oknate’s picture

Issue tags: -Needs tests
StatusFileSize
new5.88 KB
new16.09 KB

Adding test coverage for ProcessedText class added to Classy, and fixing broken php. Removing "Needs tests" tag. I'm working on Umami theme test, but that could be left out, I guess. It'd be nice to have, but the only logic is the libraries-override. Libraries-override doesn't need testing, but it would be good to prevent regressions to have test coverage that filter.align.css appears in the umami variant in that theme.

oknate’s picture

StatusFileSize
new1.84 KB
new7.72 KB
new17.92 KB

Adding umami test coverage as well. I got stuck on this one for a while, because umami installs text formats, and they were conflicting with the 'test_format' I was trying to bring over from the classy test. Things worked as soon as I figured out the issue. If you have two bits of processed text on the page, one a filter format without filter align and one with a filter format with filter align, the "withs" win out and it displays. So I was getting an unexpected filter.align.css for quite a while, it was darn frustrating, because Umami profile tests are very slow to boot up, there was a lot of waiting around while I tested things out.

oknate’s picture

Title: Constrain the width of aligned images, media, blockquotes etc to a max of 75% » [PP-2] Constrain the width of aligned images, media, blockquotes etc to a max of 75%
StatusFileSize
new881 bytes
new17.42 KB
new26.89 KB

Wim Leers and Lauriii have agreed that we should drop the align-* classes added to the widget wrapper:

#3072279: Stop generating align-* classes for preview in DrupalMedia CKEditor plugin.

As that affects this issue, I'm postponing this issue on that issue.

When 3072279 lands we won't need the problematic overrides like .cke_widget_wrapper.align-left .align-left (see the interdiff)

Note: This could go in first, but then a follow up would be needed after 3072279 lands to remove the overrides (see the interdiff).

oknate’s picture

StatusFileSize
new14.24 MB

Here's a low-res walk through using the standard profile:

Video:
https://www.drupal.org/files/issues/2019-09-27/constrain-width-test-low-...

One thing I noticed. The caption padding/margin is off. I checked and this is true on HEAD, so moving to a separate issue:

#3084368: Too much padding/margin above caption for embedded media

wim leers’s picture

Title: [PP-2] Constrain the width of aligned images, media, blockquotes etc to a max of 75% » [PP-1] Constrain the width of aligned images, media, blockquotes etc to a max of 75%

This is blocked on #3072279: Stop generating align-* classes for preview in DrupalMedia CKEditor plugin, but that issue just became unblocked. So, decreasing the postponement counter.

phenaproxima’s picture

Status: Needs review » Postponed
oknate’s picture

Title: [PP-1] Constrain the width of aligned images, media, blockquotes etc to a max of 75% » Constrain the width of aligned images, media, blockquotes etc to a max of 75%
Assigned: Unassigned » oknate
Status: Postponed » Needs work

blocker is in, needs a reroll to remove css override.

oknate’s picture

Status: Needs work » Needs review
StatusFileSize
new17.42 KB
new909.53 KB
new906.98 KB
new916.08 KB
new918.01 KB
new828.76 KB
new10.49 MB

Here's the reroll. I did a cursory manual retest. Left-align and right-align work great and look great in Standard profile. I need to retest Umami.

Screenshots of patch #61 using Standard / Bartik.
https://www.drupal.org/files/issues/2019-09-30/align-left.png
https://www.drupal.org/files/issues/2019-09-30/align-right.png
https://www.drupal.org/files/issues/2019-09-30/align-left-CKEditor.png
https://www.drupal.org/files/issues/2019-09-30/align-right-CKEditor.png

Center align doesn't work, which I believe is a pre-existing condition and is out of scope. Should we try to fix this here?
https://www.drupal.org/files/issues/2019-09-30/align-center-doesnt-work.png

Here's a video showing the new behavior in CKEditor.
Video:
https://www.drupal.org/files/issues/2019-09-30/aligned-width-constraint-...

oknate’s picture

I also see some of my css without comments explaining why I did it, and I forget why I did it.

  /**
   * If the image is align left, undo the above rule.
   * See core/modules/filter/css/filter.align.css
   */
  .node .media.align-left .field--type-image {
    float: none;
    margin-right: 0px;
  }

So I need to reconstruct the logic, hopefully in comments here, why I did one of two of the new new rules.

oknate’s picture

#3071713: Make error messages for embedded media themeable is RTBC, so we should look into how that affects this issue.

wim leers’s picture

Issue tags: +Needs followup

Center align doesn't work, which I believe is a pre-existing condition and is out of scope. Should we try to fix this here?

😨 Reproduced, this indeed exists in HEAD!

This is caused by

@media all and (min-width: 560px) {
  .node .field--type-image {
    float: left; /* LTR */
    margin: 0 1em 0 0; /* LTR */
  }
  [dir="rtl"] .node .field--type-image {
    float: right;
    margin: 0 0 0 1em;
  }
  .node .field--type-image + .field--type-image {
    clear: both;
  }
}

in core/themes/bartik/css/components/field.css. How the hell did we miss this before?

Let's open a separate issue for that 🙏

oknate’s picture

wim leers’s picture

Status: Needs review » Needs work
  1. +++ b/core/modules/filter/css/filter.align.css
    @@ -0,0 +1,44 @@
    +/**
    + * Constrain the width of aligned elements to a max of 75% when left or right
    + * aligned.
    + */
    +.align-right,
    +.align-left {
    +  max-width: 75%;
    +}
    

    🤔🤔🤔 I'm still concerned why we're doing this on the front end too, instead of just inside CKEditor instances. The issue summary does not explain the reasoning. Nor does the CSS file. The Needs issue summary update tag is already present, so I can't add that.

  2. +++ b/core/modules/filter/filter.module
    @@ -14,6 +14,7 @@
    +use Drupal\editor\Entity\Editor;
    

    🤓 Unused, should be removed.

  3. +++ b/core/profiles/demo_umami/tests/src/Functional/DemoUmamiProfileTest.php
    @@ -239,4 +240,26 @@ protected function drupalLoginWithPassword(AccountInterface $account, $password)
    +   * Tests that umami\align library is added conditionally.
    
    +++ b/core/tests/Drupal/FunctionalTests/Theme/ClassyTest.php
    @@ -35,4 +36,45 @@ public function testRegressionMissingMessagesCss() {
    +   * Tests that classy\align library is added conditionally.
    

    🤓 The backslash should be a forward slash.

  4. +++ b/core/profiles/demo_umami/tests/src/Functional/DemoUmamiProfileTest.php
    @@ -239,4 +240,26 @@ protected function drupalLoginWithPassword(AccountInterface $account, $password)
    +  }
     }
    

    🤓 Missing blank line between these closing braces.

  5. +++ b/core/profiles/demo_umami/themes/umami/css/components/ckeditor.css
    @@ -0,0 +1,9 @@
    +img {
    +  max-width: 100%;
    +  height: auto;
    +}
    
    +++ b/core/profiles/demo_umami/themes/umami/umami.info.yml
    @@ -32,3 +33,6 @@ regions:
    +ckeditor_stylesheets:
    +  - css/ckeditor.css
    

    🤔 I'm surprised we need custom styling for Umami. This IMHO needs documentation. Why do we need this for Umami, but not for any other theme?

  6. +++ b/core/profiles/demo_umami/themes/umami/css/components/filter/filter.align.css
    @@ -0,0 +1,39 @@
    + * Set the margin on figure element to override user agent style sheet and
    + * filter.align.css in Classy.  We're adding a bit of top margin to align
    
    +++ b/core/profiles/demo_umami/themes/umami/umami.info.yml
    @@ -12,6 +12,7 @@ libraries:
    +  classy/align: umami/align
    

    This is a contradiction: the CSS cannot be overriding Classy CSS if Classy CSS is not being loaded at all.

  7. +++ b/core/profiles/demo_umami/themes/umami/umami.libraries.yml
    @@ -50,6 +50,11 @@ global:
    +      css/components/filter/filter.align.css: { weight: -10 }
    
    +++ b/core/themes/classy/classy.libraries.yml
    @@ -97,3 +97,9 @@ user:
    +      css/components/filter.align.css: { weight: -10 }
    

    🤔 Why -10?

  8. +++ b/core/profiles/demo_umami/themes/umami/umami.libraries.yml
    @@ -124,3 +129,4 @@ demo-umami-tour:
    +
    

    🤓 Unnecessary change.

  9. +++ b/core/themes/bartik/css/components/field.css
    @@ -48,6 +48,17 @@
    +   * If the image is align left, undo the above rule.
    

    🤓 s/align/aligned/

  10. +++ b/core/themes/bartik/css/components/field.css
    @@ -48,6 +48,17 @@
    +   * See core/modules/filter/css/filter.align.css
    

    🤓 s/See/@see/

  11. +++ b/core/themes/bartik/css/components/field.css
    @@ -48,6 +48,17 @@
    +  .node .media.align-left .field--type-image {
    +    float: none;
    +    margin-right: 0px;
    

    🤔 Are we sure this is the correct approach? Can't we instead make the rule this is overriding a bit more strict?

  12. +++ b/core/themes/bartik/css/components/field.css
    @@ -48,6 +48,17 @@
    +  }
    +
    +
       [dir="rtl"] .node .field--type-image {
    

    🤓 Two blank lines, should be one.

oknate’s picture

Issue summary: View changes

Addressing #66.1, I'll rewrite the issue summary. I'm realizing the scope of this issue is vast and we should probably break it up a bit.

oknate’s picture

Issue summary: View changes

To reduce scope, let's move all changes related to margin around figure elements to this follow-up issue:
#3085736: Figure elements that are right-aligned or left-aligned have too much margin.

oknate’s picture

Issue summary: View changes
oknate’s picture

Issue summary: View changes
oknate’s picture

Issue summary: View changes
oknate’s picture

Issue summary: View changes
oknate’s picture

Issue summary: View changes
oknate’s picture

Issue summary: View changes
oknate’s picture

Issue summary: View changes
StatusFileSize
new8.84 KB
new10.81 KB

Responding to #66:

In general, I'm reducing scope and removing some of the minor fixes for side issues (mostly around margins, especially with figures and captions).

1. ✅ Updated the issue summary.
2. ✅ Removed.
3. ✅ Fixed classy/align forward slash.
4. ✅ Updated.
5. I added this in #43, and I refer to “the height and width problem I mentioned yesterday”, but I don’t see the comment I’m referring to. For now I think it’s best to drop this. If I see the issue again, I’ll add it in a follow-up. A nice demonstration of why very explicit comments both in the issue and the code are important.
6. 😁✅I changed the umami info from an extend to an override. Updating the comment. Update: and now removed or refactored away.
7. ✅ Removed -10, that was a cut-and-paste thing from when I copied this from Classy. There no reason behind it.
8. I think this refactored away. I’m moving the library up so as not to conflict with the patch about theming media embed errors.
9. ✅ Updated.
10 ✅ Updated.
11. and 12. I’m going to drop this for now. I’m having trouble reproducing the issue, and I didn’t document it well. I think perhaps I was duplicating this:

.caption .media .field,
.caption .media .field * {
  float: none;
  margin: unset;
}

from core/themes/stable/css/media/filter.caption.css

oknate’s picture

Status: Needs work » Needs review
oknate’s picture

Issue summary: View changes
oknate’s picture

Issue summary: View changes
oknate’s picture

Assigning draft credit to @lauriii and @phenaproxima.

And that didn't work?

oknate’s picture

Issue summary: View changes

Removing "Determine the scope for this issue and add separate or follow-up issues for other issues." I think I've reduced the scope enough and added follow-ups.

The only question is if we want to break this up into two issues:
1) changes within the WYSIWYG
2) changes outside the WYSIWYG

I get the sense based on this being reopened to address the second scope that it should be handled in one issue.

oknate’s picture

Issue summary: View changes

Adding draft change record:
https://www.drupal.org/node/3085749

oknate’s picture

Issue summary: View changes
oknate’s picture

Removing tags

wim leers’s picture

Assigned: oknate » lauriii
  1. #75.5: Agreed! 😊 But often easier said than done.
  2. #75: 👍
  3. My concern about doing this on the front end too still stands. I believe we should do this only in CKEditor iframe instances. I'm fine adding CSS to Classy for this too, but I do believe we should not try to closely match them — the CKEditor iframe viewport is always going to be much narrower, so there's no point IMHO. Assigning to @lauriii in his role as front end framework manager for making a decision :)
  4. +++ b/core/modules/filter/css/filter.align.css
    @@ -0,0 +1,44 @@
    + * @code
    + *   margin-inline-start: 40px;
    + *   margin-inline-end: 40px;
    + * @endcode
    

    What is this doing here? According to https://developer.mozilla.org/en-US/docs/Web/CSS/margin-inline-start, these are experimental CSS properties. But surprisingly widely supported.

    But then there's no further explanation as to why this is listed here. Do we want to use this in the future?

oknate’s picture

StatusFileSize
new814 bytes
new10.29 KB

#84.4 Oops, that should no longer be added in this issue. That was part of my attempt to fix margins around captioned media embeds. See #68 and the follow-up: #3085736: Figure elements that are right-aligned or left-aligned have too much margin.

I have been testing in Chrome. Given we have limited space in the WYSIWYG, 80 px of margin is frustratingly greedy. I moved it to a follow-up so that we can reduce the scope here. The 75% constraint will give us some room to do what we need to do.

phenaproxima’s picture

Issue tags: -Needs usability review
  1. +++ b/core/themes/classy/src/ProcessedText.php
    @@ -0,0 +1,50 @@
    +/**
    + * Class to hold trusted callback for processed text.
    + */
    +class ProcessedText implements TrustedCallbackInterface {
    

    Maybe worth asking @lauriii, but: should this class be marked @internal? It's doing things that are totally specific to Classy.

  2. +++ b/core/themes/classy/src/ProcessedText.php
    @@ -0,0 +1,50 @@
    +    $format = \Drupal::entityTypeManager()
    +      ->getStorage('filter_format')
    +      ->load($element['#format']);
    

    Nit: This can be using FilterFormat::load().

Apart from these minor things, the code looks good.

I'm removing the "needs usability review" tag, because I don't think this needs usability review. It's not really introducing any new patterns, or modifying existing ones -- it's trying to prevent a usability problem. I added the tag back #10, but a lot has happened since then which I think makes the tag irrelevant.

wim leers’s picture

That only leaves my concern in #84.3. It's already assigned to @lauriii for that. Tagging Needs subsystem maintainer review to stress that even more.

oknate’s picture

StatusFileSize
new753 bytes
new10.27 KB

Fixing #86.1.

For #86.2, I think classes that extend classy could override this. It's so small, I don't know why they would, but I don't think it needs to be marked internal, if the concern is other themes misusing class.

lauriii’s picture

Assigned: lauriii » Unassigned

I'm fine adding CSS to Classy for this too, but I do believe we should not try to closely match them — the CKEditor iframe viewport is always going to be much narrower, so there's no point IMHO.

For example, just testing Umami and Claro, it looks like CKEditor is rendered much wider than the actual page. Content can be also rendered in different sizes and formats - not all content is rendered as a full page. Even if this is the case for the Node entity type, CKEditor can be used for other entity types. Serving a max-width as part of the alignment everywhere makes sense because in both use cases, not having a max-width could lead to poor UX.

Also, making this change only in CKEditor would mean that the layout behaves differently depending on whether you're viewing the content on the frontend or in CKEditor. I understand that CKEditor cannot replicate the page 100% and it doesn't try to achieve that, but this type of layout rules are pretty visible. I think it's great if we can have consistency. Classy is a theme with sensible defaults and since we think this improves UX in some use cases without any real downsides, I don't really understand why we wouldn't make this change?

wim leers’s picture

Content can be also rendered in different sizes and formats - not all content is rendered as a full page. Even if this is the case for the Node entity type, CKEditor can be used for other entity types.

Right … and that to me is a reason to not do theme-specific width restrictions. Because CKEditor <iframe> instances only know they're operating on a text field. So there is no way for a theme to provide different width restrictions for e.g. a block body field vs a node body field vs a product description field.

Serving a max-width as part of the alignment everywhere makes sense because in both use cases, not having a max-width could lead to poor UX.

Sure, but that's not my concern. Let me repeat #84.3: I'm fine adding CSS to Classy for this too, but I do believe we should not try to closely match them.

Classy is a theme with sensible defaults and since we think this improves UX in some use cases without any real downsides, I don't really understand why we wouldn't make this change?

Again, just like I said in #84.3: I'm fine with Classy also shipping with some width restrictions. But it's important to stress that there's no 1:1 relationship, no promise of an exact match. My concern here is with establishing an expectation. And since the current patch adds the exact same CSS for both filter.module and classy.theme, that is a concern for me.

wim leers’s picture

+++ b/core/themes/classy/classy.theme
@@ -0,0 +1,17 @@
+function classy_element_info_alter(array &$info) {
+  if (array_key_exists('processed_text', $info)) {
+    $info['processed_text']['#pre_render'][] = [ProcessedText::class, 'preRender'];
+  }
+}

+++ b/core/themes/classy/src/ProcessedText.php
@@ -0,0 +1,49 @@
+  public static function preRender(array $element) {
...
+    if ($filter_align && $filter_align->status) {
+      $element['#attached']['library'][] = 'classy/align';
+    }

If we're going to do this, we need clear documentation for why this cannot use libraries-override to override filter/align. This is very complex.

(I didn't point this out before because I wasn't sure whether the new alignment CSS in Classy would stay. It sounds like it will now, so pointing it out now.)

wim leers’s picture

To clarify #90: I see three possible solutions:

  1. No classy-specific CSS.
  2. classy-specific CSS that does not match filter's CSS + document explicitly why.
  3. classy-specific CSS that matches filter's CSS + document even more explicitly why.

(In order of my personal preference — obviously we're not going with the first option based on @lauriii's feedback 🤓.)

wim leers’s picture

Status: Needs review » Needs work

In chatting with @lauriii and @phenaproxima, I decided to apply the patch and test it manually. I spotted another problem.

  1. +++ b/core/themes/stable/stable.info.yml
    @@ -117,6 +117,10 @@ libraries-override:
    +  filter/align:
    +    css:
    +      component:
    +        css/filter.align.css: css/filter/filter.align.css
    

    This does not work (the stable override is never used), because …

  2. +++ b/core/modules/filter/filter.libraries.yml
    @@ -31,3 +31,9 @@ caption:
    +align:
    +  version: VERSION
    +  css:
    +    component:
    +      css/filter.align.css: {}
    

    This is never used!

  3. +++ b/core/modules/ckeditor/ckeditor.module
    @@ -60,12 +60,21 @@ function ckeditor_ckeditor_css_alter(array &$css, Editor $editor) {
    +  if ($filters->has('filter_align') && $filters->get('filter_align')->status) {
    +    $css[] = drupal_get_path('module', 'filter') . '/css/filter.align.css';
    +  }
    

    That is never used because core/modules/filter/css/filter.align.css is only ever loaded here, via CKEditor's <iframe>-only stylesheets loading, not through Drupal asset library loading.

  4. Note that 1+2 could be addressed by having FilterAlign attach the filter/align library, which would also remove the need for the pretty complex hack in Classy to be able to attach CSS. #31 stopped doing that.

    @oknate did that in response to my #26.3, where I raised concern we'd do exactly the same on the front end as what we do in CKEditor instances. But … we're doing that anyway in the current patch, so what's the point of this convoluted alternative way of loading CSS? 🤷‍♂️

    @lauriii has said we should also be loading alignment CSS for Classy. Fine. So then let's let Classy do a libraries-override for filter/align?

I know we've gone back-and-forth a lot here. My primary concern is expectations for the content author. My secondary concern is grokkability of what a front end developer sees going on in Classy. The points in this review hopefully bring us back on track to solve the last few concrete concerns before we can ship this. 🤞

webchick’s picture

Ok, just a little history lesson here, to maybe help with arriving at agreement on the plan of attack.

This issue was originally filed, because if you insert a media into CKEditor, and it's of a certain size, it makes your text reflow like this:

Paragraph squished into a single column of text

...now you basically can't update your text, because it's illegible.

(I was not able to reproduce this problem with Image images, either because I did something wrong, or because images do some other funky-special CSS thing, or whatever.)

That's it. That's the bug.

To fix it, we needed to either a) allow people to resize their media in the WYSIWYG editor, or b) *force* a size such that this "illegible text smooshing" situation can't happen.

For a), we already committed #3074608: Optionally allow choosing a view mode for embedded media in EditorMediaDialog, so there is now a workaround, albeit one quite advanced. We also discussed offering drag handles for parity with images, but this caused Wim to flip a table while guzzling the blood of an unstructured glomp of text. ;) We also discussed a width percentage selector, captured at #3081303: Allow media embed width constraint to be configurable. This would actually be a superior approach to this, but we tabled it since it sounded like it was going to be a can of worms.

Since we didn't know if the two viable alternatives under a) would come together in time, we opened *this* issue to hard-code a sensible default in CKEditor media embeds, in theory a "one line patch" (lol) to satisfy the problem. Clearly, this has not borne out to be the case... and we have now escalated from "can of worms" to like... "basket of spiders" territory. 😂

So if #3081303: Allow media embed width constraint to be configurable looks like it will be easier to resolve all the concerns here (which it might be, since the percentage chosen would be the same on front-end + back-end, thus negating inconsistency concerns), then let's maybe do that instead. But still only in a "should have" capacity, since there is now a workaround in 8.8.x for the original bug that was identified.

(I worried that these two—view modes and width percentages—might be incompatible, but Alex pointed out they are not, since you can still take a "thumbnail" media size and make it 50% of that.)

I'm also just as happy to "won't fix" this one, and leave #3081303: Allow media embed width constraint to be configurable around for "if we ever get around to it." Or if this one is 99.9% of the way there, finish it off.

Basically, whatever causes the least amount of angst, and allows us to hyper focus efforts on must-haves for this initiative, +1.

wim leers’s picture

Assigned: Unassigned » wim leers

We also discussed offering drag handles for parity with images, but this caused Wim to flip a table while guzzling the blood of an unstructured glomp of text. ;)

Perhaps part that, but far more importantly: A) it'd only work for image media, B) how would we pass that width and height in pixels on to the view mode, and then on to the field formatter, and then on to the image style, C) it would not work at all with responsive images.

we have now escalated from "can of worms" to like... "basket of spiders" territory. 😂

😂

(I worried that these two—view modes and width percentages—might be incompatible, but Alex pointed out they are not, since you can still take a "thumbnail" media size and make it 50% of that.)

+1


I think this has been close for a while, but those last few things are important for long-term maintainability. And conveying the nuances of those impacts is where I've been unsuccessful at convincing and/or explaining it to others.

So let's turn this around by letting me roll a counterproposal patch that is still 90% the same as the latest patch. Then I can hear from @oknate, @phenaproxima, @lauriii, @effulgentsia and @webchick where that is falling short.

Stay tuned 😊

wim leers’s picture

Assigned: wim leers » Unassigned
Status: Needs work » Needs review
StatusFileSize
new5.54 KB
new9.53 KB

So let's turn this around by letting me roll a counterproposal patch that is still 90% the same as the latest patch. Then I can hear from @oknate, @phenaproxima, @lauriii, @effulgentsia and @webchick where that is falling short.

Did that.

wim leers’s picture

To aid reviewers, here's the rationale for each of the changes in #96's interdiff:

  1. +++ b/core/modules/ckeditor/ckeditor.module
    @@ -72,6 +72,7 @@ function ckeditor_ckeditor_css_alter(array &$css, Editor $editor) {
    +  // @see core/modules/filter/filter.libraries.yml
    

    This stresses the relationship between the "load additional CSS files into the CKEditor <iframe> instance" logic and the asset loading logic in all other situations.

  2. +++ b/core/modules/filter/src/Plugin/Filter/FilterAlign.php
    @@ -40,7 +40,12 @@ public function process($text, $langcode) {
    -      $result->setProcessedText(Html::serialize($dom));
    +      $result->setProcessedText(Html::serialize($dom))
    +        ->addAttachments([
    +          'library' => [
    +            'filter/align',
    +          ],
    +        ]);
    

    This ensures that the asset library is actually used, which means that stable's override of this also actually works.

  3. +++ b/core/tests/Drupal/FunctionalTests/Theme/ClassyTest.php
    @@ -57,7 +55,7 @@ public function testFilterAlignCss() {
    -        'value' => 'Highly illogical.',
    +        'value' => '<blockquote data-align="center">Highly illogical.</blockquote>',
    

    Now that we're loading the asset library in the alignment filter, the asset library is also only loaded when it's needed. So, we need to actually trigger the use of the alignment filter.

  4. +++ b/core/themes/classy/classy.info.yml
    @@ -26,5 +26,8 @@ libraries-extend:
    +libraries-override:
    +  filter/align: classy/align
    
    +++ /dev/null
    @@ -1,17 +0,0 @@
    -function classy_element_info_alter(array &$info) {
    -  if (array_key_exists('processed_text', $info)) {
    -    $info['processed_text']['#pre_render'][] = [ProcessedText::class, 'preRender'];
    -  }
    
    +++ b/core/themes/classy/css/components/filter.align.css
    @@ -1,6 +1,6 @@
    diff --git a/core/themes/classy/src/ProcessedText.php b/core/themes/classy/src/ProcessedText.php
    

    Rather than doing something complex to always load Classy's override of the (previously unused …) filter/align asset library, we can just use the existing libraries-override infrastructure instead.

  5. +++ b/core/themes/classy/css/components/filter.align.css
    @@ -1,6 +1,6 @@
    - * Align filter: default styling for displaying aligned images, media, etc.
    + * Override of core/modules/filter/css/filter.align.css.
    

    I still don't really see the value of having Classy override this if the CSS is 100% the same, but if we're going to do this, then this is what I think we need to change to avoid confusion about why we're doing this at all: document that it is an override.

Status: Needs review » Needs work

The last submitted patch, 96: 3078287-96.patch, failed testing. View results

wim leers’s picture

Status: Needs work » Needs review
StatusFileSize
new2.33 KB
new14.62 KB
+++ b/core/modules/filter/src/Plugin/Filter/FilterAlign.php
@@ -40,7 +40,12 @@ public function process($text, $langcode) {
-      $result->setProcessedText(Html::serialize($dom));
+      $result->setProcessedText(Html::serialize($dom))
+        ->addAttachments([
+          'library' => [
+            'filter/align',
+          ],
+        ]);

requires some test assertions to be updated. Did that.

Status: Needs review » Needs work

The last submitted patch, 99: 3078287-99.patch, failed testing. View results

oknate’s picture

Status: Needs work » Needs review
StatusFileSize
new645 bytes
new14.29 KB

Fixing one test.

diff --git a/core/modules/media/tests/src/Kernel/MediaEmbedFilterTest.php b/core/modules/media/tests/src/Kernel/MediaEmbedFilterTest.php
index 7ae880a51c..ca9b90d471 100644
--- a/core/modules/media/tests/src/Kernel/MediaEmbedFilterTest.php
+++ b/core/modules/media/tests/src/Kernel/MediaEmbedFilterTest.php
@@ -191,7 +191,7 @@ public function providerAccessUnpublished() {
           ])
           ->setCacheContexts(['timezone', 'user', 'user.permissions'])
           ->setCacheMaxAge(Cache::PERMANENT),
-        ['library' => ['filter/align', 'media/filter.caption']],
+        ['library' => ['media/filter.caption']],
       ],
     ];
   }

This library isn't attached to embedded media now.

The last submitted patch, 99: 3078287-99.patch, failed testing. View results

Status: Needs review » Needs work

The last submitted patch, 101: 3078287-100.patch, failed testing. View results

wim leers’s picture

Status: Needs work » Needs review
StatusFileSize
new3.15 KB
new11.41 KB
1) Drupal\Tests\block\Functional\BlockCacheTest::testCachePerRole
Drupal\Core\Config\UnmetDependenciesException: Configuration objects provided by block_test have unmet dependencies: block.block.test_block (classy)

These failures do not make sense!

Oh but wait …

+++ b/core/modules/simpletest/src/WebTestBase.php
@@ -387,16 +387,18 @@ protected function setUp() {
-    $container = $this->initKernel(\Drupal::request());
+    $this->container = $container = $this->initKernel(\Drupal::request());
 
     // Initialize and override certain configurations.
     $this->initConfig($container);
 
-    $this->installDefaultThemeFromClassProperty($container);
-
     // Collect modules to install.
     $this->installModulesFromClassProperty($container);
 
+    // Install the default theme using the new container at this point
+    // $container can be stale as module installation will rebuild it.
+    $this->installDefaultThemeFromClassProperty($this->container);

+++ b/core/tests/Drupal/TestSite/Commands/TestSiteInstallCommand.php
@@ -198,10 +198,12 @@ protected function installDrupal() {
     $this->doInstall();
     $this->initSettings();
-    $container = $this->initKernel(\Drupal::request());
+    $this->container = $container = $this->initKernel(\Drupal::request());
     $this->initConfig($container);
-    $this->installDefaultThemeFromClassProperty($container);
     $this->installModulesFromClassProperty($container);
+    // Install the default theme using the new container at this point
+    // $container can be stale as module installation will rebuild it.
+    $this->installDefaultThemeFromClassProperty($this->container);
     $this->rebuildAll();

+++ b/core/tests/Drupal/Tests/BrowserTestBase.php
@@ -564,10 +564,12 @@ public function installDrupal() {
     $this->initSettings();
-    $container = $this->initKernel(\Drupal::request());
+    $this->container = $container = $this->initKernel(\Drupal::request());
     $this->initConfig($container);
-    $this->installDefaultThemeFromClassProperty($container);
     $this->installModulesFromClassProperty($container);
+    // Install the default theme using the new container at this point
+    // $container can be stale as module installation will rebuild it.
+    $this->installDefaultThemeFromClassProperty($this->container);
     $this->rebuildAll();
   }

ARGH! I accidentally included these in #99. Juggling many patches. Sorry about that 🤦‍♂️

oknate’s picture

It happens!

The last submitted patch, 101: 3078287-100.patch, failed testing. View results

wim leers’s picture

Alright, now I'm curious about @phenaproxima's, @oknate's and @lauriii's feedback :)

oknate’s picture

I think everyone gave up in the short term on this issue because there were more important issues before the alpha deadline, and consensus couldn't be agreed upon as to how much we should do at the theme level. Given that it was Wim who was expressing those concerns, and that he has proffered a solution that he supports I think we could revisit this issue before the alpha deadline if other more important fixes are in.

I give it a thumbs up. This may not be a perfect solution, but it's easy to iterate on it in future releases, and this solve an ugly UX problem.

Here's a video of my testing of #104 on the standard install:

With patch:
https://www.drupal.org/files/issues/2019-10-10/snake-river-10-10-2019-st...

Without patch:
https://www.drupal.org/files/issues/2019-10-10/without-the-patch-10-10-2...

Note: I didn't look at the code closely. I'll try to do that tomorrow morning.

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.0-alpha1 will be released the week of October 14th, 2019, which means new developments and disruptive changes should now be targeted against the 8.9.x-dev branch. (Any changes to 8.9.x will also be committed to 9.0.x in preparation for Drupal 9’s release, but some changes like significant feature additions will be deferred to 9.1.x.). For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

wim leers’s picture

#108: I'm interested in hearing how/where this results in a different experience than #88, and especially where you think it's inferior. I'm glad to hear you're okay with it, but I'd love to read more nuance. :)

wim leers’s picture

Bump. This is the last remaining should-have of #2801307: [META] Support WYSIWYG embedding of media entities. Let's get this done :)

dww’s picture

I haven't closely read every comment in here, but I see no explanation of this in the summary, nor on a quick skim of recent-ish comments, so I'll ask here:

+++ b/core/tests/Drupal/FunctionalTests/Theme/ClassyTest.php
@@ -27,4 +28,43 @@ public function testRegressionMissingMessagesCss() {
+   * Tests that the classy/align library override of filter/align is loaded.

+++ b/core/themes/classy/classy.info.yml
@@ -26,5 +26,8 @@ libraries-extend:
+libraries-override:
+  filter/align: classy/align
+

+++ b/core/themes/classy/classy.libraries.yml
@@ -26,6 +26,12 @@ base:
+align:
+  version: VERSION
+  css:
+    component:
+      css/components/filter.align.css: {}
+

+++ b/core/themes/classy/css/components/filter.align.css
@@ -0,0 +1,25 @@
+/**
+ * @file
+ * Override of core/modules/filter/css/filter.align.css.
+ */

+++ b/core/themes/stable/css/filter/filter.align.css
@@ -0,0 +1,25 @@
+/**
+ * @file
+ * Align filter: default styling for displaying aligned images, media, etc.
+ */

+++ b/core/themes/stable/stable.info.yml
@@ -117,6 +117,10 @@ libraries-override:
+  filter/align:
+    css:
+      component:
+        css/filter.align.css: css/filter/filter.align.css

What gives? ;)

A) I thought we weren't allowed to touch Stable and Classy except for critical bugs.

B) The "overrides" are completely identical to the filter module's upstream CSS. We're not overriding anything here. We're just jumping through a lot of hoops, apparently for nothing.

Can we either rip all this complication out of the patch, or document why we need it (either in the issue summary, the code, or both)?

Otherwise, big +1 to getting this in. It is indeed an important fix for a potentially common usability problem.

Thanks!
-Derek

chris matthews’s picture

StatusFileSize
new64.36 KB

@seanB, @WimLeers, @oknate, @phenaproxima, @webchick @lauriii, @dww - Media in 8.8.0 ROCKS! Thank you so much for all of the time and energy that went into making this happen! I was just curious where things stand re: the status of this issue. As you probably know, the contrib Media module allows for the setting of the horizontal and vertical space inside the image property dialogue (screenshot below), but based on this thread I understand the complexities of providing this type of functionality in core. Is the patch in #104 the proposed solution? The video with the patch in #108 seems great to me.

Horizontal and Vertical Space

oknate’s picture

1) This will need a major reroll. There were some last minute changes that moved a bunch of things in regards to Media Library and Media embeds.
2) We couldn't reach consensus in this issue on an approach and scope.
3) This issue is currently on hiatus, as no one is actively working on it. For it to move forward, someone will need to dedicate some effort to reawaken the issue. I think everyone wants some of it to happen. But there is the question of technical debt, if we commit a temporary solution. There have been discussions of various UIs where the user could adjust the width and height of the images that would conflict with putting a constraint such as 75%.

Version: 8.9.x-dev » 9.1.x-dev

Drupal 8.9.0-beta1 was released on March 20, 2020. 8.9.x is the final, long-term support (LTS) minor release of Drupal 8, which means new developments and disruptive changes should now be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 9.1.x-dev » 9.2.x-dev

Drupal 9.1.0-alpha1 will be released the week of October 19, 2020, which means new developments and disruptive changes should now be targeted for the 9.2.x-dev branch. For more information see the Drupal 9 minor version schedule and the Allowed changes during the Drupal 9 release cycle.

Version: 9.2.x-dev » 9.3.x-dev

Drupal 9.2.0-alpha1 will be released the week of May 3, 2021, which means new developments and disruptive changes should now be targeted for the 9.3.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.0-rc1 was released on November 26, 2021, which means new developments and disruptive changes should now be targeted for the 9.4.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.4.x-dev » 9.5.x-dev

Drupal 9.4.0-alpha1 was released on May 6, 2022, which means new developments and disruptive changes should now be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.5.x-dev » 10.1.x-dev

Drupal 9.5.0-beta2 and Drupal 10.0.0-beta2 were released on September 29, 2022, which means new developments and disruptive changes should now be targeted for the 10.1.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

needs-review-queue-bot’s picture

Status: Needs review » Needs work
StatusFileSize
new145 bytes

The Needs Review Queue Bot tested this issue. It either no longer applies to Drupal core, or fails the Drupal core commit checks. Therefore, this issue status is now "Needs work".

Apart from a re-roll or rebase, this issue may need more work to address feedback in the issue or MR comments. To progress an issue, incorporate this feedback as part of the process of updating the issue. This helps other contributors to know what is outstanding.

Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.

Version: 10.1.x-dev » 11.x-dev

Drupal core is moving towards using a “main” branch. As an interim step, a new 11.x branch has been opened, as Drupal.org infrastructure cannot currently fully support a branch named main. New developments and disruptive changes should now be targeted for the 11.x branch, which currently accepts only minor-version allowed changes. For more information, see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 11.x-dev » main

Drupal core is now using the main branch as the primary development branch. New developments and disruptive changes should now be targeted to the main branch.

Read more in the announcement.