Angular CSS Grid Object across multiple Columns - css

I'm trying to do what I thought was a simple task but can't seem to figure it out so maybe it's not possible.
I have an object that I'm iterating through and that object has two attributes
export class OptionLine {
lineCode: number;
lineDescription: String;
}
I would like the LineCode to be Column 1 and LineDescription to be Column 2
My most recent attempt looks like:
<div class="config-options-box">
<div *ngFor="let optionLine of optionLines">
<div class="config-options-line-name">{{optionLine.lineCode}}</div>
<div class="config-options-line-choices">{{optionLine.lineDescription}}</div>
</div>
</div>
CSS:
.config-options-box {
display: grid;
grid-template-columns: 300px 600px;
grid-gap: 10px;
}
.config-options-line-name {
grid-column-start: 1;
grid-row-end: span 1
}
.config-options-line-choices {
grid-column-start: 2;
grid-row-end: span 1
}
But this ends up with item 1 having 2 lines in the first cell, item 2 having 2 lines in the second cell (row 1 column 2), etc.
Is this even possible?

Figured out I could display a sub grid inside each column of the main grid. So the main grid is 1 row x 2 columns and then each column has a grid inside that is n rows x 1 column. Probably not the most efficient solution but I should have less than 20 items so I imagine it will be fine.
<div class="config-options-box">
<div class="config-options-names">
<div *ngFor="let optionLine of optionLines">
<div class="config-options-line-name">{{optionLine.lineCode}}</div>
</div>
</div>
<div class="config-options-descriptions">
<div *ngFor="let optionLine of optionLines">
<div class="config-options-line-name">{{optionLine.lineDescription}}</div>
</div>
</div>
</div>
.config-options-box {
display: grid;
grid-template-columns: 300px 600px;
grid-gap: 10px;
}
.config-options-subgrid {
display: grid;
grid-template-columns: auto;
grid-gap: 10px;
}

Related

Having trouble sizing columns in CSS Grid using auto-fit and auto-fill [duplicate]

This question already has answers here:
Why doesn't min-content work with auto-fill or auto-fit?
(2 answers)
Closed 2 years ago.
I am trying to do a layout using CSS where I have a grid of 2 columns and 2 rows.
The first column should have a width of 1fr and the second column 4fr.
I tried using auto-fit:
HTML
<body>
<header>
<div class="item1">GRID ITEM 1</div>
<div class="item2">GRID ITEM 2</div>
<div class="item1">GRID ITEM 3</div>
<div class="item2">GRID ITEM 4</div>
</header>
</body>
CSS
header {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
}
div {
border: 1px solid;
}
I am having trouble setting 2 different column widths (1fr, 3fr) only using auto-fit and auto-fill when in desktop screen mode. Is there any way to achieve this without using media queries? Or auto-fit and auto-fill are only used when columns are of the same width?
So if I understood right. Your layout should have 5 columns (1 x 1fr , 1 x 4fr) and 2 rows. Here is something that MIGHT answer your question.
.parent {
display: grid;
grid-template-columns: repeat(5, 1fr);
grid-template-rows: repeat(2, 1fr);
height: 300px;
}
.item1 { grid-area: 1 / 1 / 2 / 2; background: red;}
.item2 { grid-area: 1 / 2 / 2 / 6; background: green; }
.item3 { grid-area: 2 / 1 / 3 / 2; background: yellow; }
.item4 { grid-area: 2 / 2 / 3 / 6; background: blue; }
<div class="parent">
<div class="item1"> </div>
<div class="item2"> </div>
<div class="item3"> </div>
<div class="item4"> </div>
</div>

Can a grid cell span every column without specifying the number of columns?

