Mjml: Allow for global mj tags definition

Created on 22 Feb 2016  路  10Comments  路  Source: mjmlio/mjml

Following feature request like #49 or #14, it's clear that MJML needs to provide a way to define mj tags attributes once, for all. This issue represents an implementation we think will cover this case nicely. The idea here is to discuss openly here and to settle on a final implementation by the end of the week.

To achieve that, we plan to add a new tag mj-attribute, which would contain a JSON encoded map. For instance:

<mj-attributes>
{
  "mj-text": {
    "align": "center",
    "padding-top": "10px" 
  }
}
</mj-attributes>

would set the align attribute to center and padding-top to 10px on each mj-text tags found in the document.

In the case an mj-text tags already defines one, or both properties, no replacement of the value is done. For instance, the following:

<mj-attributes>
{
  "mj-text": {
    "align": "center",
    "padding-top": "10px" 
  }
}
</mj-attributes>
<mj-text padding-top="42px">Hello World!</mj-text>

would not replace the padding-top definition on the mj-text tag.

The idea is to implement such "inlining" of attributes in a pre-processing phase, so the rest of the rendering process remains the same.

For now, we prefer to go with an implementation making this global attributes definition self-contained in the document itself, and not through an external file. Allowing to separate this could be added in a future release, if found useful.

Continuing from here, we found also useful to allow for global attribute definition on a given range of tags, similar to CSS classes. For that purpose, we would introduce a standard mj-class (to not collision with the standard class attributes, and className used in React). Mixing mj-class and the mj-attributes map, one can define attributes definition this way:

<mj-attributes>
{
  "foobar": {
    "align": "center"
  }
}
</mj-attributes>
<mj-text mj-class="foobar">Hello World!</mj-text>
<mj-text>Hello Second World!</mj-text>

Would inline the align attribute to center only on the first mj-text tags "Hello World!" which defines its mj-class to foobar, but not on the second mj-text which defines no mj-class.

In addition of everything above, a new mjml root tag is defined and described in details in #78.

Most helpful comment

Hello,

Just an update for everyone looking for this issue.

We started a new implementation of mj-attributes instead of using JSON we want to keep the xml approach. Here's what we propose:

<mjml>
  <mj-head>
    <mj-attributes>
      <mj-text padding="0" font-size="12px" font-family="Verdana" />
      <mj-section padding="0" background-color="green" />
      <mj-class name="foobar" padding="10px 30px"  />
    </mj-attributes>
  </mj-head>
  <mj-body>
    <mj-container>
      <mj-text mj-class="foobar">Hello World </mj-text>
      <mj-text>Hello! </mj-text>
     </mj-container>
  </mj-body>
</mjml>

What do you guys think about it ?

All 10 comments

I really like what you've described here. My only question is why you've decided to go your own route rather than use Radium? This is purely out of curiosity at this point.

I predict you will encounter some initial limitations, such as inability to add :hover, :focus or :active although I'm not too sure how useful those are for emails. Also how will we be able to create or modify media queries this way?

Hi @TheSisb, please find my answers below.

I really like what you've described here. My only question is why you've decided to go your own route rather than use Radium? This is purely out of curiosity at this point.

I'm not expert enough here, but what I understood when talking with developers who considered/used it before, it might be too much for what we do in MJML, where React is mostly here to support the component-driven approach (no management of component state afterwards, etc).
Also, as explained in the issue, the goal here is to embed such global definitions in the markup itself, not requiring one to have to manipulate style from the JS side. Makes sense?

I predict you will encounter some initial limitations, such as inability to add :hover, :focus or :active although I'm not too sure how useful those are for emails.

Correct, but the support of this state is not homogeneous anyway from our tests. Also, it could be handled through regular tags attributes.

Also how will we be able to create or modify media queries this way?

I'm not sure to understand, could you please elaborate on that?

Thanks for sharing your thoughts, definitely helps!

This looks like a good solution. I would like to see the syntax look more like CSS, than the JSON you have here (Although I understand that would be harder from a parsing point of view).

Also it seems like there could be class name conflicts if specifying mj-classes is the same syntax as specifying styling for components. In CSS the . is used to specify classes, that might work better here.

Hi @frenchie4111, thanks for your feedback. JSON format is indeed easier to parse for us.

Also it seems like there could be class name conflicts if specifying mj-classes is the same syntax as specifying styling for components. In CSS the . is used to specify classes, that might work better here.

About that, I'm not sure to understand, could you provide us with a sample please?

Sure

Names would collide:

<mj-attributes>
{
  "mj-text": {
    "align": "center"
  }
}
</mj-attributes>
<mj-text mj-class="mj-text">Hello World!</mj-text>

With the . prepending, you would know that it is defining a class.

<mj-attributes>
{
   "mj-text": {
       "align": "center"
   }
   ".mj-text": {
       "align": "right"
   }
}
</mj-attributes>
<mj-column mj-class="mj-text">
    <mj-text>
        Hello World!
    </mj-text>
</mj-column>

This is a bit of a contrived examples as creating a mj-class named the same thing as an mj-component would be silly, but I can see it being a problem, especially as more and more components get added to the ecosystem.

Also it might be better <mj-style> (rather than <mj-attributes>) to match the standard html <style> tag.

Hello,

Just an update for everyone looking for this issue.

We started a new implementation of mj-attributes instead of using JSON we want to keep the xml approach. Here's what we propose:

<mjml>
  <mj-head>
    <mj-attributes>
      <mj-text padding="0" font-size="12px" font-family="Verdana" />
      <mj-section padding="0" background-color="green" />
      <mj-class name="foobar" padding="10px 30px"  />
    </mj-attributes>
  </mj-head>
  <mj-body>
    <mj-container>
      <mj-text mj-class="foobar">Hello World </mj-text>
      <mj-text>Hello! </mj-text>
     </mj-container>
  </mj-body>
</mjml>

What do you guys think about it ?

Now released in 2.1 ! 馃憤

What about using tags like h1 and so in mj-attributes?

Most likely #81 for that

Was this page helpful?
0 / 5 - 0 ratings

Related issues

csmcanarney picture csmcanarney  路  3Comments

lucasnantonio picture lucasnantonio  路  4Comments

fmauNeko picture fmauNeko  路  3Comments

sinsunsan picture sinsunsan  路  4Comments

karanmartian picture karanmartian  路  3Comments