I was wondering if anyone has stumbled on a good solution for including matrix-like fields within a matrix block. I’m working on a site where each page's is constructed in one big matrix with several block types (each representing a “row" in the page) like…

  • Introduction
  • Stats
  • Quotes
  • Bios etc.

Blocks like Stats, Quotes, etc. can hold either just one, or several of these items, so right now the subfields look something like this:

  • Block Title
  • Stat 1: Number
  • Stat 1: Text
  • Stat 2: Number
  • Stat 2: Text …etc. up to Stat 6

Rather than having all these fields in view by default, it would (obviously) be best if the user were just adding Stats as rows in an inner table or Matrix. Initially I thought that using Table fields would be the fix, but in several cases I need to include fields that aren’t natively supported in in Tables (like Assets, Rich Text, etc.).

At the very least it would be nice to collapse some of the fields that are likely not going to be needed so they are out of the way (so in the example above, maybe show fields for the first 2 stats, hide field for the next 4).

Has anybody stumbled on a good solution (maybe a Plugin) for either allowing more field types within Tables, adding a Matrix to a Matrix block, or collapsing fields by default?

Also open to other suggestions … seems like a lot of sites take this “stacked rows” approach, so guessing I’m not alone here. Thanks!


6 Answers 6


Rather than trying to store multiple stats together in a single block, another option would be to make a "Stat" (singular) block type, which only holds a single stat, and just have authors create as many of those as they need, positioned together.

From your template, when looping through blocks, you can check to see if the current block is the first/last of its type, and add some extra HTML when that's the case, so that consecutive Stat blocks still appear grouped together in the rendered HTML. Something like this:

{% for block in entry.myMatrixField %}

    {# Find out if this is the first/last consecutive block of this
type #}
    {% set type = block.type.handle %}
    {% set isFirstConsecutiveBlockOfType = (loop.first or type != block.getPrev().type.handle) %}
    {% set isLastConsecutiveBlockOfType = (loop.last or type != block.getNext().type.handle) %}

    {% switch type %}

        {% case 'stat' %}

            {% if isFirstConsecutiveBlockOfType %}
                <div class="stats">
            {% endif %}

            <!-- Stat block HTML -->

            {% if isLastConsecutiveBlockOfType %}
            {% endif %}

        {% case 'quote' %}

            {% if isFirstConsecutiveBlockOfType %}
                <div class="quotes">
            {% endif %}

            <!-- Quote block HTML -->

            {% if isLastConsecutiveBlockOfType %}
            {% endif %}

    {% endswitch %}
{% endfor %}
  • I thought of something similar (just grouping them together in the CP), but instead of checking for the first/last block of one type, one could also use a special block type as a separator. This would allow you to also add title, description and other universal blocks types to each group. The special block could have a dropdown field "beginSection" to bring this info to the template.
    – carlcs
    Commented Jan 21, 2015 at 22:24
  • I have to say we have implemented a separator block type on a lot of our builds - aside from it being a clean solution for me as a dev it seems to be understood easily by clients. Commented Jan 22, 2015 at 8:09

Folks may also want to checkin the Super Table plugin that just came out. It allows you to create table fields that include almost any field type:


Keep in mind, though, that in many cases this may make your CMS/data pretty dependent on a plugin.


This question was asked prior to the release of the Neo plugin/field type. I think this would offer a better approach than the SuperTable (which was/is still awesome), just because I think it's easier to manage and template.

I posted an answer to a similar question with examples here.

  • Neo is excellent. I think this is the best option. Commented Sep 8, 2016 at 19:11

An alternate solution that might work is to create separate channels for 'stats' and 'quotes', and then use an entries field within your matrix block to add them to the 'stats' and 'quotes' blocks. Although not as accessible when creating the entry, it seems like it would potentially be a lot easier to manage all around, with no limitations on filedtypes, etc.

  • This is what I'm doing. I use a structure instead of a channel, so you have the option to manually organize things. Commented Jan 21, 2015 at 20:19
  • 1
    We thought about this, but in some cases they may need to create say ten+ entries to create a row which seems kind of burdensome. Also, I'd really love for them to be able to see all the content in one shot, rather than having to double-click each related entry to see it's subfields, etc. I can see the perks, but just don't think it's right for our case.
    – philzelnar
    Commented Jan 21, 2015 at 20:23
  • 1
    In my case it was the lesser evil. I would love to see matrix in matrix Commented Jan 21, 2015 at 20:33

Maybe this is not the best idea for your exact use case, but what about using a Structure section for your entries with two levels. Top level entries would be your "actual entries" and their child entries would be a substitute for your current matrix blocks. In the template of top level entries you then collect the content of the children in sort order, conditionally output the data based on the used entry type of the child.

Not sure if you are able to use live preview with such an approach though.

  • I don't recommend such a solution. It makes content spread in the control panel in completely unintuitive way. Commented Aug 24, 2020 at 18:16

Here's my article that described possible solutions to this problem:


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.