Advanced Custom Fields: Multi Column Field GitLab
Adds a Multi Column layout field to ACF. Arrange fields side by side on a 12-column or percentage grid that adapts to the width of its container.
by Viktor Kovalenko · gitlab.com/v_kovalenko/acf-multi-column-field-wordpress-plugin
Install
No release zip yet. The repository archive installs, but the folder name will carry the branch suffix and updates will not flow:
wp plugin install https://gitlab.com/v_kovalenko/acf-multi-column-field-wordpress-plugin/-/archive/master/acf-multi-column-field-wordpress-plugin-master.zipA standalone Multi Column layout field for Advanced Custom Fields (ACF and ACF PRO). Place fields side by side on a 12-column or percentage grid that adapts to the width of its container.
Based on how the Column field of ACF Extended works, without needing ACF Extended. It can run next to ACF Extended without conflicts.
| Version | 1.0.0 |
| Requires WordPress | 6.5+ |
| Requires PHP | 8.1+ |
| Requires | ACF or ACF PRO 6.0+ (installed and active) |
| Tested up to | WordPress 7.1, ACF PRO 6.8.9 |
| License | GPLv2 or later |
Contents
- Features
- Installation
- Usage
- Settings
- Responsive behaviour
- Where it works
- Comparison with ACF Extended Column
- Moving from ACF Extended Column
- Developer reference
- Known limitations
- Security
- File structure
- Changelog
Features
Grid
- Two grid modes per column: 12 columns (
1/12to12/12) or a percentage width (1–100%). - 12-column choices show the resulting width:
4/12 · 33.33%. - Widths are passed as a CSS custom property, so any value works without extra CSS.
- Endpoint column closes the current columns; the fields after it are full width again.
- A column holds every field after it, up to the next column, an endpoint or a tab.
Responsive
- Columns react to the width of their fields container, not the viewport.
- Container narrower than 640px → columns take 50%. Narrower than 420px → 100%.
- Left-aligned labels move above their inputs inside narrow columns.
- Wide content (tables, code, long URLs) shrinks inside its column instead of breaking the row.
Editor experience (field group screen)
- Auto-generated field label:
Column 6/12,Column 40%,Column Endpoint, updated live while you edit. - Live width preview bar, with 12-column tracks in 12-column mode.
- Settings that don't apply to a column are hidden: label, name, instructions, required, wrapper attributes and the empty Presentation tab.
- ACF 6 look: tinted row like the core Tab and Accordion fields, endpoint marker line, field type icon, description and preview image in Browse Fields.
Compatibility
- Standalone. Needs only ACF or ACF PRO 6.0+.
- Runs next to ACF Extended: different field type, CSS classes and assets.
- Shows an admin notice when ACF is missing, inactive or older than 6.0 (only to users who can activate plugins). The field type is not registered in that case, so nothing breaks.
Installation
- Copy the
acf-multi-column-fieldfolder towp-content/plugins/, or clone the repository there. - Install and activate ACF or ACF PRO 6.0+.
- Activate Advanced Custom Fields: Multi Column Field under Plugins.
A
Requires Pluginsheader is not used: ACF and ACF PRO have different plugin slugs, and the header can't express "one of them". The plugin checks for ACF at runtime and shows a notice instead.
Usage
Add a Multi Column field (category Layout) before the fields it should hold.
Field list in the field group Result on the edit screen
─────────────────────────────── ─────────────────────────────────
Headline (text) Headline full width
Column 8/12 (multi column) ┐
Title (text) │ ┌──────────────────┬───────────┐
Subtitle (text) │ │ Title │ Date │
Column 4/12 (multi column) │ │ Subtitle │ │
Date (date picker) ┘ └──────────────────┴───────────┘
Column Endpoint (multi column)
Content (wysiwyg) Content full width
Rules:
- A column collects the fields that follow it until the next Multi Column field (column or endpoint) or the next Tab field.
- Column widths in one row don't have to add up to 100%. The row wraps when the next column doesn't fit.
- Without an endpoint, the last column keeps collecting fields until the end of the group (or the next tab).
- Conditional logic on a column shows or hides the column with all the fields inside it.
- Conditional logic between fields in different columns, and between fields inside and outside columns, works as usual.
Settings
| Setting | Key | Values | Default | Shown when |
|---|---|---|---|---|
| Grid | grid |
12, percent |
12 |
Endpoint off |
| Columns | columns |
1/12 … 12/12 |
6/12 |
Grid = 12 columns |
| Width | percentage |
integer 1–100 (slider + number) |
50 |
Grid = Percentage |
| Endpoint | endpoint |
0, 1 |
0 |
always |
The field stores no value. Label, name, instructions and required are set automatically.
Responsive behaviour
Sizes follow the width of the fields container (the meta box, repeater row, group, flexible layout…), measured with ResizeObserver.
| Container width | 12-column / percentage columns | Full-width columns (12/12, 100%) |
Left labels inside columns |
|---|---|---|---|
| 640px and wider | configured width | 100% | beside the input |
| 420px – 639px | 50% | 100% | above the input |
| below 420px | 100% | 100% | above the input |
Why container width: the same field group can appear in a wide main column, a narrow side meta box, the block editor sidebar or a nested repeater. Viewport media queries keep columns squeezed in those narrow places on a wide screen; container width doesn't.
Where it works
| Context | Behaviour |
|---|---|
| Post / page / CPT edit screens (classic and block editor meta boxes) | ✅ Grid |
| Side meta boxes | ✅ Grid, stacks by container width |
| Options pages | ✅ Grid |
| Label placement Top and Left | ✅ Grid (left labels stack in narrow columns) |
| Seamless meta box style | ✅ Grid |
| Group field (Block / Row layout) | ✅ Grid |
| Repeater (Block / Row layout), including added rows | ✅ Grid |
| Repeater collapsed rows | ✅ The column holding the "Collapsed" field is shown full width |
| Flexible Content layouts | ✅ Grid |
| Tabs | ✅ A tab ends the current column automatically |
| Repeater / Group Table layout | ➖ Columns ignored, fields render normally |
| Edit Term, User profile (table forms) | ➖ Columns ignored, fields render normally |
| Add New Term form | ➖ Column field not rendered (same as ACF Extended) |
Comparison with ACF Extended Column
Compared against the Column field (acfe_column) in ACF Extended 0.9.2.7.
| ACF Extended — Column | Multi Column Field | |
|---|---|---|
| Dependency | Part of the ACF Extended suite; that version loads only with ACF PRO 5.8+ | Standalone plugin; ACF or ACF PRO 6.0+ |
| Field type key | acfe_column |
multi_column |
| Grid modes | 12 columns | 12 columns + percentage 1–100% |
| Width CSS | One attribute selector per value ([data-columns="6/12"]) |
One CSS custom property (--acf-mcf-width), any value |
| Responsive basis | Viewport media queries: ≤1024px → 50%, ≤640px → 100% | Container width: <640px → 50%, <420px → 100% |
| Narrow containers on wide screens (side meta box, block sidebar, nested repeater) | Keep configured widths | Stack to 50% / 100% |
| Left labels in narrow columns | Stay beside the input | Move above the input |
| Where a column ends | Next column | Next column or tab |
| Wide content inside a column | Can push the row wider (flex min-width: auto) |
Shrinks inside the column (min-width: 0) |
| Table layouts (repeater table, term/user forms) | Cells removed by JS after render; skipped on user/term screens unless ACFE Enhanced UI is on | Hidden by CSS before render (no layout jump); fields render normally |
| Collapsed repeater row, "Collapsed" field inside a column | Not handled (only a column that is itself the target) | Column with the target shown full width, other fields hidden |
| Label in field group list | (Column 6/12) |
Column 6/12, Column 40%, Column Endpoint — live |
| Width preview in settings | — | Live preview bar with grid tracks |
| Field type browser (ACF 6) | Name only | Description, icon, preview image |
| Field group list styling | Separator bar above column rows | ACF 6 layout row tint + endpoint line, like Tab / Accordion |
| Irrelevant settings | Hidden with CSS | Hidden with CSS; Required and Bindings declared unsupported via ACF supports; empty Presentation tab hidden |
| Settings sanitization | Saved as submitted | Allowlisted and clamped on load and save |
Legacy x/6 values |
Converted to x/12 |
Not applicable (see Moving from ACF Extended Column) |
| WPGraphQL for ACF | Registered as String |
Not integrated (the field holds no value) |
| Runs with the other plugin active | — | Yes: separate type, classes and assets |
| Codebase | PHP 5.6-compatible, ES5 jQuery | PHP 8.1 (namespace, strict types), ES2020+, ResizeObserver |
Same as ACF Extended: endpoint column, seamless meta boxes, left label placement, conditional logic on the column, no rendering on the Add New Term form.
Moving from ACF Extended Column
The columns and endpoint setting keys are the same as in ACF Extended, so an existing column keeps its width when only the type changes.
- Field group editor: open the column field and change Field Type to Multi Column.
- Local JSON / PHP: replace
"type": "acfe_column"with"type": "multi_column".
Old ACF Extended values on a 6-column grid (1/6 … 6/6) are not converted; they fall back to 6/12. Re-save the field group with ACF Extended active first, or set the width again.
Don't mix ACF Extended Column and Multi Column fields in the same fields container.
Developer reference
Register fields in PHP
add_action('acf/init', function (): void {
acf_add_local_field_group([
'key' => 'group_article_meta',
'title' => 'Article meta',
'fields' => [
['key' => 'field_col_main', 'type' => 'multi_column', 'grid' => '12', 'columns' => '8/12'],
['key' => 'field_title', 'label' => 'Title', 'name' => 'title', 'type' => 'text'],
['key' => 'field_subtitle', 'label' => 'Subtitle', 'name' => 'subtitle', 'type' => 'text'],
['key' => 'field_col_side', 'type' => 'multi_column', 'grid' => 'percent', 'percentage' => 33],
['key' => 'field_date', 'label' => 'Date', 'name' => 'date', 'type' => 'date_picker'],
['key' => 'field_col_end', 'type' => 'multi_column', 'endpoint' => 1],
['key' => 'field_content', 'label' => 'Content', 'name' => 'content', 'type' => 'wysiwyg'],
],
'location' => [[['param' => 'post_type', 'operator' => '==', 'value' => 'post']]],
]);
});
label and name can be left out for column fields; they are generated.
Rendered markup
<!-- Column (12-column grid) -->
<div class="acf-field acf-field-multi-column" data-type="multi_column"
data-grid="12" data-columns="8/12" style="--acf-mcf-width: 66.6667%;">
<div class="acf-label">…</div> <!-- hidden -->
<div class="acf-input">
<div class="acf-fields">…moved fields…</div>
</div>
</div>
<!-- Column (percentage) -->
<div class="acf-field acf-field-multi-column" data-grid="percent" style="--acf-mcf-width: 33%;">…</div>
<!-- Endpoint -->
<div class="acf-field acf-field-multi-column" data-endpoint="1">…</div>
| Attribute / class | Added by | Meaning |
|---|---|---|
--acf-mcf-width |
PHP | Column width in % (up to 4 decimals) |
data-grid |
PHP | 12 or percent |
data-columns |
PHP | 1/12 … 12/12 (12-column grid only) |
data-full |
PHP | Column is 100% wide |
data-endpoint |
PHP | Endpoint column |
.acf-mcf-wrapper |
JS | Fields container that holds columns (flex grid) |
.-mcf-medium |
JS | Container 420–639px wide |
.-mcf-small |
JS | Container below 420px wide |
Width attributes are output through ACF's core acf/field_wrapper_attributes filter.
Assets
| Handle | Files | Loaded on |
|---|---|---|
acf-multi-column-field-input (style + script) |
assets/css/input.css, assets/js/input.js |
Any screen where ACF renders fields (acf/input/admin_enqueue_scripts) |
acf-multi-column-field-group (style + script) |
assets/css/field-group.css, assets/js/field-group.js |
ACF field group editor (acf/field_group/admin_enqueue_scripts) |
Scripts load in the footer and depend on acf-input / acf-field-group. No build step; files are plain, unminified CSS and JS.
Known limitations
- Breakpoints (640px / 420px) are constants in
assets/js/input.js, not settings. - Layout only: the field stores no value, isn't exposed in the REST API and has no front-end output.
- Columns are ignored in table layouts and on the Add New Term form.
- One grid per fields container: don't mix ACF Extended Column and Multi Column fields in the same container.
- Needs a browser with
ResizeObserver,:is()and:has()support (all current evergreen browsers).
Security
- No AJAX actions, REST routes, options or custom database access.
- Field settings are allowlisted (
grid,columns) and clamped (percentage) whenever a field is loaded or saved. - All HTML output is escaped (
esc_attr,esc_html, ACF'sacf_esc_attrs). - The requirements notice is shown only to users with the
activate_pluginscapability.
File structure
acf-multi-column-field/
├── acf-multi-column-field.php Plugin header, ACF check, admin notice, field registration
├── src/
│ └── Field.php Field type (settings, sanitization, wrapper attributes, assets)
├── assets/
│ ├── css/
│ │ ├── input.css Grid on edit screens
│ │ └── field-group.css Field group editor styles, width preview, type icon
│ ├── js/
│ │ ├── input.js Moves fields into columns, container size classes
│ │ └── field-group.js Live label, endpoint marker, width preview
│ └── images/
│ ├── icon-field-multi-column.svg
│ └── field-preview-multi-column.svg
├── readme.txt WordPress plugin readme
└── README.md
Changelog
1.0.0
- Initial release.
License
GPLv2 or later. See https://www.gnu.org/licenses/gpl-2.0.html.