CMS Development

DChimenti20
Participant

srcsets with hubl

SOLVE

I am running into trouble getting the srcset function to operate in a custom module. the images aren't resizing as anticipated. I have them set to responsive and lazy loading in the settings. I have tried it with and without media queries and run into the same issue.

I have asked a couple of people and they've told me they've had a tough time with the resize_image_url function too, so I'm hoping it's something simple that someone can just show me where I have made a mistake.

Below is code and a snip of my field group so you have the relevant names for the fields. For some reason it jumps sizes at 521px but at no other barriers. Apologies, I've only been on the CMS about 8 days and I am trying to pass the best practices course practicum.

<section class="team_members">
<div class="team_member">

{% for item in module.team %}

<div class="item">
{% if item.image_field.src %}
{% set loadingAttr = item.image_field.loading != "disabled" ? 'loading="{{ item.image_field.loading }}"' : '' %}
<img srcset="{{ resize_image_url(item.image_field.src, 150) }} 150w,
{{ resize_image_url(item.image_field.src, 200) }} 200w,
{{ resize_image_url(item.image_field.src, 250) }} 250w,
{{ resize_image_url(item.image_field.src, 299) }} 299w"
sizes="(max-width: 374px) 150px,
(max-width: 767px) 200px,
(max-width: 1032px) 250px,
299px"
src="{{ item.image_field.src }}"
alt="{{ item.image_field.alt }}"
width="{{ item.image_field.width }}"
height="{{ item.image_field.height }}"
{{ loadingAttr }}>
{% endif %}
<div class="member_name">

{% inline_text field="text_field" value="{{ item.text_field }}" %}
</div>
<div class="member_position">

{% inline_rich_text field="richtext_field" value="{{ item.richtext_field }}" %}
</div>
</div>
{% endfor %}
</div>
</section>

 

 