I have a grid with a dynamically generated number of rows and columns. The cells are placed individually with grid-column-start.
I also have accompanying headings which need span every column. I would expect grid-column-start: 1; grid-column-end: -1 to produce this behaviour. However, it only does so if the number of columns is specified in advance with grid-template-columns.
See the following demonstration:
.grid {
display: grid;
grid-gap: 5px;
}
.grid--three {
grid-template-columns: auto auto auto;
}
.grid--auto {
grid-auto-columns: auto;
}
.grid-heading {
background: pink;
grid-column-start: 1;
grid-column-end: -1;
padding: 5px;
}
.grid-cell {
background: lightblue;
padding: 5px;
}
.grid-cell--1 {
grid-column-start: 1;
}
.grid-cell--2 {
grid-column-start: 2;
}
.grid-cell--3 {
grid-column-start: 3;
}
<h3>Three column grid</h3>
<div class="grid grid--three">
<div class="grid-heading">
My heading
</div>
<div class="grid-cell">
one
</div>
<div class="grid-cell">
two
</div>
<div class="grid-cell">
three
</div>
</div>
<h3>Any column grid</h3>
<div class="grid grid--auto">
<div class="grid-heading">
My heading
</div>
<div class="grid-cell grid-cell--1">
one
</div>
<div class="grid-cell grid-cell--2">
two
</div>
<div class="grid-cell grid-cell--3">
three
</div>
</div>
Is it possible to get full column spanning behaviour without prescribing the number of columns?
Unfortunately, no. This is not possible with the current version of CSS Grid (Level 1).
For a grid area to expand across all columns or rows, using the negative integer method (1 / -1), you'll need an explicit grid container.
From the specification:
7.1. The Explicit Grid
Numeric indexes in the grid-placement properties count from the edges
of the explicit grid.
Positive indexes count from the start side (starting from 1 for the start-most explicit line), while negative indexes count from the end side (starting from -1 for the end-most explicit line).
and here...
8.3. Line-based Placement: the grid-row-start, grid-column-start, grid-row-end, and grid-column-end properties
If a negative integer is given, it instead counts in reverse, starting
from the end edge of the explicit grid.
position:absolute can do this but it remain a hacky way as you will need an extra element to take the first cell and have your real element on the top filling the whole row. It can be tricky if it's not the first row.
.grid {
display: grid;
grid-gap: 5px;
position:relative; /* Don't forget this */
}
.grid--three {
grid-template-columns: auto auto auto;
}
.grid--auto {
grid-auto-columns: auto;
}
/**/
.grid:before {
content:"\80"; /* Zero width invisible character */
padding:5px;
grid-column: 1/-1;
}
.grid-heading {
background: pink;
position:absolute;
top:0;
left:0;
right:0;
padding: 5px;
}
/**/
.grid-cell {
background: lightblue;
padding: 5px;
}
.grid-cell--1 {
grid-column-start: 1;
}
.grid-cell--2 {
grid-column-start: 2;
}
.grid-cell--3 {
grid-column-start: 3;
}
<h3>Three column grid</h3>
<div class="grid grid--three">
<div class="grid-heading">
My heading
</div>
<div class="grid-cell">
one
</div>
<div class="grid-cell">
two
</div>
<div class="grid-cell">
three
</div>
</div>
<h3>Any column grid</h3>
<div class="grid grid--auto">
<div class="grid-heading">
My heading
</div>
<div class="grid-cell grid-cell--1">
one
</div>
<div class="grid-cell grid-cell--2">
two
</div>
<div class="grid-cell grid-cell--3">
three
</div>
</div>

Making an element span all columns on a grid with automatic columns [duplicate]

This question already has answers here:
Make a grid item span to the last row / column in implicit grid
(5 answers)
Closed 4 years ago.
I have a CSS grid with automatic columns and 2 rows, where all but a specific element go into the first row. The special element is placed on the second row, and should fill the whole space used by all columns.
The current implementation is like this:
.TabArea {
display: grid;
grid-auto-columns: auto;
grid-template-rows: auto 1fr;
grid-auto-flow: column;
/* for visualization purposes */
background: gainsboro;
}
.Tab-title {
grid-row: 1;
}
.Tab-body {
grid-row: 2;
grid-column: 1 / -1;
/* for visualization purposes */
background: beige;
}
<div class="TabArea">
<div class="Tab-title">Title A</div>
<div class="Tab-title">Title B</div>
<div class="Tab-title">Title B</div>
<div class="Tab-body">content</div>
</div>
But as you can see, the Tab-body is only placed on the first column, despite the fact there are additional columns. How can I make it span all columns?
The solution in https://stackoverflow.com/a/44052563/1045510 does not work here because the number of columns is variable, and columns would take up space on the end, pushing the Tab-titles to the left.
I think you need to use span in order to make it span across columns as you can only use negative integers in an explicit grid:
.TabArea {
display: grid;
grid-auto-columns: auto;
grid-template-rows: auto 1fr;
grid-auto-flow: column;
/* for visualization purposes */
background: gainsboro;
}
.Tab-title {
grid-row: 1;
}
.Tab-body {
grid-row: 2;
grid-column-start: 1;
grid-column-end: span 3;
/* for visualization purposes */
background: beige;
}
<div class="TabArea">
<div class="Tab-title">Title A</div>
<div class="Tab-title">Title B</div>
<div class="Tab-title">Title B</div>
<div class="Tab-body">content</div>
</div>

Grid Columns Without Rows?

