CSS Grid Group Variable Width Columns into Fixed Width - html

I've just started learning about CSS Grids and I'm struggling to achieve a certain layout. I have a grid with 4 columns and I want the total width of column 1 + column 2 to equal 50% of the grid and the total width of column 3 + column 4 to equal 50% of the grid. The tricky part is I need the individual columns to have variable widths, specifically columns 1 and 3 to expand with the text they contain and columns 2 and 4 to grow and shrink in relation to the width of columns 1 and 3. Is this possible using the grid layout?
I've been using codepen to test:
https://codepen.io/anon/pen/MqxJNW
<div class="outergrid">
<div class="one">One</div>
<div class="two">Two </div>
<div class="three">Three</div>
<div class="four">Four</div>
<div class="five">Five</div>
<div class="six">Six</div>
<div class="Seven">Seven</div>
<div class="Eight">Eight</div>
<div class="Nine">Nine</div>
<div class="Ten">Ten</div>
* {box-sizing: border-box;}
.outergrid
{
display:grid;
max-width: 540px;
margin: 0 auto;
grid-template-columns: repeat(4, auto);
grid-template-rows: repeat(3, auto);
gap: 5px 5px;
}
.outergrid > div
{
border: 2px solid rgb(233,171,88);
border-radius: 5px;
background-color: rgba(233,171,88,.5);
padding: 1em;
color: #d9480f;
word-break: break-word;
}
Thanks

Related

CSS Grid: column-gap forces parent to overflow

I want to achieve 12 column grid behavior similar to what Bootstrap has,
but using CSS grids.
I need to have a fixed gaps in pixels
And have a 12 column grid, so I can decide how to place the children.
I'm facing the issue, that combination of grid-template-columns and column-gap doesn't shrink the columns on a smaller screens, but cause horizontal overflow on a screen.
How can I achieve expected behavior with shrinking without reducing the number of columns and keeping the gap in pixels.
DEMO:
.parent {
max-width: 300px;
height: 500px;
overflow: auto;
border: 1px solid blue;
}
.box {
grid-column: span 6 / span 6;
background: red;
height: 40px;
}
.grid {
display: grid;
grid-template-columns: repeat(12, minmax(0, 1fr));
gap: 40px;
}
<div class="parent">
<div class="grid">
<div class="box"></div>
<div class="box"></div>
</div>
</div>

How can I enforce a grid width despite gaps pushing it beyond that width?

I just burnt myself trying to mimic a bootstrap-like 12-column layout using css grids. The issue I'm having is that grid content seem to have an inherent minimum width based on the column gap.
Please consider this code:
.container {
width: 300px;
margin-top: 20px;
}
.grid {
height: 100%;
display: grid;
background-color: rgba(0, 255, 0, 0.5);
grid-template-columns: repeat(12, 1fr);
gap: 40px;
}
.col {
outline: 1px dotted red;
background: rgba(0, 0, 255, 0.5);
}
.col-3 {
grid-column: 3 span / 3 span;
}
.col-4 {
grid-column: 4 span / 4 span;
}
.col-5 {
grid-column: 5 span / 5 span;
}
<div class="container">
<div class="grid">
<div class="col col-3">
Column 1
</div>
<div class="col col-4">
Column 2
</div>
<div class="col col-5">
Column 3
</div>
</div>
</div>
The container width is 300px yet the grid items span over 440px. I suppose this behavior could make sense since the grid gap is 40px and there are 11 gaps (40px*11=440px).
So in this situations there are two conflicting constraints – the grid should be 300px yet the gap between each column should be 40px. Now the latter constraint takes precedence over the first one. Is there any way to have the first constraint take precedence over the second one instead?
Here's an example JSFiddle.

HTML table cell column mixing fixed widths + percentages

I want to do something very basic, a table with 4 columns: 2 columns should be 50px each, the other 2 columns should take 50% of the remaining space each.
I'm surprised to find out that calc() does not work for setting width on table cells. So doing something like td { width: calc(50% - 100px); } is not a possibility.
Is there a way to achieve this with the table element or is using another layout method like flexbox the only choice?
You could use a grid layout with grid-template-columns
grid-template-columns: 50px 50px 1fr 1fr;
Defines 4 columns in your grid which represent (respectively) 50px, 50px and 1fr takes one fraction of the remaining space (twice)
.grid {
display: grid;
grid-template-columns: 50px 50px 1fr 1fr;
grid-gap: 1px;
}
.col {
height: 100px;
background-color: red;
}
.col:nth-child(2) {
background-color: yellow;
}
.col:nth-child(3) {
background-color: teal;
}
.col:nth-child(4) {
background-color: navy;
}
<div class="grid">
<div class="col"></div>
<div class="col"></div>
<div class="col"></div>
<div class="col"></div>
</div>
Width calculation for tables is a bit clunky, but can be improved by using table-layout: fixed because then cell widths will no longer be calculated based on what's inside the cells. And then you may not even need calc() anymore, although you definitely can.
It should also be noted that a table by default takes up the least width possible, it usually gets better if we tell the table to use 100% width (or whatever is needed in your case).
width: 100% combined with table-layout: fixed and no calc() gives the following results:
table {
width: 100%;
table-layout: fixed;
}
td {
background: #eee;
height: 70px;
}
td.fixed {
width: 50px;
}
td.rest {
width: 50%;
background: #fca;
}
<table>
<tbody>
<tr>
<td class="fixed">1</td>
<td class="fixed">234</td>
<td class="rest">a</td>
<td class="rest">bcd efg</td>
</tr>
</tbody>
</table>
You can use a grid system (Bootstrap) that can design table, It's a sample
<div class="container">
<div class="row">
<div class="col">
1 of 3
</div>
<div class="col-6">
2 of 3 (wider)
</div>
<div class="col">
3 of 3
</div>
</div>
<div class="row">
<div class="col">
1 of 3
</div>
<div class="col-5">
2 of 3 (wider)
</div>
<div class="col">
3 of 3
</div>
</div>
</div>

