Variable widths and responsive related issues with custom module for emails

Hello! I’d like to start by saying that all the questions I’m about to ask are for custom module creation to be used on the most recent Drag-and-Drop Builder (with the rendered UI, not the one that uses blocks) for emails only.

I’m trying to create a module that allows users to choose to add an icon next to a bunch of text (although I already had this same problem on other situations). The problem being that since I’m only allowed to use the D&D Builder, I can’t add any custom CSS since I don’t get to customize the <head> section, and I’m also constrained by normal email limitations.

Now my image (icon) is always the same size (64px), so adding to that a 20px gap, I end up with a <table> element that is 84px wide. Now, the <table> that contains the text, that needs to be next to it can be any size, because when I import it into my email I want the users to be able to decided if they want to had some padding (using the “Fill” option all modules have in the builder) or not. My issue is that I need to set a width, or else it can’t be side-by-side with the icon’s <table>, but since it is variable, I can’t just put a random number and be done with it.

I’ve looked at Hubl documentation, but it’s always a bit dfficult to find answers when you are working with just emails and the D&D Builder, since usually people ask things for the other builder or landing pages.

Ideally, I would like to know if there’s a filter/variable/function that allows me to get the width of another element (maybe by using a custom ID on), that way I can check the size of the global container <table> that my icon and text are on (that I have on my custom module as well), and substract the size of the icon <table> (84px) to end up up with an absolute number that allows the other <table> to stand next to it.

And if so, of course this bears the question of the responsive side of it. If I can use an absolute number on the text’s <table> by using a variable, it means that on smaller screens this element is going to be too wide. Unfortunately for me, Hubspot has a mobile-first approach even for emails, so all the queries are made for desktop, on mobile everything is always 100% unless the element has a width attribute in which case it just uses that width and goes with it. And since I can’t use custom CSS…

Maybe what I’m asking here is too complex to be handled on the D&D Builder, but that’s the only option I have. So if anyone would know how to handle this problem, I would be very grateful!

Thanks.

Hi @brunoalves_ebp,

When creating a cusom module, you have the option to create a HTML, CSS and JS part, for email you are indeed only able to add HTML.

Check out the knowledge base Create and edit modules for more info.

If you want to set custom css for a specific module instead of a global css for the module, you can write your css in your HTML part, since it’s supports Hubl. If you wrap your styling inside the require_css it will place your css into your head. Check out the Hubl function require_css.

For example:

{% require_css %}
<style>
.markup{
 /* Custom styling */
}
</style>
{% end_require_css %}

To make a styling unique for that spesific module that is added to a page, you can use the variable {{ name }}. This will generate a unique block id that will be different on every added module on your page.

Your code then will look like this:

HTML

<div class="markup markup-{{ name }}">
</div>

CSS

{% require_css %}
<style>
.markup-{{ name }}{
 /* Custom styling */
}
</style>
{% end_require_css %}

It’s also good to check the documentation for Email template markup and look at the section ‘hs-inline-css and data-hse-inline-css’. Perhaps this will solve your problem.

Besides the possibilities inside HubSpot, you should also be aware that not all email clients supports all styling functions. Mailchimp has a good article about that called ‘Limitation of HTML Email’

For your question to get data from an object or image, it’s best to have an image object back from your field. Then you can check filters like |pprint of |tojson what’s inside to use code. Also check the Filters inside the documentation.