I'm trying to create a 3 column layout using the CSS Grid spec but I'm running into an issue with rows and element sizing. My columns need to contain an unspecified amount of content with varying heights.
This is my ideal layout:
Problems:
1) If I tell element A and B to use row 1, column 1 then they stack on top of one another rather than B below A.
2) If I specify element B to use the second row, then it gets pushed below element C due to element C making row 1 tall.
3) If I specify element B to use the second row, then element A stretches to fill row 1.
Is there any way to get elements to behave like in the first picture?
The only solution I know of is to create "scaffolding" divs inside the columns like this:
<div class="grid">
<div class="col">
<div class="itemA"></div>
<div class="itemB"></div>
</div>
<div class="col">
<div class="itemC"></div>
</div>
<div class="col">
<div class="itemD"></div>
<div class="itemE"></div>
<div class="itemF"></div>
</div>
</div>
But I dislike doing that and I thought the grid spec was supposed to allow for layout creation without scaffolding.
Questions:
1) Is there any way to prevent elements from stretching to fill the row vertically?
2) Is it possible to put two elements on the same row and have them appear one below the other instead of conflicting?
Here's my 2 pens where I'm attempting to find a solution with and without scaffolding:
Without scaffolding
With scaffolding
The closest i could have, but i do recommend you to use flexbox, You can't only define columns in CSS grids, the browsers will define rows for you, if you don't, and you don't manage them, you will get weird layout.
I hard coded the difference in heights between elements.
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.grid {
background: brown;
display: grid;
grid-template-columns: auto 1fr auto;
grid-gap: 10px;
padding: 10px;
}
.grid>div {
background-color: orange;
}
.itemA {
grid-column-start: 1;
grid-row: 1 / 1;
width: 100px;
height: 100px;
}
.itemB {
grid-column-start: 1;
grid-row: 2 / 4;
height: 200px;
}
.itemC {
grid-column-start: 2;
grid-row: 1 / 3;
height: 200px;
}
.itemD {
grid-column-start: 3;
width: 100px;
height: 100px;
}
.itemE {
grid-column-start: 3;
height: 100px;
}
.itemF {
grid-column-start: 3;
grid-row: 3 / 4;
height: 200px;
}
<div class="grid">
<div class="itemA">A</div>
<div class="itemB">B</div>
<div class="itemC">C</div>
<div class="itemD">D</div>
<div class="itemE">E</div>
<div class="itemF">F</div>
</div>

Make a grid column span the entire row

Imagine we have 2 CSS Grid containers with dynamic columns count based on width.
display: grid;
grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
The grid works perfectly, but what if we need to have another grid to have the 1st column to be same as in another grid with the code shown above, but it's another column to span through more cells - depending on how many cells are in the current row.
To better understand issue, there are images:
On more narrow wrapper:
We would need to apply something like grid-column: span ALL (if something like that exists), with meaning that ALL = till the end of current row.
What is really important is that "First" column should always align with "1" column.
Code to run example is here:
.grid div {
/* Not important fancy styles */
height: 40px;
text-align: center;
padding-top: 20px;
}
.grid {
width: 350px;
display: grid;
grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
background-color: silver;
}
.grid-second {
background-color: red;
}
.grid-another {
background-color: purple;
border: 1px solid gray;
}
<div class="grid">
<div class="grid-first">
First
</div>
<div class="grid-second">
Second (Want till end)
</div>
</div>
<!-- Another same grid -->
<div class="grid">
<div class="grid-another">
1
</div>
<div class="grid-another">
2
</div>
<div class="grid-another">
3
</div>
<div class="grid-another">
4
</div>
</div>
PS. please do not post solutions using media query. I am interested in any (even little hacky solution), which will work without usage of media queries.
Here are two interesting sections in the CSS Grid specification:
7.1. The Explicit Grid
Numeric indexes in the grid-placement properties count from the edges
of the explicit grid. Positive indexes count from the start side,
while negative indexes count from the end side.
also here...
8.3. Line-based Placement: the grid-row-start, grid-column-start, grid-row-end, and grid-column-end properties
If a negative integer is given, it instead counts in reverse, starting
from the end edge of the explicit grid.
In other words, when dealing with an explicit grid, which means a grid defined by these properties:
grid-template-rows
grid-template-columns
grid-template-areas
grid (which is the shorthand for the three properties above, among others)
... you can make a grid area span all columns by setting this rule:
grid-column: 1 / -1;
That tells the grid area to span from the first column line to the last column line, which I believe meets your stated objective:
"We would need to apply something like grid-column: span ALL (if something like that exists), with meaning that ALL = till the end of current row."
jsFiddle demo
.grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
background-color: silver;
}
.grid-second {
grid-column: 2 / -1;
background-color: red;
}
/* Not important fancy styles */
.grid div {
height: 40px;
text-align: center;
padding-top: 20px;
}
.grid-another {
background-color: purple;
border: 1px solid gray;
}
<div class="grid">
<div class="grid-first">First</div>
<div class="grid-second">Second (Want till end)</div>
</div>
<!-- Another same grid -->
<div class="grid">
<div class="grid-another">1</div>
<div class="grid-another">2</div>
<div class="grid-another">3</div>
<div class="grid-another">4</div>
<div class="grid-another">1</div>
<div class="grid-another">2</div>
<div class="grid-another">3</div>
<div class="grid-another">4</div>
<div class="grid-another">1</div>
<div class="grid-another">2</div>
<div class="grid-another">3</div>
<div class="grid-another">4</div>
</div>

Resources