Difficulty in Understanding CSS-Styling in Mjml

Difficulty in understanding CSS-styling in MJML

Good question.

MJML and HTML are markup languages. MJML depends entirely on HTML and CSS for browser effects. That is, the MJML program translates the MJML markup into HTML and CSS. The browser gets only the HTML and CSS.

If we restrict ourselves to HTML and CSS constructs that email clients (Gmail, etc.) support, we can get good email results. That's hard. MJML helps.

In HTML, we can interact with DOM objects via CSS, sometimes using the concept of class. We can use attributes, both in and out of classes.

Similarly, in MJML we can interact with MJML components via MJML attributes and the MJML concept of mj-class. We can use MJML attributes both in and out of mj-classes.

The MJML mj-style component supports specifying CSS code that MJML includes in the HTML. That is, the code inside the mj-style tags is CSS, not either HTML or MJML. All syntax, application rules, and effects come only from CSS and HTML.

Email authors can apply MJML attributes and mj-class only to MJML components, not to HTML elements. MJML translates MJML markup to HTML, but email authors must depend on that translation process.

Consider this MJML script.

<mjml>
<mj-head>
<mj-attributes>
<mj-class name="mjclass" color="green" font-size="30px" />
</mj-attributes>
<mj-style inline="inline">
.blue-text div {
color: blue !important;
}
</mj-style>
<mj-style>
.red-text div {
color: red !important;
text-decoration: underline !important;
}
</mj-style>
</mj-head>
<mj-body>
<mj-section>
<mj-column>
<mj-text css-class="red-text" font-style="italic">
I'm red and underlined
</mj-text>
<mj-text css-class="blue-text">I'm blue because of inline</mj-text>
<mj-text mj-class="mjclass">I'm green</mj-text>
</mj-column>
</mj-section>
</mj-body>
</mjml>

This is code from MJML documentation (almost, see below). Let's look into it.

https://mjml.io/try-it-live/jecmNRR-jzO You might find this URL useful--I hope it won't go stale for at least a month. There, you'll see the above script and its browser rendering. I'll explain how to see the HTML markup. I'll use that URL below.

Mostly for others or for later readers: If you're not able to use the URL and wish to recreate the following, maybe you can copy-and-paste the above code into https://mjml.io/try-it-live. Otherwise, you'll want access to the MJML program and to MJML and HTML files. MJML introductory pages are at https://mjml.io/. MJML works as a NodeJS (NPM) module. The community offers a desktop application. The MJML team supports a VS Code plug-in. There are lots of live questions and answers at https://mjml.slack.com/ (signup: https://join.slack.com/t/mjml/shared_invite/zt-gqmwfwmr-kPBnfuuB7wof5httaTcXxg).

In the MJML, let's look at this element

<mj-text css-class="red-text" font-style="italic">
I'm red and underlined
</mj-text>

Compared to the documentation, I used three lines (rather than one) and I added the MJML attribute font-style. No other changes.

  • In the mj-style containing ".red-text" (CSS code, remember), we specify we want the text to be red and underlined (CSS and HTML rules and effects).
  • In the mj-text tag above, perhaps you'd expect the MJML syntax of font-style="italic" would italicize the text.

Indeed we see all those in the browser rendering. The text is red, underlined, and italicized.

How did that happen? MJML created HTML; let's look at the HTML.

If you're using the URL above, touch/click the words "View HTML" near the top right of the rendering window. I hope you'll see code you recognize as HTML and CSS.

I'll mention two line numbers below. They're probably tied to MJML version 4.7.1. I found them with a search for "red-text"; that should work in many other versions.

My line 75 is part of an HTML style tag MJML included. The HTML inside is identical to the code within the MJML mj-style tag that contains "red-text". Whew! That's the intent.

HTML

My line 108 is part of an HTML table, in particular a td. This element has a class of "red-text" and a child div. The div has an HTML attribute "font-style:italic" and text of "I'm red and underlined".

HTML td and div

The text in the div is affected by (1) the attribute within the div calling for italics, and (2) the attributes from class "red-text" (CSS and HTML rules) calling for red and for underlining on child divs.

That's how that text got to be red, underlined, and italicized. And that's how to use css-class. And mj-class. Thanks for reading this far.

Second question, also a good question. (Why the div in the documentation?)

