Emoji issue when rendering on webkit - Issue with how HTML is rendered

We have lots of users that uses Apple devices and/or webkit based browser report issue when scrolling the topics to the point of the forum being unusable.

An example, taken on video here.

After doing quite some digging, it seems that the most probable cause is how webkit is… how to I put this mildly… trash at handling image resizing.

However, that led also to noticing how the emojis are rendered in the cooked html and I’d like some clarification because maybe I’m missing some configuration that I could have done that prevented this.

In green you can see the original size of the emoji.

In azure/cyan/whatever the default attributes added by Discourse when cooking the content.

In red the CSS added by the plugin I wrote that:

  • import the emojis (they are quite a lot)
  • add some custom CSS to have them render properly as they are not all “20 by 20”

Now I’ve run a simple test. Removed from the cooked field in the DB for that topic, all the width="20" height="20" and asked the users to try again and visualize che topic, scrolling, replying even if someone is adding new posts but without using emoji as to not inject again those two attributes in the rendered html of the emojis.

Apparently that was what is causing the issues on webkit as all reports I have confirm that now that those two attributes are removed, there is not issue with the scrolling.

So, is there a way to prevent Discourse from adding those parameters? Why is discourse assuming that every emoji is going to be “20x20” and, on top of that, enforcing it via html attribute instead of using CSS?

Thank you

I was able to repro on my iPad but not on Chrome desktop.

I scroll up, and the timeline goes back to the previous post, making it difficult to scroll past and go further up in the timeline.

But I have a hard time to repro it consistently. I was stuck a post #1955, but after I was able to scroll up past it, if I went back down and scroll up again, it wouldn’t block me anymore :thinking:

The reason is that it happens every time a new emoji is being “lazy loaded” and the size attributes are being rendered.

Once it’s rendered, the issue doesn’t happen. But if you go through a topic with lots of replies and in which emoji are used a fair bit, you’ll constantly see this behaviour happens and it will make using Discourse impossible.

We managed to “fix” it in our custom theme but I think this should be addressed in the default theme as well, or even better, in the function that cook the posts as I can’t see a reason for those size related html attributes to be applied instead of using simple CSS.

I’ll add that every browser for iOS seems to be using webkit, so it’s going to be an issue mostly for apple device. I’m not an expert on it tho, so take this with a grain of salt. Some more testing would be required.

1 Like

That’s because all the standardized unicode emoji are meant to fit into a square, and we assume sites want their emoji to be sized consistently in a way that works alongside text and other emoji :teapot: if that teapot was 50x50 it would put a huge gap between lines like this:

Screenshot 2023-03-13 at 5.36.36 PM

There’s a good explanation from when it was originally added:

With supporting details from Multimedia: Images - Learn web development | MDN

When the width and height attributes of an image are included on an HTML <img> element, the aspect ratio of the image can be calculated by the browser prior to the image being loaded. This aspect ratio is used to reserve the space needed to display the image, reducing or even preventing a layout shift when the image is downloaded and painted to the screen. Reducing layout shift is a major component of good user experience and web performance.

While developer best practices from the last decade may have recommended omitting the width and height attributes of an image on an HTML <img>, due to aspect ratio mapping, including these two attributes is considered a developer best practice.

All that said, you’ve got a reasonable example of a case where the default sizing won’t work for all emoji… that old cheers emoji is 3x as wide, so it doesn’t fit nicely in a square. It’s not unusual for other apps to limit all emoji to squares so we’re not too unusual in our behavior here (both Slack and Discord do it, for example)… but alternatively we could considering allowing custom emoji to optionally have dimensions set.

1 Like

From the CSS side this is easily implemented:

img.emoji {
  width: auto; /* replacing width: 20px; */
  height: 20px;
  vertical-align: text-bottom;

(See DEV: add native lazy loading for emojis by rr-it · Pull Request #15830 · discourse/discourse · GitHub for explanation.)

The harder work is on the “custom emoji” part and emoji rendering:

  • custom emoji needs an extra attribute for each emoji: aspect-ratio (or as an alternative height and width).
  • emoji rendering must use the new attribute aspect-ratio for custom emoji to vary the width accordingly – height stays at 20px.

Fast and easy approach for custom emoji:
For custom emoji img-tags set height="20" only and don’t set width at all – thereby ditching the benefit of setting aspect-ratio/width and height.
CSS: img.emoji { width: auto; }