id to each block to saved data blocks property layout property to saved data object.The layout should describe layout scheme of Blocks by their ids. For example
[---1---]
[---2---]
[ 3 ][ 4 ]
[---5---]
should be described as
[1, 2, [3, 4], 5]
```
Hey. Smart feature. Nice 馃憦
We really need this in our project. Do you think there is any simpler and temporary way I can implement this with current API?
I too would love to have something like this. Will try to contribute! :P
+1 for this feature
This is very interested feature! 馃槂
But Editor.js may become difficult to maintain.
This is the only feature I need to start using Editor.js in my project.
I think that this feature should be thought of I a more generic mater.
Though it's great in its use for layout. It could do more than that. The setup inside Editor.js would be the same but the output could also be:
Tabs (vertical/horizontal)
Slides
Ul => li
Bootstrap => Rows and columns
And probably more...
Since editor.js allows us to set our own options. You can add options for:
Tabs and bootstrap like => Type: Tab / Boostrap or row size, it's basically up to you.
I have also explained some of it on my post #1199
+1 from my end too please. This would be really important to have.
@neSpecc Also, is it limited to 2 columns or can it be more?
For eg. if I need a row with 4 columns, while the data model should remain the same making it [1, 2, [3, 4,5,6], 7] but I hope editor.js would be supporting that.
Thanks.
Is the idea to limit it to a single level? Or will it be recursive nesting?
In other words, will this be possible?
[ 1 ]
[ 2 ]
[ 3 ] [ 4 ]
[ 5 [ 6 [ 7 ] 8 ] 9 ]
[1, 2, [3, 4], [5, [6, [7], 8], 9]]
Hi, I think this feature will make editorjs more awesome.
A Simple Idea:
Brief: By using CSS flex and bootstrap like column layout system there is no need to have row blocks in order to achieve grid layouting or even nested elements ( not an ultimate solution but a minimal editorjs style :| )
You can
.codex-editor__redactor{display: flex;flex-wrap: wrap;flex-direction: row;}.ce-block{width: 100%;}I don't know how can I add default settings to all available elements (like delete and sort arrows for paragraph or header ) but if someone can guide me where to look I can prepare a demo to show you! ;)
This is the current implementation in my project:

Thanks
Hi Again :)
I tested flex layout and it worked fine so far. I made a demo Paragraph with layout settings and other custom tools ( text fields,buttons and ..)
It can be added like supportMultipeColumns: true to EditorJS.
I hope it helps! It is for me ;) I can not implement this settings globally though (for other available tools).
About nesting and having extra elements to implement multiple columns I think EditorJS is more Editor than a Builder or Composer . Actually this is the main reason I'm developing with EditorJS and it is clean, minimal and super flexible!
Here is the demo:

@oodeveloper Awesome to see this. Do you have any reference/code on how we can do this? Thanks.
@tvvignesh sure, the issue is that you need to add settings to each plugin too( like Header, Quote, Image and ...)
I'm still working on it [I know editorJS for about 3 days! :) It would be great if someone point me to a right direction but I need to study the code so I can plug it globally :)]
Here is a Button field which has this feature. It is just a demo, you need to save the data, I was just testing :)).
But renderSettings is complete and adds multiple columns ui!
NOTE: It uses BootStrap flex columns and padding system [col-1, col-2 and ... | pl-1, pr-2, pt-3, pb-4] so please make sure you have these classes in your CSS.
tools: { button: SimpleButtonField }
PLUGIN:
CSS:
#editorjs{max-width: 650px;margin: 0 auto}
.codex-editor__redactor{display: flex;flex-wrap: wrap;flex-direction: row;}
.ce-block{width: 100%;padding-left: 0;padding-right: 0;}
.cdx-settings-input{border: 1px solid rgba(201,201,204,.48);-webkit-box-shadow: inset 0 1px 2px 0 rgba(35,44,72,.06);box-shadow: inset 0 1px 2px 0 rgba(35,44,72,.06);border-radius: 3px;padding: 3px 8px;outline: none;width: 100%;-webkit-box-sizing: border-box;box-sizing: border-box;}
.cdx-small{font-size: .6rem}
.ce-block__content{max-width: 100%}
.cdx-settings-button.disabled{pointer-events: none;opacity: .5}
.cdx-settings-sidebar{position: absolute;left: 100%;top:0;background: #fff;width: 108px;height: 145px;box-shadow: 0 3px 15px -3px rgba(13,20,33,.13);border-radius: 0 4px 4px 0;z-index: 0;}
JS:
// Button
class SimpleButtonField {
constructor({data, api}){
this.api = api;
this._currentWidth = 12;
this._pl = 0;
this._pr = 0;
this._pt = 0;
this._pb = 0;
this._wrapper = undefined;
this._block = undefined;
this._input = undefined;
this._settingsSidebar = undefined;
this._button = undefined;
}
static get toolbox() {
return {
title: 'Button',
icon: `<svg version="1.1" width="22" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 50 30" style="enable-background:new 0 0 50 30;" xml:space="preserve"><path id="XMLID_2_" class="st0" d="M45.7,0.2H5.1c-1.8,0-3.2,1.5-3.2,3.2V27c0,1.8,1.5,3.2,3.2,3.2h40.7c1.8,0,3.2-1.5,3.2-3.2V3.4 C49,1.6,47.5,0.2,45.7,0.2z M28.9,20.9l-1.2,0.8l-1.9-2.9l-3.4,2.2L20.2,8.7l10.3,6.8l-3.6,2.4L28.9,20.9z"/></svg>`
};
}
render(){
var wrapper = document.createElement('div');
var button = document.createElement('button');
wrapper.setAttribute('class','form-group');
button.setAttribute('class','btn btn-primary btn-block');
button.innerHTML = 'Button';
wrapper.appendChild(button);
this._button = button;
this._wrapper = wrapper;
return wrapper;
}
renderSettings(){
const wrapper = document.createElement('div');
let caption = document.createElement('input');
caption.classList.add('cdx-settings-input','mb-1');
caption.setAttribute("placeholder", 'Caption');
let selectClass = document.createElement('select');
selectClass.setAttribute('id','field-type');
selectClass.setAttribute("placeholder", 'Type');
selectClass.classList.add('cdx-settings-input');
selectClass.classList.add('mb-1');
const classOptions = [
{
value: '',
title: 'Class'
},
{
value: 'info',
title: 'Info'
},
{
value: 'warning',
title: 'Warning'
},
{
value: 'danger',
title: 'Danger'
},
{
value: 'success',
title: 'Success'
},
{
value: 'primary',
title: 'Primary'
}
];
classOptions.forEach( opt => {
let option = document.createElement('option');
option.setAttribute("value", opt.value);
option.innerHTML = opt.title;
selectClass.appendChild(option);
});
// inputId.innerHTML = tune.icon;
caption.addEventListener('keyup', (e) => {
this._button.innerHTML = e.target.value;
});
selectClass.addEventListener('change', (e) => {
this._button.setAttribute('class','btn btn-block btn-'+e.target.value);
});
var parent = this._wrapper.parentNode;
this._block = parent.parentNode;
// increase width
let inreaseWidthBtn = document.createElement('div');
inreaseWidthBtn.classList.add('cdx-settings-button');
inreaseWidthBtn.innerHTML = `<svg width="17" height="10" viewBox="0 0 17 10" xmlns="http://www.w3.org/2000/svg"><path d="M13.568 5.925H4.056l1.703 1.703a1.125 1.125 0 0 1-1.59 1.591L.962 6.014A1.069 1.069 0 0 1 .588 4.26L4.38.469a1.069 1.069 0 0 1 1.512 1.511L4.084 3.787h9.606l-1.85-1.85a1.069 1.069 0 1 1 1.512-1.51l3.792 3.791a1.069 1.069 0 0 1-.475 1.788L13.514 9.16a1.125 1.125 0 0 1-1.59-1.591l1.644-1.644z"/></svg>`;
wrapper.appendChild(inreaseWidthBtn);
inreaseWidthBtn.addEventListener('click', () => {
this._increaseWidth();
inreaseWidthBtn.classList.toggle('cdx-settings-button--active');
});
/// Decrease width
let decreaseWidthBtn = document.createElement('div');
decreaseWidthBtn.classList.add('cdx-settings-button');
decreaseWidthBtn.innerHTML = `<svg version="1.1" height="10" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="-674 380 17 10" style="enable-background:new -674 380 17 10;" xml:space="preserve"><path d="M-674,383.9h3.6l-1.7-1.7c-0.4-0.4-0.4-1.2,0-1.6c0.4-0.4,1.1-0.4,1.6,0l3.2,3.2c0.6,0.2,0.8,0.8,0.6,1.4 c-0.1,0.1-0.1,0.3-0.2,0.4l-3.8,3.8c-0.4,0.4-1.1,0.4-1.5,0c-0.4-0.4-0.4-1.1,0-1.5l1.8-1.8h-3.6V383.9z"/><path d="M-657,386.1h-3.6l1.7,1.7c0.4,0.4,0.4,1.2,0,1.6c-0.4,0.4-1.1,0.4-1.6,0l-3.2-3.2c-0.6-0.2-0.8-0.8-0.6-1.4 c0.1-0.1,0.1-0.3,0.2-0.4l3.8-3.8c0.4-0.4,1.1-0.4,1.5,0c0.4,0.4,0.4,1.1,0,1.5l-1.8,1.8h3.6V386.1z"/></svg>`;
wrapper.appendChild(decreaseWidthBtn);
decreaseWidthBtn.addEventListener('click', () => {
this._decreaseWidth();
decreaseWidthBtn.classList.toggle('cdx-settings-button--active');
});
// Paddings
let paddingBtn = document.createElement('div');
paddingBtn.classList.add('cdx-settings-button');
paddingBtn.innerHTML = `<svg version="1.1" height="12" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="-674 379 17 12" style="enable-background:new -674 379 17 12;" xml:space="preserve"><rect x="-666.1" y="379.9" width="1.7" height="10.3"/><polygon points="-657,384.2 -659.9,384.2 -658.8,383.1 -660,381.9 -663.1,385 -660,388.1 -658.8,386.9 -659.9,385.8 -657,385.8 "/><rect x="-671.9" y="379.9" width="4.1" height="1.7"/><rect x="-674" y="384.2" width="6.1" height="1.7"/><rect x="-671.9" y="388.4" width="4.1" height="1.7"/></svg>`;
wrapper.appendChild(paddingBtn);
paddingBtn.addEventListener('click', (e) => {
if(e.target.classList.contains('cdx-settings-button--active')){
this._settingsSidebar.remove();
e.target.classList.remove('cdx-settings-button--active');
} else {
e.target.classList.add('cdx-settings-button--active');
let paddingWrapper = document.createElement('div');
paddingWrapper.classList.add('cdx-settings-sidebar');
// buttons
// Left
let paddingLeftBtn = document.createElement('span');
paddingLeftBtn.classList.add('cdx-settings-button','disabled');
paddingLeftBtn.innerHTML = `<svg version="1.1" height="10" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="-674 380 17 10" style="enable-background:new -674 380 17 10;" xml:space="preserve"><polygon points="-659,384.1 -667.8,384.1 -665.8,381.9 -667,380.7 -671,384.9 -667.1,388.9 -665.8,387.7 -667.8,385.7 -659,385.7 "/></svg>`;
paddingWrapper.appendChild(paddingLeftBtn);
let paddingLeftPlusBtn = document.createElement('span');
paddingLeftPlusBtn.classList.add('cdx-settings-button');
paddingLeftPlusBtn.innerHTML = `<svg version="1.1" height="10" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="-674 381.5 17 7" style="enable-background:new -674 381.5 17 7;" xml:space="preserve"><polygon points="-664.7,388.5 -664.7,381.5 -666.3,381.5 -666.3,388.5 "/><polygon points="-669,385.8 -662,385.8 -662,384.2 -669,384.2 "/></svg>`;
paddingWrapper.appendChild(paddingLeftPlusBtn);
paddingLeftPlusBtn.addEventListener('click', (e) => {
this._increasePadding('l');
});
let paddingLeftMinusBtn = document.createElement('span');
paddingLeftMinusBtn.classList.add('cdx-settings-button');
paddingLeftMinusBtn.innerHTML = `<svg version="1.1" height="10" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="-674 381.5 17 7" style="enable-background:new -674 381.5 17 7;" xml:space="preserve"><polygon points="-669,385.8 -662,385.8 -662,384.2 -669,384.2 "/></svg>`;
paddingWrapper.appendChild(paddingLeftMinusBtn);
paddingLeftMinusBtn.addEventListener('click', (e) => {
this._decreasePadding('l');
});
// Right
let paddingRightBtn = document.createElement('span');
paddingRightBtn.classList.add('cdx-settings-button','disabled');
paddingRightBtn.innerHTML = `<svg version="1.1" height="10" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="-674 380 17 10" style="enable-background:new -674 380 17 10;" xml:space="preserve"><polygon points="-671,385.7 -662.2,385.7 -664.2,387.7 -662.9,388.9 -659,384.9 -663,380.7 -664.2,381.9 -662.2,384.1 -671,384.1 "/></svg>`;
paddingWrapper.appendChild(paddingRightBtn);
let paddingRightPlusBtn = document.createElement('span');
paddingRightPlusBtn.classList.add('cdx-settings-button');
paddingRightPlusBtn.innerHTML = `<svg version="1.1" height="10" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="-674 381.5 17 7" style="enable-background:new -674 381.5 17 7;" xml:space="preserve"><polygon points="-664.7,388.5 -664.7,381.5 -666.3,381.5 -666.3,388.5 "/><polygon points="-669,385.8 -662,385.8 -662,384.2 -669,384.2 "/></svg>`;
paddingWrapper.appendChild(paddingRightPlusBtn);
paddingRightPlusBtn.addEventListener('click', (e) => {
this._increasePadding('r');
});
let paddingRightMinusBtn = document.createElement('span');
paddingRightMinusBtn.classList.add('cdx-settings-button');
paddingRightMinusBtn.innerHTML = `<svg version="1.1" height="10" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="-674 381.5 17 7" style="enable-background:new -674 381.5 17 7;" xml:space="preserve"><polygon points="-669,385.8 -662,385.8 -662,384.2 -669,384.2 "/></svg>`;
paddingWrapper.appendChild(paddingRightMinusBtn);
paddingRightMinusBtn.addEventListener('click', (e) => {
this._decreasePadding('r');
});
// Top
let paddingTopBtn = document.createElement('span');
paddingTopBtn.classList.add('cdx-settings-button','disabled');
paddingTopBtn.innerHTML = `<svg version="1.1" height="13" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="-674 378.5 17 13" style="enable-background:new -674 378.5 17 13;" xml:space="preserve"><polygon points="-664.6,391 -664.6,382.2 -662.6,384.2 -661.4,382.9 -665.4,379 -669.6,383 -668.4,384.2 -666.2,382.2 -666.2,391 "/></svg>`;
paddingWrapper.appendChild(paddingTopBtn);
let paddingTopPlusBtn = document.createElement('span');
paddingTopPlusBtn.classList.add('cdx-settings-button');
paddingTopPlusBtn.innerHTML = `<svg version="1.1" height="10" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="-674 381.5 17 7" style="enable-background:new -674 381.5 17 7;" xml:space="preserve"><polygon points="-664.7,388.5 -664.7,381.5 -666.3,381.5 -666.3,388.5 "/><polygon points="-669,385.8 -662,385.8 -662,384.2 -669,384.2 "/></svg>`;
paddingWrapper.appendChild(paddingTopPlusBtn);
paddingTopPlusBtn.addEventListener('click', (e) => {
this._increasePadding('t');
});
let paddingTopMinusBtn = document.createElement('span');
paddingTopMinusBtn.classList.add('cdx-settings-button');
paddingTopMinusBtn.innerHTML = `<svg version="1.1" height="10" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="-674 381.5 17 7" style="enable-background:new -674 381.5 17 7;" xml:space="preserve"><polygon points="-669,385.8 -662,385.8 -662,384.2 -669,384.2 "/></svg>`;
paddingWrapper.appendChild(paddingTopMinusBtn);
paddingTopMinusBtn.addEventListener('click', (e) => {
this._decreasePadding('t');
});
// Bottom
let paddingBottomBtn = document.createElement('span');
paddingBottomBtn.classList.add('cdx-settings-button','disabled');
paddingBottomBtn.innerHTML = `<svg version="1.1" height="13" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="-674 378.5 17 13" style="enable-background:new -674 378.5 17 13;" xml:space="preserve"><polygon points="-666.2,379 -666.2,387.8 -668.4,385.8 -669.6,387 -665.4,391 -661.4,387.1 -662.6,385.8 -664.6,387.8 -664.6,379 "/></svg>`;
paddingWrapper.appendChild(paddingBottomBtn);
let paddingBottomPlusBtn = document.createElement('span');
paddingBottomPlusBtn.classList.add('cdx-settings-button');
paddingBottomPlusBtn.innerHTML = `<svg version="1.1" height="10" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="-674 381.5 17 7" style="enable-background:new -674 381.5 17 7;" xml:space="preserve"><polygon points="-664.7,388.5 -664.7,381.5 -666.3,381.5 -666.3,388.5 "/><polygon points="-669,385.8 -662,385.8 -662,384.2 -669,384.2 "/></svg>`;
paddingWrapper.appendChild(paddingBottomPlusBtn);
paddingBottomPlusBtn.addEventListener('click', (e) => {
this._increasePadding('b');
});
let paddingBottomMinusBtn = document.createElement('span');
paddingBottomMinusBtn.classList.add('cdx-settings-button');
paddingBottomMinusBtn.innerHTML = `<svg version="1.1" height="10" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="-674 381.5 17 7" style="enable-background:new -674 381.5 17 7;" xml:space="preserve"><polygon points="-669,385.8 -662,385.8 -662,384.2 -669,384.2 "/></svg>`;
paddingWrapper.appendChild(paddingBottomMinusBtn);
paddingBottomMinusBtn.addEventListener('click', (e) => {
this._decreasePadding('b');
});
// buttons - end
wrapper.appendChild(paddingWrapper);
this._settingsSidebar = paddingWrapper;
}
});
wrapper.appendChild(caption);
wrapper.appendChild(selectClass);
return wrapper;
}
_increaseWidth(){
this._block.classList.remove('col-'+this._currentWidth);
if(this._currentWidth < 12){
this._currentWidth = this._currentWidth + 1;
}
this._block.classList.add('col-'+this._currentWidth);
}
_decreaseWidth(){
this._block.classList.remove('col-'+this._currentWidth);
if(this._currentWidth > 2){
this._currentWidth = this._currentWidth - 1;
}
this._block.classList.add('col-'+this._currentWidth);
}
_increasePadding(direction = 'l'){
var amount = 0;
if(direction == 'l'){
amount = this._pl;
} else if(direction == 'r'){
amount = this._pr;
} else if(direction == 't'){
amount = this._pt;
} else if(direction == 'b'){
amount = this._pb;
}
this._block.classList.remove('p'+direction+'-'+amount);
if(amount < 5){
if(direction == 'l'){
this._pl = this._pl + 1;
amount = this._pl;
} else if(direction == 'r'){
this._pr = this._pr + 1;
amount = this._pr;
} else if(direction == 't'){
this._pt = this._pt + 1;
amount = this._pt;
} else if(direction == 'b'){
this._pb = this._pb + 1;
amount = this._pb;
}
}
this._block.classList.add('p'+direction+'-'+amount);
}
_decreasePadding(direction = 'l'){
var amount = 0;
if(direction == 'l'){
amount = this._pl;
} else if(direction == 'r'){
amount = this._pr;
} else if(direction == 't'){
amount = this._pt;
} else if(direction == 'b'){
amount = this._pb;
}
this._block.classList.remove('p'+direction+'-'+amount);
if(amount > 0){
if(direction == 'l'){
this._pl = this._pl - 1;
amount = this._pl;
} else if(direction == 'r'){
this._pr = this._pr - 1;
amount = this._pr;
} else if(direction == 't'){
this._pt = this._pt - 1;
amount = this._pt;
} else if(direction == 'b'){
this._pb = this._pb - 1;
amount = this._pb;
}
}
this._block.classList.add('p'+direction+'-'+amount);
}
save(blockContent){
return {
url: blockContent.value
}
}
}
@oodeveloper Thanks 馃檹 I will test it out and see if I can get around it. I am new to editorjs too. The minimalistic UI, clean data and good docs were what pulled me to it. Hoping to experiment a lot with it.
@tvvignesh :pray:
Exactly, EditorJS is too nice and minimal to not have multi column layout solution or far from EditorJS approach! :sweat_smile:
An alternative solution can be to add this feature to all available tools as another version(multicolumn) but it won't make sense and it is not logical for this common UI to be on all plugins seperately I think!
I hope you find it, I'm working on it too :wink:
Hey,
I Managed to add this feature as a tune: LayoutTune and tried to save and load data by creating setData and getData api methods for blocks.
You can check live implementation here:
Online Demo
_(loaded blocks are to demonstrate setting of width and padding values)_
It is nice to have api methods which let you manipulate tool instance data outside of the tool (or I may didn't find it :grin: )
(editorsJS edited core and block-tune-layout.ts class)
Every current tool will work fine except table and quote tools.
I couldn't save or load data in standard way though :sweat_smile: (and I needed to move on for my project and wait for main version) so I just get the job done for my case and it is working fine by performance.
It is not the ultimate solution but I think it fits the editorial aspect of EditorJS!
BTW: I didn't use flex! blocks will float now!
Other altnative tools: https://github.com/editor-js/awesome-editorjs/pull/14
It can make more flexible layouts (flex, float, ..., and more), but it is still an experimental tool!
@hata6502 Thanks man :pray: inline editorjs is an awesome idea.
I was about to fix the issues by optimizing user behavior like:
BUT now inline editor idea can help a lot and make this work for me :tada:!
if user grids the blocks and continue on each block! I am trying to not engage user with grid layouts directly though.
I hope this feature gets ready soon and it would be great if it can act as table plugin to grid the blocks!:smiley:
You helped a lot :wink:
BTW: editorjs-inspector rocks more if it can extract changes to edited attributes
@neSpecc Thanks for this issue. Appreciate if you could share a timeline for releasing this feature. We would like to use this in one of our projects.
I developed a layout block tool.
See: https://github.com/hata6502/editorjs-layout#readme
@hata6502 I think this is the one. Specially new column zooming in feature is awesome.
My adventure ended by adding this feature to all tools to continue! :)
I updated the demo: https://oodeveloper.github.io/editorjs-multicolumn/ [this approach is limited]
Thanks man (:pray:)
Most helpful comment
Hi Again :)

I tested flex layout and it worked fine so far. I made a demo Paragraph with layout settings and other custom tools ( text fields,buttons and ..)
It can be added like
supportMultipeColumns: trueto EditorJS.I hope it helps! It is for me ;) I can not implement this settings globally though (for other available tools).
About nesting and having extra elements to implement multiple columns I think EditorJS is more Editor than a Builder or Composer . Actually this is the main reason I'm developing with EditorJS and it is clean, minimal and super flexible!
Here is the demo: