mjmlio / mjml

MJML: the only framework that makes responsive-email easy
https://mjml.io
MIT License
17.08k stars 960 forks source link

css-class is not applied to some elements like mj-button #1972

Closed oscarotero closed 4 years ago

oscarotero commented 4 years ago

Describe the bug The documentation says that mj-button have the css-class property but this value is never applied. After inspect the code, I didn't see any reference to css-class anywhere, so I guess this property is ignored. I could experiment the same bug with other components like mj-image, for instance.

To Reproduce Steps to reproduce the behavior:

  1. Create a file with this MJML code:
    <mjml>
    <mj-head>
    <mj-style>
      .primary {
        background-color: red !important;
        color: white !important;
      }
    </mj-style>
    </mj-head>
    <mj-body>
    <mj-section>
      <mj-column>
        <mj-button css-class="primary">
          Click me!
         </mj-button>
      </mj-column>
    </mj-section>
    </mj-body>
    </mjml>
  2. Render it to HTML
  3. See the html in a browser or an email client

Expected behavior The button should have the "primary" class anywhere and it should look with a red background and white text.

MJML environment (please complete the following information):

iRyusa commented 4 years ago

It does work fine css class are applied on the top level element of the render tree (td for column elements).

https://mjml.io/try-it-live/Hyk3ndQJP you can just view the html to see where your css rules are even applied here.

burakkilic commented 3 years ago

I agree with @oscarotero . I'm trying to apply css-class to an mj-button but I couldn't.

iRyusa commented 3 years ago

As you can’t go back to ancestors in CSS it’s way better that way. If you really need this you can use mj html attributes to add a css class anywhere

On 7 May 2021, at 22:16, burakkilic @.***> wrote:

 I agree with @oscarotero . I'm trying to apply css-class to an mj-button but I couldn't.

— You are receiving this because you modified the open/close state. Reply to this email directly, view it on GitHub, or unsubscribe.

GarryFlemings commented 3 years ago

@burakkilic Keep in mind that HTML and MJML attributes, even with the same names, may be different. In the case of mj-button, MJML's background-color affects a different region than HTML's background-color.

Consider https://mjml.io/try-it-live/clYisczGX_B. I colored the three relevant regions of mj-button with colors different than those in the .primary class.

In the rendering, you see their effect.

Look at the HTML in Try-it-Live (it's on MJML 4.7.1 at this writing). You'll find "pink" only on line 108. "green" appears twice on line 111 and once on 112. "aqua" is only on line 112.

Now, add css-class="primary" to the mj-button with what's already there.

The rendering shows this.

Why? Let's look at the HTML.

The references to pink, green, and aqua mentioned above for HTML lines 108 to 112 remain.

Line 108 has a new entry, class="primary". So this <td> is the element that gets the class. Obviously, the HTML background-color in "primary" beat the HTML style="background:pink;" inline in line 108. We see that the region that was pink is red. Probably had some to do with CSS Specificity and that !important hammer!

What happened with color: white !important? There's no attribute for text color in this <td> element and even if it could cascade, CSS Specificity says it gets a score of 0 when cascading. So, four elements and four lines later, when we get to the <p> element containing both the reference to color:aqua; and the text for the button, anything cascading has no effect. That explains the lack of effect of white !important.

Maybe you thought the HTML background-color: red !important would affect the background color of the button? There's no documentation in either HTML or MJML that says that. You've done the experiment to determine what it actually affects. And you've proven that for this usage of mj-button in version 4.7.1, HTML background-color is the same as MJML container-background-color. (It's probably true under other conditions too, but confirming it for other usages is a good idea!)

HTML attributes and MJML attributes are separate sets. One set can be used only in HTML constructs; the other only in MJML constructs. They're different.

@iRyusa is entirely right that MJML is acting as expected. (He's pretty good at getting it right!)

Here's the point for all of us, though: Wish as we might, we cannot depend on "css-class applying to the top-level element" to do what we think it should do. It follows HTML/CSS rules. If that's not the effect you want, you can continue the process to the next step and target the correct part of the DOM. Either use the recent <mj-html-attributes> component or apply the "old school" mj-style technique available before the new component. They boil down to the same: Find the element to affect and write a selector for it.