.team_member{
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: space-evenly;
max-width: 100%;
}
.item{
flex: 0 0 25%;
text-align: center;
align-items: center;
justify-content: center;
color: #222222;
font-family: {{ module.style.font_field }};
flex-direction: column;
}
@media (max-width: 1032px) {
.item img{
max-width: 250px;
height: auto;
}
.item {
flex: 0 0 25%;
}
@media (max-width: 768px) {
.item img{
max-width: 200px;
height: auto;
}
.item {
flex: 0 0 33%;
}
@media (max-width: 374px) {
.item img{
max-width: 150px;
height: auto;
}
.item {
flex: 0 0 100%;
}
}

DChimenti20_0-1741635770517.png

 



 

1 Accepted solution
Anton
Solution
Thought Leader | Partner
Thought Leader | Partner

srcsets with hubl

SOLVE

Hey @DChimenti20

thanks for providing the code. As we've chatted in the slack channel, you've solved this yourself 🎉 

But a few optimization ideas:

Add some variables on top of the module to add the ability to change it easier without digging through the whole module code (Very benefitial for big&complex modules) and also wrap the css in require_css or require_head statements. Doing so will push the style-tag to the <head>-tag of the page and optimize the rendering. 

 

Here's how this could look:

{% set breakpoints = {
 "sm": "374",
 "md": "768",
 "lg": "1024"
} %}
{% set image_sizes = {
 "sm": "150",
 "md": "200",
 "lg": "250"
} %}

<section class="team_members">
    <div class="team_member">

    {% for item in module.team %}
    <div class="item">
        {% if item.image_field.src %}
        {% set loadingAttr = item.image_field.loading != "disabled" ? 'loading="{{ item.image_field.loading }}"' : '' %}
        
            <img 
                srcset="{{ resize_image_url(item.image_field.src, image_sizes.sm) }} {{ image_sizes.sm }}w,{{ resize_image_url(item.image_field.src, image_sizes.md) }} {{ image_sizes.md }}w,{{ resize_image_url(item.image_field.src, image_sizes.lg) }} {{ image_sizes.lg }}w"
                sizes="(max-width: {{ breakpoints.sm }}px) {{ image_sizes.sm }}px,(max-width: {{ breakpoints.md }}px) {{ image_sizes.md }}px,(max-width: {{ breakpoints.lg }}px) {{ image_sizes.lg }}px,{{ image_sizes.lg }}px" src="{{ item.image_field.src }}"
                alt="{{ item.image_field.alt }}"
                width="{{ item.image_field.width }}"
                height="{{ item.image_field.height }}"
                {{ loadingAttr }}
            >
        {% endif %}
        <div class="member_name">
            {{ item.text_field }}
        </div>
        <div class="member_position">
            {{ item.richtext_field }}
        </div>
    </div>
    {% endfor %}
    </div>
</section>

 

{% require_css %}
<style>
.team_member{
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    justify-content: space-evenly;
    max-width: 100%;
}

.item{
    flex: 0 0 25%;
    text-align: center;
    align-items: center;
    justify-content: center;
    color: #222222;
    font-family: {{ module.style.font_field }};
    flex-direction: column;
}

@media (max-width: {{breakpoints.lg}}px) {
    .item img{
        max-width: {{image_sizes.lg}}px;
        height: auto;
    }
    .item {
        flex: 0 0 25%;
    }
}

@media (max-width: {{breakpoints.md}}px) {
    .item img{
        max-width: {{image_sizes.md}}px;
        height: auto;
    }
    .item {
        flex: 0 0 33%;
    }
}
@media (max-width: {{breakpoints.sm}}px) {
    .item img{
        max-width: {{image_sizes.sm}}px;
        height: auto;
    }
    .item {
        flex: 0 0 100%;
    }
}
</style>
{% end_require_css %}

 

 

best, 

Anton

Anton Bujanowski Signature

View solution in original post

9 Replies 9
GRajput
Recognized Expert | Gold Partner
Recognized Expert | Gold Partner

srcsets with hubl

SOLVE

Hi @DChimenti20 

 

Your srcset is working, but the CSS max-width and flex-basis settings in your media queries are conflicting with the srcset behavior. The resize_image_url function is behaving unexpectedly due to fixed flex-basis and image max-width settings.
This is forcing the image to a maximum of 250px, even when the srcset is trying to load a smaller or larger image.
So the browser only sees the max-width and doesn’t respect the srcset breakpoints properly.
The width and height attributes in your <img> tag could be interfering with the srcset behavior.

<img
srcset="{{ resize_image_url(item.image_field.src, 150) }} 150w,
{{ resize_image_url(item.image_field.src, 200) }} 200w,
{{ resize_image_url(item.image_field.src, 250) }} 250w,
{{ resize_image_url(item.image_field.src, 299) }} 299w"
sizes="(max-width: 374px) 150px,
(max-width: 767px) 200px,
(max-width: 1032px) 250px,
299px"
src="{{ item.image_field.src }}"
alt="{{ item.image_field.alt }}"
width="{{ item.image_field.width }}" <!--  REMOVE THIS -->
height="{{ item.image_field.height }}" <!-- REMOVE THIS -->
{{ loadingAttr }}>

 

By removing the width and height attributes from the image, you don't need to use a media query to set the size of the image to different devices.

 

I hope this will help you out. Please mark it as Solution Accepted and upvote to help another Community member.
Thanks!

 

 

 




Gaurav Rajput
Director, MarTech( Growth Natives)

Book a meeting


0 Upvotes
DChimenti20
Participant

srcsets with hubl

SOLVE

So this is not what is happening. It's at 299px because there is an inline setting in HubL to the explicit width setting of 299px. This is reflected in the inspect tool. You are correct that the resize image url is doing what it is supposed to do, but where it is being overriden is incorrect. It is defaulting to the explicit width setting in the HubL code which is required to be included by the course.

0 Upvotes
Anton
Solution
Thought Leader | Partner
Thought Leader | Partner

srcsets with hubl

SOLVE

Hey @DChimenti20

thanks for providing the code. As we've chatted in the slack channel, you've solved this yourself 🎉 

But a few optimization ideas:

Add some variables on top of the module to add the ability to change it easier without digging through the whole module code (Very benefitial for big&complex modules) and also wrap the css in require_css or require_head statements. Doing so will push the style-tag to the <head>-tag of the page and optimize the rendering. 

 

Here's how this could look:

{% set breakpoints = {
 "sm": "374",
 "md": "768",
 "lg": "1024"
} %}
{% set image_sizes = {
 "sm": "150",
 "md": "200",
 "lg": "250"
} %}

<section class="team_members">
    <div class="team_member">

    {% for item in module.team %}
    <div class="item">
        {% if item.image_field.src %}
        {% set loadingAttr = item.image_field.loading != "disabled" ? 'loading="{{ item.image_field.loading }}"' : '' %}
        
            <img 
                srcset="{{ resize_image_url(item.image_field.src, image_sizes.sm) }} {{ image_sizes.sm }}w,{{ resize_image_url(item.image_field.src, image_sizes.md) }} {{ image_sizes.md }}w,{{ resize_image_url(item.image_field.src, image_sizes.lg) }} {{ image_sizes.lg }}w"
                sizes="(max-width: {{ breakpoints.sm }}px) {{ image_sizes.sm }}px,(max-width: {{ breakpoints.md }}px) {{ image_sizes.md }}px,(max-width: {{ breakpoints.lg }}px) {{ image_sizes.lg }}px,{{ image_sizes.lg }}px" src="{{ item.image_field.src }}"
                alt="{{ item.image_field.alt }}"
                width="{{ item.image_field.width }}"
                height="{{ item.image_field.height }}"
                {{ loadingAttr }}
            >
        {% endif %}
        <div class="member_name">
            {{ item.text_field }}
        </div>
        <div class="member_position">
            {{ item.richtext_field }}
        </div>
    </div>
    {% endfor %}
    </div>
</section>

 

{% require_css %}
<style>
.team_member{
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    justify-content: space-evenly;
    max-width: 100%;
}

.item{
    flex: 0 0 25%;
    text-align: center;
    align-items: center;
    justify-content: center;
    color: #222222;
    font-family: {{ module.style.font_field }};
    flex-direction: column;
}

@media (max-width: {{breakpoints.lg}}px) {
    .item img{
        max-width: {{image_sizes.lg}}px;
        height: auto;
    }
    .item {
        flex: 0 0 25%;
    }
}

@media (max-width: {{breakpoints.md}}px) {
    .item img{
        max-width: {{image_sizes.md}}px;
        height: auto;
    }
    .item {
        flex: 0 0 33%;
    }
}
@media (max-width: {{breakpoints.sm}}px) {
    .item img{
        max-width: {{image_sizes.sm}}px;
        height: auto;
    }
    .item {
        flex: 0 0 100%;
    }
}
</style>
{% end_require_css %}

 

 

best, 

Anton

Anton Bujanowski Signature
DChimenti20
Participant

srcsets with hubl

SOLVE

This is killer advice @Anton  . I appreciate you both taking the time to reply. Those 2 courses are great for being able to build out pretty much any module you would need, but there are so many nuances to structure, syntax, etc that come with experience that I really appreciate both of your help!

Jaycee_Lewis
Community Manager
Community Manager

srcsets with hubl

SOLVE

Thank you @Anton 🙌 As always, you are the best! — Jaycee


Did you know that the Community is available in other languages?
Join regional conversations by changing your language settings !
Jaycee_Lewis
Community Manager
Community Manager

srcsets with hubl

SOLVE

Hey, @DChimenti20 👋 Thanks for your question. It sounds like you're making great progress for only being 8 days into working with HubSpot. 

 

Have you tried a simplified approach to your images? Something like: 

<img src="{{ resize_image_url(item.image_field.src, 250) }}"
     alt="{{ item.image_field.alt }}"
     loading="lazy"
     width="250"
     height="auto">

It's just one optimized image size, but it will display reliability and consistently across devices.

 

A few other best practices to keep in mind:

  • Keep original images under 2MB
  • Always include alt text
  • Specify width and height when possible
  • Match CSS breakpoints with your image sizes

Have fun building! — Jaycee

 


Did you know that the Community is available in other languages?
Join regional conversations by changing your language settings !
DChimenti20
Participant

srcsets with hubl

SOLVE

Thanks @Jaycee_Lewis!

This would totally work, but in the course they want you to use the HubL code snippets for width and height attributes. Both yours an Anton's answers are great though.

I know that you are actually affiliated with HubSpot. I only have 3 days left on my trial and the performance test for lighthouse keeps going above and below 90, which it needs to be above when they test it.

Is there any way to get it grading of the practicums expedited so if it does drop below for some reason, I have time to resubmit before being locked out and losing my work (the reasons it has been dropping below and things like third-party scripts from what I have seen, so unsure if I can even do anything about that in a sandbox account)?

Anton
Thought Leader | Partner
Thought Leader | Partner

srcsets with hubl

SOLVE

Hey @DChimenti20

don't worry about getting locked out of a dev portal. 
If you've created it via  https://developers.hubspot.com/ you got a so-called app-test account in this one you've - most likely - have created a CMS sandbox in which you're doing the practicum.

If so, simply login into the app-test account and renew the trial. Trials are always for 90 days and none of your process will be lost if you somehow forget to renew it before the 90 days expire. 

Bildschirmfoto 2025-03-11 um 18.00.55.png

There are a few things that will stop working, but once you renew the trial everything will work just fine. 

 

Pro tip: If you want to move things between portals, you can do it via Design-Manager. Simply right-click on a theme/folder and select "copy to different account".

Bildschirmfoto 2025-03-11 um 21.45.42.png

 

If you like to go the CLI route - also possible. Simply authenticate both portals, fetch it from one to local and upload it to the other. 😉 

 

Have fun

Anton Bujanowski Signature
DChimenti20
Participant

srcsets with hubl

SOLVE

@Antonbro - you are always on point with the code snips, graphics and everything else to make it easy to understand. Thank you so much.

I do have a Dev Sandbox Account, but on my CRM account it keeps telling me I have 3 days left, so I assumed that meant my CMS access would go away because that was how I got it in the first place.

If I'll still have access to my Dev Sandbox either way, that's even better.

Appreciate you!