Prevent content from expanding or overflowing column

I am new to CSS grid and tried hard but no luck, I am creating a printable format for A4 paper,and have setup fixed sizes for the columns. The content of the column "UNIT" in the first row (excluding Header row) is spanned/expanded to the next column whenever VALUE entered exceeds the width/border. I want the VALUE (i.e "UnitName12345678") not to cross the border but move to the next line in the same column. Also in minmax(50px , max-content) 50px is applied to only the HEADER row and what I am missing in to apply that to all the rows.
This Container will be having multiple rows generated dynamically.
Present output:
Expected output:
Code Pen : https://codepen.io/thaslim123/pen/gyQwmm
body {
margin: 0px;
}
.printcontainertable {
display: inline-grid;
grid-template-rows: minmax(50px, max-content);
grid-template-columns: 100px 500px 100px 100px 100px 100px;
width: 1150px;
padding: 10px;
}
.printcontainertable div {
border: 1px solid black;
text-align: center;
}
<div class="printcontainertable">
<div> SL.No</div>
<div> Product name</div>
<div> Unit</div>
<div> Qty</div>
<div> Price</div>
<div> total</div>
<div> 1. </div>
<div> Apple </div>
<div>UnitName12345678</div>
<div>10</div>
<div> 100.00 </div>
<div> 1000.00 </div>
<div> 2. </div>
<div> Orange </div>
<div>UnitName</div>
<div>10</div>
<div> 100.00 </div>
<div> 1000.00 </div>
</div>
PS: As I will be having fixed HEADER and FOOTER container on top and bottom of the above container (i.e .printcontainertable), How can I fix a static Height for the same. Kindly Suggest me if any other better way to implement it in GRID.
Alright, I do think there are some other things that can be improved depeniding on exactly what you need (semantics, structure, etc.) the main issue regarding the word that exceeds the border can be fixed by applying word-break: break-word to the item that contains the text.
body {
margin: 0px;
}
.printcontainertable {
display: inline-grid;
grid-template-rows: minmax(50px, max-content);
grid-template-columns: 100px 500px 100px 100px 100px 100px;
width: 1150px;
padding: 10px;
}
.printcontainertable div {
border: 1px solid black;
text-align: center;
}
.unitname {
word-break: break-word;
}
<div class="printcontainertable">
<div> SL.No</div>
<div> Product name</div>
<div> Unit</div>
<div> Qty</div>
<div> Price</div>
<div> total</div>
<div> 1. </div>
<div> Apple </div>
<div class="unitname">UnitName12345678</div>
<div>10</div>
<div> 100.00 </div>
<div> 1000.00 </div>
<div> 2. </div>
<div> Orange </div>
<div>UnitName</div>
<div>10</div>
<div> 100.00 </div>
<div> 1000.00 </div>
</div>
I want the VALUE (i.e "UnitName12345678") not to cross the border but move to the next line in the same column.
Then allow the unbroken line of text to break into multiple lines. Use the overflow-wrap property.
Add this to your code:
.printcontainertable div {
overflow-wrap: break-word;
}
Also in minmax(50px , max-content), 50px is applied to only the HEADER row and what I am missing is to apply that to all the rows.
You're using grid-template-rows. This creates explicit rows, meaning rows that you define.
So when you say this:
grid-template-rows: minmax(50px , max-content);
...you're defining only one row with that rule.
You need to use grid-auto-rows, which applies to implicit rows, which is what you need when rows are generated dynamically.
Make this adjustment to your code:
.printcontainertable {
display: inline-grid;
/* grid-template-rows: minmax(50px , max-content); */
grid-auto-rows: minmax(50px , max-content); /* new */
grid-template-columns: 100px 500px 100px 100px 100px 100px;
width:1150px;
padding:10px;
}
.printcontainertable {
display: inline-grid;
/* grid-template-rows: minmax(50px , max-content); */
grid-auto-rows: minmax(50px, max-content); /* new */
grid-template-columns: 100px 500px 100px 100px 100px 100px;
width: 1150px;
padding: 10px;
}
.printcontainertable div {
overflow-wrap: break-word; /* new */
border: 1px solid black;
text-align: center;
}
body {
margin: 0px;
}
<div class="printcontainertable">
<div> SL.No</div>
<div> Product name</div>
<div> Unit</div>
<div> Qty</div>
<div> Price</div>
<div> total</div>
<div> 1. </div>
<div> Apple </div>
<div>UnitName12345678</div>
<div>10</div>
<div> 100.00 </div>
<div> 1000.00 </div>
<div> 2. </div>
<div> Orange </div>
<div>UnitName</div>
<div>10</div>
<div> 100.00 </div>
<div> 1000.00 </div>
</div>

