Smarter grid directive for layouts with fixed number of columns (or rows) to achieve cleaner css #1198
Description
Feature Request
What is the desired behavior?
A better way to specify a grid layout with a fixed number of rows or columns - and taking advantage of this value to intelligently only add margin where needed - with no negative values.
For example it could look something like this:
<div fxLayout="row wrap" fxLayoutGap="1em" fxCols="3">
<div>A1</div>
<div>A2</div>
<div>A3</div>
<div>B1</div>
<div>B2</div>
<div>B3</div>
</div>
Given that we know we have 3 columns - when adding margin we can intelligently do this:
<!-- split elements into groups of 3 -->
<!-- row 1: add margin on left except for first item -->
<div style="margin: 0 0 0 0">A1</div>
<div style="margin: 0 0 0 1em">A2</div>
<div style="margin: 0 0 0 1em">A3</div>
<!-- row 2: add margin on left except for first item, and add margin on top for all items -->
<div style="margin: 1em 0 0 0">B1</div>
<div style="margin: 1em 0 0 1em">B2</div>
<div style="margin: 1em 0 0 1em">B3</div>
This is similar to the fxLayoutGutter
directive feature request but specifically for row / column grid layouts where a fixed number of columns or rows is required.
A few points:
- You would only be allowed to specify one of
fxCols
orfxRows
- CSS grid may be mature enough for many people's use cases.
- It may need to be the user's responsibility to ensure that the flex items fit the width or height and didn't wrap (which would completely break the layout). Another possibility would be to insert a spacer to force a newline but that may be too complicated.
- Per the previous point it might be possible to add a calculated percentage based on number of columns eg.
style.flex="0 1 33%"
- Only applicable for items of the same size, which is most of the times I've ever needed a grid.
- Wouldn't conflict with other similar existing directives - although there may be confusion as to valid combinations
What is the use-case or motivation for the desired behavior?
Existing directives such as fxLayoutGap="1em grid"
create fragile css where usage of negative margins and padding is applied. Child components extend beyond the bounds of their parents and when child items are components the grid layout padding conflicts with existing @HostBinding padding from the component itself. This means you have to add another div to wrap the component.
Sample code
This is very non-production code I wrote a while ago to test the concept - based upon flexLayoutGap.
Only including the triggerUpdate function - this is for a mythical fxColumns
directive. Please escuse the hardcoded dimensions.
private triggerUpdate() {
const items = this.childrenNodes
.filter(el => el.nodeType === 1);
items.forEach((ele, ix) => {
// this layout is for columns
const isFirstRow = ix < this.fxColumns;
const isFirstCol = ix % this.fxColumns == 0;
if (this.fxColumns == 1)
{
// special case for a one column layout
const margin = (isFirstRow ? '0' : '1em 0 0 0');
this.renderer.setStyle(ele, 'margin', margin);
}
else
{
// add left margin - except for first column
// add top margin - except for first row
const margin = (isFirstRow ? '0' : '1.5em') + ' 0 0 ' + (isFirstCol ? '0' : '1.5em');
this.renderer.setStyle(ele, 'margin', margin);
}
});
Is there anything else we should know?
- @CaerusKaru asked me to open this as a separate issue - so happy to suggest it.