strapi-column-control
v1.0.4
Published
Strapi Column Control — column layout plugin for Strapi 5 Dynamic Zones (container, row, columns, nested blocks). Use any CSS library, framework, or custom grid.
Maintainers
Readme
Strapi Column Control
Column layouts for Strapi 5 Dynamic Zones — container → row → columns — without replacing your existing components. Map column_class on the frontend with any CSS library, framework, or custom grid.
Requires Strapi 5 (@strapi/strapi ^5.43) and Node.js 20–26.
npm install strapi-column-controlWhat it does
Editors add a Column control block to a Dynamic Zone. Each column has a nested blocks zone where they stack the same components you already use (headlines, buttons, images, custom types).
Article dynamic_zone
└── Column control layout (container, row, columns)
├── Column 1 (span 6)
│ └── blocks[] your components, in order
└── Column 2 (span 6)
└── blocks[] same allow-list as the parent zonecolumn_classis a numeric span (for example6). Your frontend maps it to Bootstrap, Tailwind, CSS Grid, or any custom classes.- Spans in one row must sum to ≤
gridColumns(default12). blocksrender in array order.
Install
From your Strapi 5 project root:
npm install strapi-column-controlEnable the plugin in config/plugins.ts:
export default {
'strapi-column-control': {
enabled: true,
config: {
gridColumns: 12, // max sum of column_class per row
},
},
};Restart Strapi. postinstall patches Content-Type Builder so you can edit Dynamic Zones that include this plugin.
Config
| Key | Default | Purpose |
| --- | --- | --- |
| gridColumns | 12 | Maximum sum of column_class in one Column control block |
| columnBlocks | auto | Optional extra UIDs for column blocks. Prefer adding types on the parent Dynamic Zone instead |
Allowed content in columns
Add Column control and your block types to the parent Dynamic Zone (dynamic_zone, sections, and so on):
"components": [
"plugin::strapi-column-control.layout.column-control",
"atoms.button",
"atoms.headline-text"
]Restart Strapi. The plugin copies those UIDs into each column’s blocks zone. Editors add instances in Content Manager.
Content-Type Builder
- Create components as usual.
- Open the content type → edit the Dynamic Zone → Add components → select the new types → Finish.
- Click Save in the CTB top bar (not only modal Finish) and wait for Strapi to restart.
Do not edit the plugin Column component’s blocks list in CTB. That allow-list is derived from the host Dynamic Zone. Emptying it fails validation; the UI blocks editing plugin layout zones when possible.
Component UIDs
| UID | Role |
| --- | --- |
| plugin::strapi-column-control.layout.column-control | Layout block on the host Dynamic Zone |
| plugin::strapi-column-control.layout.column | One column (span + blocks) |
Fields
| Field | Description |
| --- | --- |
| configuration | Container width, padding, gutter, reverse on mobile |
| columns | Repeatable columns |
| columns.column_class | Span units; row total ≤ gridColumns |
| columns.blocks | Nested Dynamic Zone (parent DZ types + optional columnBlocks) |
| columns.admin_label | Private Content Manager title (auto) |
Example: 5 + 5 + 2 = 12 when gridColumns is 12. The REST JSON shape is stable across upgrades.
REST populate=*
Document middleware deepens shallow Dynamic Zone populate so nested columns → blocks are returned.
Mapper service
const mapper = strapi.plugin('strapi-column-control').service('mapper');
const { gridColumns } = mapper.getGridConfig();
const { valid, violations, message } = mapper.validateColumnSpans(entry.dynamic_zone);
const mapped = mapper.mapColumnControl(section); // host maps column_class to CSS| Route | Auth | Returns |
| --- | --- | --- |
| POST /api/strapi-column-control/map | public | { configuration, mapped, classes, html } |
| GET /admin/strapi-column-control/grid-config | admin | { gridColumns } |
Example API JSON
Two columns. Each blocks array can hold several components:
{
"__component": "plugin::strapi-column-control.layout.column-control",
"configuration": {
"container_width": "default",
"container_padding": "default",
"gutter": "default",
"reverse_on_mobile": false
},
"columns": [
{
"column_class": 6,
"blocks": [
{
"__component": "atoms.headline-text",
"title": "Welcome",
"subtitle": "Blocks in this column stack top to bottom"
},
{
"__component": "atoms.button",
"button_text": "Get started",
"url": "/signup"
}
]
},
{
"column_class": 6,
"blocks": [
{
"__component": "atoms.headline-text",
"title": "Features",
"subtitle": "Any type allowed on the parent Dynamic Zone"
},
{
"__component": "atoms.button",
"button_text": "Learn more",
"url": "/docs"
}
]
}
]
}Upgrade
Bump the package and restart Strapi. No content migration or host-app code changes.
npm install strapi-column-control@latestRelease notes: CHANGELOG.md.
For AI agents
Machine-readable summary: llms.txt (included in the npm package).
