Is it possible to tile the groups in node-red-dashboard vertically?

Here my dashboard with 6 groups.

I have numbered the group labels in the same order as they appear in the dashboard editor window:

So you can see that the dashboard node is tiling the groups first horizontally and then vertically.
My Question: So is there a way to switch the tiling order so that it first tiles the groups vertically and then horizontally ?

I understand that for fixed size groups (so not making use of collapse) and a fixed size browser screen I can achieve this by changing the order of the groups in the node-red dashboard editor but I want it also to work for different browser screen sizes and when I collapse/uncollapse groups.

Have you tried making the group smaller? Set the group to the width of the tabs and it will force all the tabs into one column

All the six groups have the same size = 8.

Note that the 6 groups themselves contain several widgets: you can't see them in the screenshot as I have collapsed them. The problem is not with the tiling of widgets within the groups but with the tiling of the groups within the tab.

Why not put all those widgets into one group?

I want every group to have a title and want to be able to (de)collapse all widgets belonging to a group.

Well cant say it is impossible but many things then do need heavy overrides. So the layout behavior is completely different...

Smaller screen:

Bigger screen

Flow contains totally random nodes inside groups but all are from default collection.

[{"id":"1fb35f29bb459e80","type":"ui_button","z":"bf0d83d32eec75c2","name":"","group":"674712f8d915bcc0","order":9,"width":0,"height":0,"passthru":false,"label":"random","tooltip":"","color":"","bgcolor":"","className":"","icon":"","payload":"","payloadType":"date","topic":"topic","topicType":"msg","x":180,"y":100,"wires":[[]]},{"id":"8ec4a283e5a7af92","type":"ui_button","z":"bf0d83d32eec75c2","name":"negative value","group":"674712f8d915bcc0","order":2,"width":3,"height":1,"passthru":true,"label":"- value","tooltip":"","color":"","bgcolor":"","className":"","icon":"","payload":"-5","payloadType":"num","topic":"","topicType":"str","x":200,"y":180,"wires":[[]]},{"id":"d5d8e1e3310fa854","type":"ui_button","z":"bf0d83d32eec75c2","name":"positive value","group":"674712f8d915bcc0","order":3,"width":3,"height":1,"passthru":true,"label":"+ value","tooltip":"","color":"","bgcolor":"","className":"","icon":"","payload":"3","payloadType":"num","topic":"","topicType":"str","x":200,"y":140,"wires":[[]]},{"id":"de6f6d0003c8f83c","type":"ui_template","z":"bf0d83d32eec75c2","group":"a0cb64ed7acda92f","name":"text-input","order":6,"width":"6","height":"1","format":"<style>\n    /*the container class defined as additional class for ui_template*/\n    .input-container{\n        display: flex;        \n        flex-direction: row;\n        justify-content: flex-start;\n        align-items: center;\n        padding:3px 12px;\n    }\n    /* a paragraph which is direct child of the input-container*/\n    .input-container > p {\n        color:red !important;\n        user-select:none;\n        width:100%;\n    }\n    /* an input element which is direct child of the input-container*/\n    .input-container > input{\n        background-color: transparent;\n        border: unset;\n        border-bottom: 1px solid #00a9ff;       \n        outline: unset;\n        color: #e2ff00;\n        text-align: end;\n        width:3em;\n    }\n\n    \n</style>\n\n<p>HW Target temp</p>\n<input type=\"text\" min=\"17.2\" max=\"63\" ng-model=\"inputChange\" ng-keypress=\"$event.keyCode === 13 && sendInput()\"><span>°C</span></input>\n\n<script>\n(function(scope) {\n\n    //define a variable to hold and share the typed data\n    //so it can be used in any function in scope\n    let inputData = ''\n\n    // function to be called on keyboard \"Enter\"\n    scope.sendInput = function() {\n        //if the data is empty string, dont send anything        \n        if(inputData == ''){\n            return\n        }       \n        // send last know inputData to the server\n        scope.send({payload: parseFloat(inputData), topic: \"input-changed\"})        \n    }\n\n    scope.$watch('inputChange', function(data) {\n        if (data) {            // every time something is typed, store the data so it can be used whenever needed\n            inputData = data;           \n        }\n    });\n    // this can be deleted if you don't need to react on any input message.\n    scope.$watch('msg', function(msg) {\n        if (msg) {\n        // Do something when msg arrives     \n        }\n    });\n})(scope);\n</script>\n","storeOutMessages":true,"fwdInMessages":true,"resendOnRefresh":true,"templateScope":"local","className":"input-container","x":240,"y":220,"wires":[[]]},{"id":"ff30c601e53818e8","type":"ui_switch","z":"bf0d83d32eec75c2","name":"","label":"AC switch","tooltip":"","group":"a0cb64ed7acda92f","order":5,"width":"6","height":"1","passthru":true,"decouple":"false","topic":"topic","topicType":"msg","style":"","onvalue":"true","onvalueType":"bool","onicon":"","oncolor":"","offvalue":"false","offvalueType":"bool","officon":"","offcolor":"","animate":false,"className":"","x":280,"y":260,"wires":[[]]},{"id":"b9039e34deee9b65","type":"ui_text","z":"bf0d83d32eec75c2","group":"674712f8d915bcc0","order":7,"width":0,"height":0,"name":"","label":"AC text","format":"value","layout":"row-spread","className":"","x":320,"y":300,"wires":[]},{"id":"9821976d.81e4a8","type":"inject","z":"bf0d83d32eec75c2","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"2","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":210,"y":500,"wires":[["5d17609.94dd2a","9d583201.b3e3","7ceb37db.bf6158","9f86e34f.b94b5"]]},{"id":"5d17609.94dd2a","type":"random","z":"bf0d83d32eec75c2","name":"","low":1,"high":"100","inte":"true","property":"payload","x":380,"y":460,"wires":[["ff079329.434ad"]]},{"id":"9d583201.b3e3","type":"random","z":"bf0d83d32eec75c2","name":"","low":1,"high":"100","inte":"true","property":"payload","x":380,"y":540,"wires":[["a8b35e60.cbf8b","6a797db2.668714"]]},{"id":"a8b35e60.cbf8b","type":"ui_template","z":"bf0d83d32eec75c2","group":"3cd020e88fa644c5","name":"simple level blue ","order":9,"width":3,"height":3,"format":"<div id=\"{{'level_'+$id}}\" class=\"simple-gauge\">\n    <div class=\"leveltext title\">LEVEL</div>\n    <div class=\"leveltext value\"></div>\n    <div class='levelbody' style='background:#2196f399;'></div>\n    <div class='levelframe' style='border-color:#2196f3; border-width:2px;'></div>\n</div>\n<script>\n(function(scope) {\n   \n  scope.$watch('msg', function(msg) {\n    if (msg) {\n        if(!$(\"#level_\"+scope.$id)){\n            return\n        }\n        $(\"#level_\"+scope.$id).find(\".levelbody\").css(\"height\",msg.payload+\"%\")\n        $(\"#level_\"+scope.$id).find(\".value\").text(msg.payload+\"%\")\n    }\n  });\n})(scope);\n</script>","storeOutMessages":true,"fwdInMessages":true,"resendOnRefresh":true,"templateScope":"local","className":"","x":600,"y":540,"wires":[[]]},{"id":"9139794a.12e668","type":"ui_template","z":"bf0d83d32eec75c2","group":"a0cb64ed7acda92f","name":"simple level top down","order":12,"width":3,"height":3,"format":"<div id=\"{{'level_'+$id}}\" class=\"simple-gauge\">\n    <div class=\"leveltext title\">BLINDS</div>\n    <div class=\"leveltext value\"></div>\n    <div class='levelbody topdown' style='background:\"#FFFFCCf7\";'></div>\n    <div class='levelframe' style='border-color:\"#FFFFFF\"; border-width:6px;'></div>\n</div>\n\n<script>\n(function(scope) {\n   \n  scope.$watch('msg', function(msg) {\n    if (msg) {\n        if(!$(\"#level_\"+scope.$id)){\n            return\n        }\n        $(\"#level_\"+scope.$id).find(\".levelbody\").css(\"height\",msg.payload+\"%\")\n        $(\"#level_\"+scope.$id).find(\".value\").text(msg.payload+\"%\")\n    }\n  });\n})(scope);\n</script>","storeOutMessages":true,"fwdInMessages":true,"resendOnRefresh":true,"templateScope":"local","className":"","x":620,"y":500,"wires":[[]]},{"id":"a78d7f3c.66fc6","type":"ui_template","z":"bf0d83d32eec75c2","group":"19f5ed07.08a453","name":"simple-gauge css","order":3,"width":0,"height":0,"format":"<style id=\"simple-gauge\">\n\n.simple-gauge{\n    overflow:hidden;\n    position:relative;\n    width:100%;\n    height:100%;\n}\n.levelbody.side.right {\n    right:0;\n}\n.levelbody.side.left {\n    left:0;\n}\n.levelbody.side {\n    height:100%;\n    width:0%;\n}\n.levelbody.topdown {\n    bottom: unset;\n    top:0;\n}\n.levelbody.round {\n    height:100%;\n    width:100%;\n}\n.levelbody{\n    background: #FFFFCCf7;\n    height: 0%;\n    position: absolute;\n    width: 100%;\n    bottom: 0;\n    z-index:0;\n    transition: all 1s;\n    box-shadow: inset 0px 0px 10px 0px #00000080;\n}\n.bodywrap{\n    position: absolute;\n    clip-path: circle(50%);\n    width: 100%;\n    height: 100%;\n    bottom: 0;\n}\n.levelframe.round{\n    border-radius:50%;\n}\n.levelframe{\n    position:absolute;\n    box-sizing:border-box;\n    background:transparent;\n    height:100%;\n    width: 100%;\n    border:1px solid #FFFFFF ;\n    box-shadow:inset 0px 0px 41px 0px #000000b5;\n    bottom:0;\n    z-index:1;\n}\n.leveltext{\n    top:30%;\n    position:relative;\n    width:100%;\n    text-align:center;\n    text-shadow: 0px 0px 9px #191938c2;\n    z-index:2;\n    mix-blend-mode: exclusion;\n}\n.leveltext.value{\n    font-size:25px;\n}\n.leveltext.title{\n}\n</style>","storeOutMessages":true,"fwdInMessages":true,"resendOnRefresh":true,"templateScope":"global","className":"","x":610,"y":620,"wires":[[]]},{"id":"ff079329.434ad","type":"ui_template","z":"bf0d83d32eec75c2","group":"19f5ed07.08a453","name":"simple level side","order":11,"width":3,"height":3,"format":"<div id=\"{{'level_'+$id}}\" class=\"simple-gauge\">\n    <div class=\"leveltext title\">BLINDS</div>\n    <div class=\"leveltext value\"></div>\n    <div class='levelbody side' style='background:\"#FFFFCCf7\";'></div>\n    <div class='levelframe' style='border-color:\"#FFFFFF\"; border-width:6px;'></div>\n</div>\n\n<script>\n(function(scope) {\n   \n  scope.$watch('msg', function(msg) {\n    if (msg) {\n        if(!$(\"#level_\"+scope.$id)){\n            return\n        }\n        $(\"#level_\"+scope.$id).find(\".levelbody\").css(\"width\",msg.payload+\"%\")\n        $(\"#level_\"+scope.$id).find(\".value\").text(msg.payload+\"%\")\n    }\n  });\n})(scope);\n</script>","storeOutMessages":true,"fwdInMessages":true,"resendOnRefresh":true,"templateScope":"local","className":"","x":600,"y":460,"wires":[[]]},{"id":"e9e664c6.c84b48","type":"ui_template","z":"bf0d83d32eec75c2","group":"19f5ed07.08a453","name":"simple level double side","order":13,"width":"4","height":3,"format":"<div id=\"{{'level_'+$id}}\" class=\"simple-gauge\">\n    <div class=\"leveltext title\">CURTAINS</div>\n    <div class=\"leveltext value\"></div>\n    <div class='levelbody side left' style='background:\"#FFFFCCf7\";'></div>\n    <div class='levelbody side right' style='background:\"#FFFFCCf7\";'></div>\n    <div class='levelframe' style='border-color:\"#FFFFFF\"; border-width:6px;'></div>\n</div>\n\n<script>\n(function(scope) {\n   \n  scope.$watch('msg', function(msg) {\n    if (msg) {\n        if(!$(\"#level_\"+scope.$id)){\n            return\n        }\n        $(\"#level_\"+scope.$id).find(\".levelbody.side\").css(\"width\",(msg.payload/2)+\"%\")\n       \n        $(\"#level_\"+scope.$id).find(\".value\").text(msg.payload+\"%\")\n    }\n  });\n})(scope);\n</script>","storeOutMessages":true,"fwdInMessages":true,"resendOnRefresh":true,"templateScope":"local","className":"","x":630,"y":420,"wires":[[]]},{"id":"6a797db2.668714","type":"ui_template","z":"bf0d83d32eec75c2","group":"3cd020e88fa644c5","name":"simple level blue round","order":10,"width":3,"height":3,"format":"<div id=\"{{'level_'+$id}}\" class=\"simple-gauge round\">\n    <div class=\"leveltext title\">LEVEL</div>\n    <div class=\"leveltext value\"></div>\n    <div class=bodywrap>\n    <div class='levelbody round' style='background:#2196f399;'></div>\n    </div>\n    <div class='levelframe round' style='border-color:#2196f3; border-width:2px;'></div>\n</div>\n<script>\n(function(scope) {\n   \n  scope.$watch('msg', function(msg) {\n    if (msg) {\n        if(!$(\"#level_\"+scope.$id)){\n            return\n        }\n        $(\"#level_\"+scope.$id).find(\".levelbody\").css(\"top\",(100-msg.payload)+\"%\")\n        $(\"#level_\"+scope.$id).find(\".value\").text(msg.payload+\"%\")\n    }\n  });\n})(scope);\n</script>","storeOutMessages":true,"fwdInMessages":true,"resendOnRefresh":true,"templateScope":"local","className":"","x":620,"y":580,"wires":[[]]},{"id":"9f86e34f.b94b5","type":"random","z":"bf0d83d32eec75c2","name":"","low":1,"high":"100","inte":"true","property":"payload","x":380,"y":420,"wires":[["e9e664c6.c84b48"]]},{"id":"7ceb37db.bf6158","type":"random","z":"bf0d83d32eec75c2","name":"","low":1,"high":"100","inte":"true","property":"payload","x":380,"y":500,"wires":[["9139794a.12e668"]]},{"id":"4e7e0d90ee7aa1ad","type":"ui_template","z":"bf0d83d32eec75c2","group":"674712f8d915bcc0","name":"A bit different layout","order":7,"width":0,"height":0,"format":"<style id='different-layout'>\n    .masonry-container {\n        position: relative;\n        width:100%;\n        margin: 1em auto;\n        align-content: center;\n        display: grid;\n        grid: auto-flow / repeat(3, 330px);\n        justify-content: center;\n        justify-items: center;\n        align-items: start;\n        gap: 0.5em;\n    }\n    .masonry-container > * {\n        position: relative;\n        left:unset !important;\n        top:unset!important;        \n    }\n\n    .masonry-container > ui-card-panel:has(> .ordered-1){\n        order:1;\n    }\n    .masonry-container > ui-card-panel:has(> .ordered-2){\n        order:4;\n    }\n    .masonry-container > ui-card-panel:has(> .ordered-3){\n        order:2;\n    }\n    .masonry-container > ui-card-panel:has(> .ordered-4){\n        order:5;\n    }\n    .masonry-container > ui-card-panel:has(> .ordered-5){\n        order:3;\n    }\n    .masonry-container > ui-card-panel:has(> .ordered-6){\n        order:6;\n    }\n\n    @media screen and (max-width: 1024px) {\n        .masonry-container {\n            grid: auto-flow / repeat(2, 330px);\n        }\n        .masonry-container > ui-card-panel:has(> .ordered-1){\n            order:1;\n        }\n        .masonry-container > ui-card-panel:has(> .ordered-2){\n            order:3;\n        }\n        .masonry-container > ui-card-panel:has(> .ordered-3){\n            order:5;\n        }\n        .masonry-container > ui-card-panel:has(> .ordered-4){\n            order:2;\n        }\n        .masonry-container > ui-card-panel:has(> .ordered-5){\n            order:4;\n        }\n        .masonry-container > ui-card-panel:has(> .ordered-6){\n            order:6;\n        }\n    }\n\n\n</style>","storeOutMessages":true,"fwdInMessages":true,"resendOnRefresh":true,"templateScope":"global","className":"","x":510,"y":220,"wires":[[]]},{"id":"7d38fc60032eac9c","type":"ui_numeric","z":"bf0d83d32eec75c2","name":"","label":"numeric","tooltip":"","group":"b5937d89450a68f6","order":0,"width":0,"height":0,"wrap":false,"passthru":true,"topic":"topic","topicType":"msg","format":"{{value}}","min":0,"max":10,"step":1,"className":"","x":360,"y":340,"wires":[[]]},{"id":"64d74175c19852ce","type":"ui_switch","z":"bf0d83d32eec75c2","name":"","label":"switch","tooltip":"","group":"02e7165d30fe7c8f","order":0,"width":0,"height":0,"passthru":true,"decouple":"false","topic":"topic","topicType":"msg","style":"","onvalue":"true","onvalueType":"bool","onicon":"","oncolor":"","offvalue":"false","offvalueType":"bool","officon":"","offcolor":"","animate":false,"className":"","x":410,"y":380,"wires":[[]]},{"id":"674712f8d915bcc0","type":"ui_group","name":"1. group","tab":"62083694d0eab7ca","order":1,"disp":true,"width":"6","collapse":true,"className":"ordered-1"},{"id":"a0cb64ed7acda92f","type":"ui_group","name":"3. group","tab":"62083694d0eab7ca","order":3,"disp":true,"width":"6","collapse":true,"className":"ordered-3"},{"id":"3cd020e88fa644c5","type":"ui_group","name":"4. group","tab":"62083694d0eab7ca","order":4,"disp":true,"width":"6","collapse":true,"className":"ordered-4"},{"id":"19f5ed07.08a453","type":"ui_group","name":"2. group","tab":"62083694d0eab7ca","order":2,"disp":true,"width":"6","collapse":true,"className":"ordered-2"},{"id":"b5937d89450a68f6","type":"ui_group","name":"5. group","tab":"62083694d0eab7ca","order":5,"disp":true,"width":"6","collapse":true,"className":"ordered-5"},{"id":"02e7165d30fe7c8f","type":"ui_group","name":"6. group","tab":"62083694d0eab7ca","order":6,"disp":true,"width":"6","collapse":true,"className":"ordered-6"},{"id":"62083694d0eab7ca","type":"ui_tab","name":"Home","icon":"dashboard","order":1,"disabled":false,"hidden":false}]
1 Like

Thanks a lot, it works nicely if width of group is 6 but what do I need to change if width of group is 8.

grid: auto-flow / repeat(3, 330px);

The 330px here is width of the ui-card-panel element. That needs to be changed.

Use browser developer tool to identify the correct size..

It should be 328px also in the code but I was lazy. Sorry about that.

Also the breaking point here @media screen and (max-width: 1024px) is something you should figure out for your case cos it really depends on choice of screen sizes and the content sizes.

2 Likes

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.