CSS Grid Template Columns Repeat No More Than X Times

I have a layout in which multiple items will be aligned in a grid. Let's use the following as an example:
.grid-container {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-gap: 20px;
}
.grid-item {
display: block;
width: 100%;
background-color: purple;
color: white;
text-align: center;
padding: 30px 5px;
}
<div class="grid-container">
<div class="grid-item">Item</div>
<div class="grid-item">Item</div>
<div class="grid-item">Item</div>
<div class="grid-item">Item</div>
<div class="grid-item">Item</div>
<div class="grid-item">Item</div>
<div class="grid-item">Item</div>
<div class="grid-item">Item</div>
<div class="grid-item">Item</div>
</div>
In the above code, the grid will repeat 3 columns per row and each item will expand to 1/3 of the row width. The problem is that in a responsive situation, the grid will always repeat 3 columns.
If I change the repeat value to auto-fit and adjust the column sizing to use minmax I can control how the page scales down and reduce the col width and count to some sane value. So adjusted code would look something like this:
.grid-container {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px,1fr));
grid-gap: 20px;
}
.grid-item {
display: block;
width: 100%;
background-color: teal;
color: white;
text-align: center;
padding: 30px 5px;
}
<div class="grid-container">
<div class="grid-item">Item</div>
<div class="grid-item">Item</div>
<div class="grid-item">Item</div>
<div class="grid-item">Item</div>
<div class="grid-item">Item</div>
<div class="grid-item">Item</div>
<div class="grid-item">Item</div>
<div class="grid-item">Item</div>
<div class="grid-item">Item</div>
</div>
This works well scaling down, but here is where I am having problems - I want to cap the number of cols at 3 when the page scales up. Ideally, I would like to use minmax in the repeat directive like this:
grid-template-columns: repeat( minmax(1, 3), minmax(300px, 1fr) );
but of course this doesn't work. How can I limit repeat to 3 columns while still maintaining my downscale settings with auto-fit?
I don't think you can set a max-limit on the number of columns using auto-fit or auto-fill. By definition, they will create as many tracks as can fit in the container without overflowing:
§ 7.2.2.2. Repeat-to-fill: auto-fill and auto-fit
repetitions
When auto-fill [or auto-fit] is given as the repetition number ...
then the number of repetitions is the largest possible positive
integer that does not cause the grid to overflow its grid container.
And you can't set the max value of the minmax() function to 30%, because then you run into the same problem you had in your first example:
grid-template-columns: repeat(3, 1fr)
Namely, the column tracks become fixed on all screen sizes, and the layout is not responsive.
I understand that you're looking for a solution that doesn't require media queries. But if you want to use grid layout, I think media queries may be your best bet.
Otherwise, consider flex layout:
jsFiddle demo
.grid-container {
display: flex;
flex-wrap: wrap;
}
.grid-item {
width: 30%;
min-width: 300px;
flex-grow: 1;
background-color: teal;
color: white;
text-align: center;
padding: 30px 5px;
border: 5px solid white;
}
* {
box-sizing: border-box;
}
<div class="grid-container">
<div class="grid-item">Item</div>
<div class="grid-item">Item</div>
<div class="grid-item">Item</div>
<div class="grid-item">Item</div>
<div class="grid-item">Item</div>
<div class="grid-item">Item</div>
<div class="grid-item">Item</div>
<div class="grid-item">Item</div>
<div class="grid-item">Item</div>
</div>
If you go the flex route, then read this post, too:
Targeting flex items on the last row
if I understand correctly what you can do is set a media query for larger screens. Lets say you want to show a 3 column grid for screens over 992px you can use something like this
#media only screen and (min-width: 992px){
.grid-container{
grid-template-columns: repeat(3, 1fr);
}
}
Let me know if that helps you! check it here https://codepen.io/anon/pen/Krzbmz
I solved a similar issue by setting max-width to the grid. I had my columns as repeat(auto-fit, 150px). I wanted a max number of columns as x4 with 50px gap. So max-width of grid set to 800px.