<p><a href="http://twig.sensiolabs.org/doc/filters/merge.html" rel="nofollow">Merge</a> operates on arrays or array-like things, and you probably handed it the string <code>"card"</code>, which is why you got that error.</p>

<p>I think what you want to do here is use the transform in the control panel to define the aspect ratio, but use the <code>img</code> macro to determine which sizes to transform to.</p>

<p>You can calculate the aspect ratio like this:</p>

<pre><code>{% set aspectRatio = asset.getHeight(options.style) / asset.getWidth(options.style) %}
</code></pre>

<p>And generate transforms like this:</p>

<pre><code>transform|merge({width: width, height: width * aspectRatio})
</code></pre>

<p>You will want to be careful with the native (untransformed) image: only use it if it has the correct aspect ratio.</p>

<p>You will want to be careful with avoiding transforming to a larger image - skip the ones where the width would be greater than the native width <em>and</em> the ones where the height would be greater than the native height.</p>

<p>Using the <code>crop</code> transform instead of the <code>stretch</code> one (that the article uses) is the right thing to do too.</p>

<p>Also, consider the <a href="https://github.com/aelvan/Imager-Craft" rel="nofollow">imager</a> plugin, which has some useful srcset supporting features (and postdates that article)</p>

CC BY-SA 3.0
2016-08-09T17:52:18.297Z
I am going to take a look at imager as I believe this does what I want to achieve and more. It looks quite useful. Thanks for your help Marion.
Terry Upton
CC BY-SA 3.0
2016-08-09T17:58:20.397Z
+1 for Imager (and declaring all transforms inline, not via the CP).
Mats Mikkel Rummelhoff
CC BY-SA 3.0
2016-08-12T16:08:46.400Z
I need to update the [useful article](https://straightupcraft.com/articles/responsive-images-with-twig-macros), but I want to take this opportunity to advise against scaling an image to be just slightly smaller than its native size - it will get scaled twice - once by the server, and then probably again by the browser, and the image degrades with no compensating drop in image size
Marion Newlevant
CC BY-SA 3.0
2016-08-09T16:47:14.487Z
2016-08-09T16:47:14.487Z
Marion Newlevant
<p>So I have setup a macro based on the excellent article here;<br>
<a href="https://straightupcraft.com/articles/responsive-images-with-twig-macros" rel="nofollow">https://straightupcraft.com/articles/responsive-images-with-twig-macros</a></p>

<pre><code>{% macro responsive(asset, options={}) %}
{% import _self as self %}

{% set options = {
    alt: '',
    class: [],
    style: 'default'
}| merge(options) %}

    {% set transform = {
        mode: 'crop',
    } %}

{% set nativeWidth = asset.getWidth(false) %}

{% set config = {
    default: {
        srcsetWidths: [300, 600, 1000,],
        sizes: [
            '(max-width: 47.5em) 100vw',
            '50vw'
        ],
        defaultWidth: 600
    },

    cards: {
        srcsetWidths:   [345, 600, 700, 905, 1000, 1200, 1400],
        sizes: [
            '(max-width: 47.5em) 100vw',
            '(max-width: 60em) 50vw',
            '33vw'
        ],
        defaultWidth: 600
    }
} %}

{% set params = config[options.style] %}
{% set srcset = [asset.getUrl(false)~' '~nativeWidth~'w'] %}

{% for width in params['srcsetWidths'] %}
    {% if width &lt; nativeWidth %}
    {% set srcset
         = srcset|merge([asset.getUrl(transform|merge({width: width}))~' '~width~'w'])
    %}
    {% endif %}
{% endfor %}

&lt;img
    {# src attr: transformed only if necessary #}
    {% if nativeWidth &lt;= params['defaultWidth'] %}
      src="{{ asset.getUrl(false) }}"
    {% else %}
      src="{{ asset.getUrl(transform|merge({width: params['defaultWidth']})) }}"
    {% endif %}

    srcset="{{ srcset|join(', ') }}"
    sizes="{{ params['sizes']|join(', ') }}"

    alt="{{options.alt}}"
    {{ self._classAttr(options.class) }}
/&gt;
{% endmacro %}
</code></pre>

<p>However, I want to be able to generate each individual responsive set based on different transform parameters. The first instance I have is created a series of card images images for a 1x3 row of feature cards. These will be a fixed ratio which I want the system to handle and not the user. These cards have the following sizes for each srcset width;</p>

<ul>
<li>1400 x 875</li>
<li>1200 x 750</li>
<li>1000 x 625</li>
<li>905 x 566</li>
<li>700 x 438</li>
<li>600 x 375</li>
<li>345 x 216 </li>
</ul>

<p>I have created an image transform in the Control Panel called Card Image that has been set to crop and the width/height set to the largest size (1400x875). I wondered if I could use this handle in the macro, but I run into errors;</p>

<blockquote>
  <p>The merge filter only works with arrays or "Traversable", got "string" as first argument.</p>
</blockquote>

<p>As I will have different use cases and create different 'responsive images' throughout the site, I want the flexibility of setting up different transforms, I thought it was perhaps sensible to keep these all in the control panel under the Image Transforms section, as these are easily referable and editable. Then pass in the required handle into the Macro.</p>

<p>Does anyone have a better approach or solution, and any ideas how I can overcome the error mentioned? </p>

<p>Thanks.</p>

<error-message><macro><responsive-images>
Responsive Images Srcset and Sizes based on Image Transform
# Responsive Images Srcset and Sizes based on Image Transform

(Asked by: username_0 on 2016-08-08)

So I have setup a macro based on the excellent article here;
https://straightupcraft.com/articles/responsive-images-with-twig-macros
{% macro responsive(asset, options={}) %}
{% import _self as self %}

{% set options = {
    alt: '',
    class: [],
    style: 'default'
}| merge(options) %}

    {% set transform = {
        mode: 'crop',
    } %}

{% set nativeWidth = asset.getWidth(false) %}

{% set config = {
    default: {
        srcsetWidths: [300, 600, 1000,],
        sizes: [
            '(max-width: 47.5em) 100vw',
            '50vw'
        ],
        defaultWidth: 600
    },

    cards: {
        srcsetWidths:   [345, 600, 700, 905, 1000, 1200, 1400],
        sizes: [
            '(max-width: 47.5em) 100vw',
            '(max-width: 60em) 50vw',
            '33vw'
        ],
        defaultWidth: 600
    }
} %}

{% set params = config[options.style] %}
{% set srcset = [asset.getUrl(false)~' '~nativeWidth~'w'] %}

{% for width in params['srcsetWidths'] %}
    {% if width < nativeWidth %}
    {% set srcset
         = srcset|merge([asset.getUrl(transform|merge({width: width}))~' '~width~'w'])
    %}
    {% endif %}
{% endfor %}


{% endmacro %}

However, I want to be able to generate each individual responsive set based on different transform parameters. The first instance I have is created a series of card images images for a 1x3 row of feature cards. These will be a fixed ratio which I want the system to handle and not the user. These cards have the following sizes for each srcset width;

1400 x 875
1200 x 750
1000 x 625
905 x 566
700 x 438
600 x 375
345 x 216 

I have created an image transform in the Control Panel called Card Image that has been set to crop and the width/height set to the largest size (1400x875). I wondered if I could use this handle in the macro, but I run into errors;

The merge filter only works with arrays or "Traversable", got "string" as first argument.

As I will have different use cases and create different 'responsive images' throughout the site, I want the flexibility of setting up different transforms, I thought it was perhaps sensible to keep these all in the control panel under the Image Transforms section, as these are easily referable and editable. Then pass in the required handle into the Macro.
Does anyone have a better approach or solution, and any ideas how I can overcome the error mentioned? 
Thanks.

**Tags:** error-message, macro, responsive-images


---

## 1 answers

### Answer by username_1 on 2016-08-09. Score: 4 | Accepted answer

Merge operates on arrays or array-like things, and you probably handed it the string "card", which is why you got that error.
I think what you want to do here is use the transform in the control panel to define the aspect ratio, but use the img macro to determine which sizes to transform to.
You can calculate the aspect ratio like this:
{% set aspectRatio = asset.getHeight(options.style) / asset.getWidth(options.style) %}

And generate transforms like this:
transform|merge({width: width, height: width * aspectRatio})

You will want to be careful with the native (untransformed) image: only use it if it has the correct aspect ratio.
You will want to be careful with avoiding transforming to a larger image - skip the ones where the width would be greater than the native width and the ones where the height would be greater than the native height.
Using the crop transform instead of the stretch one (that the article uses) is the right thing to do too.
Also, consider the imager plugin, which has some useful srcset supporting features (and postdates that article)

> **Comments:**
> **username_0**: I am going to take a look at imager as I believe this does what I want to achieve and more. It looks quite useful. Thanks for your help Marion.  
> **username_2**: +1 for Imager (and declaring all transforms inline, not via the CP).  
> **username_1**: I need to update the [useful article](https://straightupcraft.com/articles/responsive-images-with-twig-macros), but I want to take this opportunity to advise against scaling an image to be just slightly smaller than its native size - it will get scaled twice - once by the server, and then probably again by the browser, and the image degrades with no compensating drop in image size  

---