{# Helps printing variable, useful for debugging #}
{{ module.image|pprint }}

{# Writes an object as a json string #}
{{ module.image|tojson }}

Hope this helped you.

Hi! Thanks a lot for the very useful explanations.

It’s awesome that we can include custom CSS directly into the <head> section using require_css, somehow I didn’t catch that when I went through the documentation multiple times now. Or maybe I thought it was only going to work on landing pages and such. It’s definetly going to come in handy for my custom modules!

About the other part of your answers, about getting data from objects, I’m not quite sure it is what I’m looking for. From what I’m getting from the documentation and your explanations, those filters can only get data from objects added on custom modules, but what I am actually looking for is getting data from an element that is present in my email DOM. I would like to be able to get the width or height from elements that I’ve put on my custom module once they are rendered. This is because when your insert a module in an email builder, you can customize a “fill” option that adds or removes padding, making the element be able to touch or not touch the borders of the email container, and thus changing it’s total width/height. That’s why I need to extract that data so I can do something with it afterwards.

I don’t know if I have misundertood something in your answer though, so feel free to correct me if there was something that I didn’t catch or if I don’t explain my question correctly.

Thanks! :slightly_smiling_face:

Hi @brunoalves_ebp,

How did you added the image? It it by the rich text or hardcoded inside your module or template? Then you can’t get info from another object.

You can only get the width and height of an image if you created a custom module. I also recommend setting the option for ‘Avalible size options’ to Show all or width and height. Did you follow the manual for ‘Creating and edit modules’?

If you have done it this way, you can get different values from the object.

Here are some value samples:

Src: {{ module.image.src }}
Width: {{ module.image.max_width }}
Height: {{ module.image.max_height }}
Alt: {{ module.image.alt }}
Size_type: {{ module.image.size_type }}
Loading: {{ module.image.loading }}

Perhaps css box-sizing:border-box; can help if you work with padding. But i’m not sure what the support is within email clients.

Hi @Indra! Thanks again for your answer.

How did you added the image?


That’s the thing, I am not trying to get the image’s width/size. My image is always going to be 64px wide, that much I am certain. It’s more something along the lines of this:

<!-- This is the global container, which is 100% of it's parent, so it would be 600px wide if I didn't specify any padding in the builder, but it can be less wide if I use the "fill" option in the builder to add padding. -->
<table align="left" width="100%">
<tr>
<td>
 <!-- This is a column with my image, which is always 64px wide -->
 <table align="left" width="64">
 <tr>
 <td>
 <img src="{{ module.image.href }}" alt="" width="64" height="64">
 </td>
 </tr>
 </table>
</td>
</tr>

<!-- This my column with text, which the width can be whatever space I have left -->
<tr>
<td>
 <table align="left">
 <tr>
 <td>
 {{ module.text }}
 </td>
 </tr>
 </table>
</td>
</tr>
</table>

(I haven’t included ALL the things you are supposed to add when you are creating for emails, this is just a quick example)

So I need to get the global container width in pixels (because by default it takes 100% of it’s parent space, which can vary if decide to add padding to it or not directly in the builder), so I can then substract the width of my image column (64px + 20px for space), and that would give me the width I need for the text column.


It it by the rich text or hardcoded inside your module or template? Then you can’t get info from another object.


So yeah, as you can see, this is directly hardcoded inside the module. I figured you can’t really get data from an harcoded element inside a module, but I wanted to make sure I wasn’t missing anything.

What I am thinking right now, is maybe use what you suggested, and include a “dummy” image which is only going to be there so I can get the pixel width of my main container. Let’s say I make a 600px wide image with only 1px height, I could add that image using modules inside my main container, and get it’s data through the filters you showed me. However, images are always a bit tricky to use inside emails, so I’ll have to think about it.

---

Changing the subject and coming back to the require_css function, I’m having trouble implementing it in my module. This is what I have done:

{% require_css %}
<!--[if !mso]><!-->
<style>
 b, strong { font-weight: bold!important; }

 i, em { font-style: italic!important; }

 a strong, a b { font-weight: 400!important; }

 a, a span { color: #0f4486; }

 sup { line-height: 0; mso-line-height-rule: exactly; }

 @media only screen and (max-width: 639px){
 .hse-image-wrapper > tbody > tr > td {
 padding-left: 20px !important;
 padding-right: 20px !important;
 }
 }
</style>
<!--<![endif]-->
{% end_require_css %}

Before I added the require_css function, my <style> tags did work correctly, just not in some email clients, like Gmail, since they are automatically removed when they are not inside the <head>. But now, after adding require_css, they just don’t work at all, they are not even there (I’ve inspected the DOM).

Maybe it has something to do with the builder not rendering custom added css to the <head> directly? I’ve tried previewing it, and also testing it directly in some email clients (all the default ones at least), and in either case, the CSS just isn’t there. I’ve also tried removing the [if_mso] commentary condition for Outlook, but that did nothing at all.

Do you have any ideas?

Thanks again.

Hello.

Just wanted to let you know that I am still looking for a way to solve this.

More specifically, if anyone could help me figure out why the require_css function doesn’t seem to be working as intended, it would already be a big help.

Thank you.