Here's an introduction to a technique you might use a lot as an email author with MJML.

  1. Write the MJML you want.

  2. If you can't find MJML stylings to get the right rendering, identify the MJML tag you want to target. Add a css-class to the MJML and write an mj-style for the class you used. The objective now is to know where MJML will put the CSS class; the exact stylings can come later. Then, in the HTML, find that class and the DOM object you'd style as an HTML author (the target DOM object). (Secret: You're both those authors!)

  3. Use CSS in mj-style to style the target DOM object.

In this case, step 1 is complete with the MJML script above (you wouldn't have the mj-styles yet). This is where you'd decide to make the text "I'm red and underlined" (wait for it!), red and underlined. Email authors can do both of those with MJML, but we're learning to do them with CSS and HTML. We'll continue.

Step 1 led me to the mj-text with "I'm red and underlined"--the target mj-text.

Step 2 starts when you put the css-class in the target mj-text and write a matching mj-style. The mj-style might not have final attributes.

Step 2 is complete when you search the HTML code for the class name used in your mj-style and the string "I'm red and underlined". Something's wrong if these DOM objects aren't close to each other; they could be the same object. Their relationship governs how you'll write the mj-style CSS in step 3.

In step 2, I'd found the class in a td at HTML line 108 and the string in a child div.

Step 3 starts when you write CSS for the mj-style just as you'd write for an HTML style to select the target DOM object. Be careful to use only selectors email client programs support; otherwise, your email will give unexpected results to contacts using those programs. Also, select the CSS attributes to create your rendering.

Step 3 ends when you get the desired rendering.

In step 3, ".red-text div" selects the div; that went in the MJML script within the mj-style referring to "red-text". The needed CSS attributes went there, too.

This is beyond your question, but it's short: Check whether you feel the mj-html-attributes component makes this process easier.

That's, "Why the div?" It won't always be a div; the target DOM object might be more than one object deep.

Welcome to the MJML world. In writing MJML, keep in mind that the list of HMTL classes and the list of MJML mj-classes are separate, not interchangeable. And the same with the list of HTML attributes and the list of MJML attributes; also not interchangeable (though MJML reuses names, as they should). You can use them all, but keep them separate (as this element did).

More questions? There's help here. Again, there are lots of good answers at https://mjml.slack.com/ (signup: https://join.slack.com/t/mjml/shared_invite/zt-gqmwfwmr-kPBnfuuB7wof5httaTcXxg), too. Two friendly crowds.

How to set a fixed width for columns in mjml?

  1. If it is ambiguous whether you've used mj-column > width, I should suggest that as the first step. Perhaps you've used it.

  2. Paradoxically, I'll suggest using mj-style inline="inline". In your MJML, target the HTML element you need using the technique suggested in https://documentation.mjml.io/#mj-html-attributes and Difficulty in understanding CSS-styling in MJML

If I understand your use case right, you need to get the necessary HTML attributes inside the HTML elements. MJML will put yours there because of the inline="inline" instruction above. That's the first HTML, the file MJML creates. With luck, the email client doing the forwarding won't change that. Maybe no client will change those; test carefully.

Your use case is challenging. Meeting the challenge of creating a generally forwardable email is huge; it's tough to know all possible modifications made at any one export or import at an email client, let alone the combined effect of combinations of clients. MJML typically makes email authors more efficient in getting email into all email clients the first time; MJML doesn't try to support forwarding. Each forward requires an export from the first email client and an import into the second. See https://www.litmus.com/blog/when-forwarded-emails-break/

BTW: In addition to StackOverflow, a great source of MJML support is https://mjml.slack.com/ You probably would have gotten a more prompt response there than this one. (Sorry!)

Does anybody know how I'd create a column with more than one section inside it?

According to MJML documentation:

mj-text is an "ending tag", which means it can contain HTML code
which will be left as it is, so it can contain HTML tags with
attributes, but it cannot contain other MJML components.

Source

Which means you should be able to add HTML inside mj-text. Your resulting MJML will look something similar to:

<mjml>
<mj-body>

<!-- Side image -->
<mj-section background-color="white">
<!-- left paragraph -->
<mj-column>
<mj-text>
<table width="100%" border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td>row 1</td>
</tr>
<tr>
<td>row 2</td>
</tr>
</tbody>
</table>

</mj-text>

</mj-column>
<!-- right image -->
<mj-column>
<mj-image width="200px" src="https://designspell.files.wordpress.com/2012/01/sciolino-paris-bw.jpg" />
</mj-column>
</mj-section>

</mj-body>
</mjml>

React class styling from css stylesheet not working

Without a working example, it's hard to say, but here's a hide/show toggle example (click Run code snippet). Try copying/pasting this example into your project and seeing if it works. If it doesn't, then there's something not set up properly with your project, where stylesheets aren't being properly imported.

class App extends React.Component {  constructor(props) {     super(props);        this.state = { clicks: 0, hidden: false };        this.handleIncreaseClicks = this.handleIncreaseClicks.bind(this);    this.handleButtonDisplay = this.handleButtonDisplay.bind(this);  }      handleIncreaseClicks() {    this.setState(state => ({ clicks: state.clicks + 1 }));  }       handleButtonDisplay() {    this.setState(state => ({ hidden: !state.hidden }));  }
render() { return( <React.Fragment> <div className={`container ${this.state.hidden ? "hide-me" : ""}`}> <p className="label">Clicks:</p> <button className="clicks" onClick={this.handleIncreaseClicks} > {this.state.clicks} </button> <br /> </div> <button className="hide-show-button" onClick={this.handleButtonDisplay} > {this.state.hidden ? "Show" : "Hide"} Clicks </button> </React.Fragment> ) }}
ReactDOM.render( <App />, document.getElementById('root'));
.container {  display: flex;  justify-content: flex-start;  align-items: center;}
.label { font-weight: 700; margin-right: 10px;}
.hide-show-button { cursor: pointer; margin: 0 5px; text-align: center; font-size: 14px; width: 100px; padding: 4px; border-radius: 3px; border: 1px solid #333333; transition: all 0.2s ease-in-out;}
.hide-show-button { background-color: #f56342; color: white;}
.hide-show-button:hover { background-color: #be391c;}
.clicks { cursor: pointer; font-size: 14px; width: 100px; padding: 4px; border-radius: 3px; border: 1px solid #333333; text-align: center; transition: all 0.2s ease-in-out;}
.clicks:hover { background-color: #c1c1c1;}
.clicks:focus, .hide-show-button:focus { outline: 0;}
.hide-me { display: none }
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

<div id='root'></div>

Text shadow in mjml for email html

mj-text takes plain HTML so you can add a text-shadow like you would in plain HTML (see live here).

<mjml>
<mj-body>
<mj-section>
<mj-column>
<mj-text font-size="20px" font-family="helvetica">
<p style="text-shadow: 1px 1px #ff0000;">Hello world</p>
</mj-text>
</mj-column>
</mj-section>
</mj-body>
</mjml>

Like highlighted in another answer, note that text-shadow is not well supported across email clients.



Related Topics



Leave a reply



Submit