CSS Grid layout: specify grid position with less typing? - html

(I am trying to convert this data entry page from a very primitive CSS/HTML "table" layout to something a bit better, using CSS Grid layout).
In line with common practice, it seems, I've made it 12 columns wide. Each entry field has a label, of the same width. In other words my CSS is currently very repetitive:
.container {
display: grid;
grid-template-columns: repeat(12, minmax(0, 1fr));
grid-gap: 10px;
}
#SigNameLabel {
grid-column: 1 / 13;
grid-row: 2;
}
#SignatureName {
grid-column: 5 / 13;
grid-row: 2;
}
#PaymentNoLabel {
grid-column: 1 / 13;
grid-row: 3;
}
#PaymentNo {
grid-column: 5 / 13;
grid-row: 3;
}
#CurrencyLabel {
grid-column: 1 / 13;
grid-row: 4;
}
#Currency {
grid-column: 5 / 13;
grid-row: 4;
}
* {
border: 1px solid #999;
}
<div class="container">
<div id='SigNameLabel' class='unselectable'>Signature name:</div>
<div id='SignatureName' class='unselectable dataField single-line'></div>
<div id='PaymentNoLabel' class='unselectable'>Payment No:</div>
<div id='PaymentNo' class='unselectable dataField single-line'></div>
<div id='CurrencyLabel' class='unselectable'>Currency:</div>
<div id='Currency' class='dataField single-line'></div>
</div>
Short of using JS to "create" the layout in automated fashion, i.e. by analysing the DIVs in the container, is there any way to make the CSS less cumbersome and explicit, more just "taking its lead from" what the HTML does?
For example, I have had to give a specific ID to each of the labels here: when they each sat in their own TD they didn't need that. Is there any way each such label DIV could be given a class, say left-hand-column, and somehow they could all have grid-column: 1 / 13 applied to them, and somehow the same grid-row as the data field DIV to their right?

You can simplify your code like below. And you don't necessarily need 12 columns
.container {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
grid-gap: 10px;
}
.container>*:nth-child(even) {
grid-column: span 2;
border:1px solid;
}
.container>*:nth-child(odd) {
/* Not sure if you need this but it will allow
the full width of the grid like your code grid-column: 1 / 13;
width:calc(300% + 2*10px); */
border:1px solid red;
}
<div class="container">
<div id='SigNameLabel' class='unselectable'>Signature name:</div>
<div id='SignatureName' class='unselectable dataField single-line'></div>
<div id='PaymentNoLabel' class='unselectable'>Payment No:</div>
<div id='PaymentNo' class='unselectable dataField single-line'></div>
<div id='CurrencyLabel' class='unselectable'>Currency:</div>
<div id='Currency' class='dataField single-line'></div>
</div>

Related

Nested CSS grid acting strangely

If you look at the nested grid in Firefox and look at the grid display you will see the four separate nested grids each with 1 row and 12 columns. However, if you look at the CSS file you can only assign the element "main-services-text", "main-banner-text", etc., by treating it as a single 4 row grid.
So my question is, is this the way it should work or is it a bug. Also should I use it?
.main-grid {
display: grid;
grid-template-columns: repeat(12, 1fr);
grid-template-rows: 100px 100px 100px 100px;
}
/* Step 1a assign the main elements "" to the MAIN Grid*/
.main-banner {
grid-column: 1 /13;
grid-row: 1 / 2;
background-color: cornflowerblue;
}
.main-services {
grid-column: 1 /13;
grid-row: 2 / 3;
background-color: lightcyan;
}
.main-why-us {
grid-column: 1 /13;
grid-row: 3 / 4;
background-color: orange;
}
.main-who-are-we {
grid-column: 1 /13;
grid-row: 4 / 5;
background-color: chocolate;
}
/* Step 2: Set up individual nested GRIDS*/
main section {
display: grid;
color: olive;
grid-template-columns: repeat(12, 1fr);
grid-template-rows: 100px;
}
/* Step 2 assign elements to the nested grids */
.main-banner-text {
grid-column: 3 / 5;
grid-row: 1 / 2;
}
.main-services-text {
grid-column: 6 / 9;
grid-row: 2 / 3;
}
.main-why-us-text {
grid-column: 10 / 13;
grid-row: 3 / 4;
}
.main-who-are-we-text {
grid-column: 9 / 10;
grid-row: 4 / 5;
}
<main class="main-grid">
<section class="main-banner">Banner</section>
<p class="main-banner-text">Main banner text</p>
<section class="main-services">Services</section>
<p class="main-services-text">Main services text</p>
<section class="main-why-us">Why Us</section>
<p class="main-why-us-text">Main Why us text</p>
<section class="main-who-are-we">Who are we</section>
<p class="main-who-are-we-text">Main who are we text</p>
</main>

CSS-Grid: How to align 2 left, one large in the middle and two right?

I am struggling to get what I want and I am not sure if its even possible.
Tried everything I got, showing some code below
section {
display: grid;
grid-template-columns: auto auto auto auto;
}
section > *{
border: 1px solid red;
}
section > h1{
grid-row: 1;
grid-column: 2 / 3;
}
section > h2{
grid-row: 2;
grid-column: 2 / 3;
}
section > img{
grid-row: 1/2;
grid-column: 1 / 3;
width: 20%;
}
section > span{
grid-row: 1;
grid-column: 3 / 3;
}
<div>
<section>
<h1>HEADING</h1>
<img src=img.png alt="">
<h2>HEADING 2</h2>
<span>11:44</span>
</section>
<section>
<h1>HEADING</h1>
<img src=img.png alt="">
<h2>HEADING 2</h2>
<span>11:44</span>
</section>
...
</div>
I want the image to appear left, using the upper and lower cell, so full height.
I want the h1 to use the upper center space.
I want the h2 to use the lower center space.
i want the span to use the upper right space.
The lower right space should be combined with the lowercenter in case the content of lowercenter overflows.
You were almost there but there were some issues.
You defined a four column grid but your description only requires three.
grid-template-columns: auto 1fr 1fr; /* (seems more appropriate) /*
* {
margin: 0 !important;
}
section {
display: grid;
grid-template-columns: auto 1fr 1fr;
}
section>* {
border: 1px solid red;
}
section>h1 {
grid-row: 1;
grid-column: 2 / 3;
}
section>h2 {
grid-row: 2;
grid-column: 2 / 4;
/* span 2 columns*/
}
section>img {
grid-row: 1 / 3;
/* span 2 rows */
}
section>span {
grid-row: 1;
}
<section>
<h1>HEADING</h1>
<img src="https://placekitten.com/200/200" alt="">
<h2>HEADING 2</h2>
<span>11:44</span>
</section>
I want the h2 to use the lower center space.
I want the span to use the upper right space.
The lower right space should be combined with the lowercenter in case the content of lowercenter overflows.
The h2 area is supposed to span 2 columns so we extend it out into column 3.

Overlapping Photos with CSS Grid

https://codepen.io/nhn34/pen/zVQyWG
I'm trying to overlap 3 photos using CSS Grid. This is the outcome that I want:
desired outcome
I tried following these tutorials that both uses the same method but they didn't work for me: https://www.superhi.com/video/overlapping-layouts-with-css-grid,
https://www.youtube.com/watch?v=sZJrcOfBaNY
The results that I get looks like in CodePen and I don't know where I did wrong!
These are my code:
section {
display: grid;
grid-template-columns: repeat(4, 1fr);
div:first-child {
grid-column: 2 / span 3;
}
div:nth-child(2) {
grid-column: 1 / span 2;
}
div:last-child {
grid-column: 2 / span 2;
}
}
<section>
<div>
<img src="img/cancer/face1.svg" alt="face1">
</div>
<div>
<img src="img/cancer/cancer.jpg" alt="cancer">
</div>
<div>
<img src="img/cancer/point1.svg" alt="point1">
</div>
</section>
you only missed specifing grid-row property
grid-row: 1;
good luck

How to reverse the css grid columns order?

I want to be able to reverse the order of columns (the 2 small to the left, the big one right). I've tried several solutions but didn't find one that works.
Here's the code:
.images-block-box{
display: grid;
grid-gap: 16px;
grid-template-columns: 708fr 340fr;
& > div:first-child{
grid-row: span 2;
}
&.reverse{
grid-template-columns: 340fr 708fr;
& > div:first-child{
order: 2; // doesn't work (I want to place the first item at the end of the 3)
}
}// reverse
}// images-block-box
Note that I really want to reverse the order of the columns themselves, not just their dimensions.
Simply adjust grid-column and conisder grid-auto-flow:dense; to allow the next elements to be placed before:
.grid {
display: grid;
grid-gap: 16px;
grid-template-columns: 2fr 1fr;
grid-auto-flow:dense;
margin:5px;
}
.grid div {
min-height: 50px;
border: 1px solid;
}
.grid div:first-child {
grid-row: span 2;
}
.grid.reverse {
grid-template-columns: 1fr 2fr;
}
.grid.reverse div:first-child {
grid-column:2;
}
<div class="grid">
<div></div>
<div></div>
<div></div>
</div>
<div class="grid reverse">
<div></div>
<div></div>
<div></div>
</div>
dense
If specified, the auto-placement algorithm uses a “dense” packing algorithm, which attempts to fill in holes earlier in the grid if smaller items come up later. This may cause items to appear out-of-order, when doing so would fill in holes left by larger items.ref
Another option is to place the big box to the last column by using grid-column-end: -1 - see demo below:
.images-block-box {
display: grid;
grid-gap: 16px;
grid-template-columns: 708fr 340fr;
grid-template-rows: 100px 100px;
grid-auto-flow: column;
}
.images-block-box>div {
border: 1px solid;
}
.images-block-box>div:first-child {
grid-row: span 2;
}
.images-block-box.reverse {
grid-template-columns: 340fr 708fr;
}
.images-block-box.reverse>div:first-child {
grid-column-end: -1;
}
<div class="images-block-box">
<div></div>
<div></div>
<div></div>
</div>
<br/>
<div class="images-block-box reverse">
<div></div>
<div></div>
<div></div>
</div>
grid-column-end
<integer> && <custom-ident>?
Contributes the nth grid line to the grid
item’s placement. If a negative integer is given, it instead counts in
reverse, starting from the end edge of the explicit grid.
Since there are 2 answers that could be marked as accepted (thanks to #kukkuz and #Temani Afif) I'm posting here a sum up. The working techniques pointed out till now are:
grid-auto-flow: dense (container) + grid-column: 2 (first-child)
grid-auto-flow: column (container) + grid-column-end: -1 (first-child)
The rest of the code remains the same. Please take a look at the related answers.
Both are currently working well (at least in major/modern browsers).
Then Maybe You can use a different approach
.grid {
display: grid;
grid-template-columns: 5fr 2fr;
grid-template-rows: 1fr 1fr;
height: 500px;
grid-gap: 2rem;
}
.one {
background-color: red;
grid-row: 1 / 3;
}
.two {
background-color: green;
}
.three {
background-color: blue;
}
.reverse > .one {
grid-column: 2 / 3;
grid-row: 2 / 3;
}
.reverse > .three {
grid-column: 1 / 2;
grid-row: 1 / 3;
}
<h1>Without Reverse</h1>
<div class="grid">
<div class="one"></div>
<div class="two"></div>
<div class="three"></div>
</div>
<h1>With Reverse</h1>
<div class="grid reverse">
<div class="one"></div>
<div class="two"></div>
<div class="three"></div>
</div>

Css grid, large size on some cards, how to place them like this

I'm using grid for this layout and I'm halfway through. As you can see number 10,20,30,40,50 gets placed on the same spot (I place them there). I would like to have my layout as from 1 to 10 are
Large on the left (1,11,21,31,41...), 4 small on the right
Large on the right (10,20,30,40...), 4 small on the left
NOTE, this list can contain from 40-100 items, so using fixed positions to place it there would not be an option. Also the making nr 6 large and changing the order does not work either due to sorting.
Hope it's clear what I'm trying to do here.
.layout-scale {
display: grid;
grid-template-columns: repeat(4, 25%);
grid-gap: 1rem;
}
.layout-scale__items {
background-color: aqua;
min-height: 10rem;
}
.layout-scale__items:nth-child(10n + 1) {
background-color: deeppink;
grid-column: span 2;
grid-row: span 2;
}
.layout-scale__items:nth-child(10n + 10) {
background-color: lime;
grid-column: 3 / span 2;
grid-row: 3 / span 2;
}
<div class="layout-scale">
<div class="layout-scale__items">1</div>
<div class="layout-scale__items">2</div>
<div class="layout-scale__items">3</div>
<div class="layout-scale__items">4</div>
<div class="layout-scale__items">5</div>
<div class="layout-scale__items">6</div>
<div class="layout-scale__items">7</div>
<div class="layout-scale__items">8</div>
<div class="layout-scale__items">9</div>
<div class="layout-scale__items">10</div>
<div class="layout-scale__items">11</div>
<div class="layout-scale__items">12</div>
<div class="layout-scale__items">13</div>
<div class="layout-scale__items">14</div>
<div class="layout-scale__items">15</div>
<div class="layout-scale__items">16</div>
<div class="layout-scale__items">17</div>
<div class="layout-scale__items">18</div>
<div class="layout-scale__items">19</div>
<div class="layout-scale__items">20</div>
<div class="layout-scale__items">21</div>
<div class="layout-scale__items">22</div>
<div class="layout-scale__items">23</div>
<div class="layout-scale__items">24</div>
<div class="layout-scale__items">25</div>
<div class="layout-scale__items">26</div>
<div class="layout-scale__items">27</div>
<div class="layout-scale__items">28</div>
<div class="layout-scale__items">29</div>
<div class="layout-scale__items">30</div>
<div class="layout-scale__items">31</div>
<div class="layout-scale__items">32</div>
<div class="layout-scale__items">33</div>
<div class="layout-scale__items">34</div>
<div class="layout-scale__items">35</div>
<div class="layout-scale__items">36</div>
<div class="layout-scale__items">37</div>
<div class="layout-scale__items">38</div>
<div class="layout-scale__items">39</div>
<div class="layout-scale__items">40</div>
<div class="layout-scale__items">41</div>
<div class="layout-scale__items">42</div>
<div class="layout-scale__items">43</div>
<div class="layout-scale__items">44</div>
<div class="layout-scale__items">45</div>
<div class="layout-scale__items">46</div>
<div class="layout-scale__items">47</div>
<div class="layout-scale__items">48</div>
<div class="layout-scale__items">49</div>
<div class="layout-scale__items">50</div>
</div>
All green boxes start at 3rd row (grid-row: 3 / span 2) so they are in the same place.
Also, if I understood the pattern in your mind, you have to use indexes 1,11,21,.. and indexes 8,18,28,...
Try this:
.layout-scale {
display: grid;
grid-template-columns: repeat(4, 25%);
grid-gap: 1rem;
}
.layout-scale__items {
background-color: aqua;
min-height: 10rem;
}
.layout-scale__items:nth-child(10n + 1) {
background-color: deeppink;
grid-column: span 2;
grid-row: span 2;
}
.layout-scale__items:nth-child(10n + 8) {
background-color: lime;
grid-column: span 2;
grid-row: span 2;
}
I have landed in solving it with "fixed" position on grid-row. I have a loop in scss that generates it for the :nth-child(). The 10 extra classes are worth it compared to the extra markup and css to solve it with a "row" "bootstrap if you will" approach, and even more css for eventually that would be for a fallback solution. For my use case it will not be more than 100 items. If your case use more then 100 items just change the loop times.
$increment: 3;
// change the 10 to your wanted amount
#for $i from 1 through 10 {
.layout-scale__items:nth-child(#{$i*10}) {
grid-row: #{$increment} / span 2;
}
$increment: $increment + 4;
}
My full solution is on jsfiddle (due to internal code editor does not support scss)
<div class="layout-scale">
<div class="layout-scale__items">1</div>
<div class="layout-scale__items">2</div>
<div class="layout-scale__items">3</div>
<div class="layout-scale__items">4</div>
<div class="layout-scale__items">5</div>
<div class="layout-scale__items">6</div>
<div class="layout-scale__items">7</div>
<div class="layout-scale__items">8</div>
<div class="layout-scale__items">9</div>
<div class="layout-scale__items">10</div>
<div class="layout-scale__items">11</div>
...
</div>
.layout-scale {
display: grid;
grid-template-columns: repeat(4, 25%);
grid-gap: 1rem;
}
.layout-scale__items {
background-color: aqua;
min-height: 10rem;
}
.layout-scale__items:nth-child(10n + 1) {
background-color: deeppink;
grid-column: span 2;
grid-row: span 2;
}
.layout-scale__items:nth-child(10n + 10) {
background-color: lime;
grid-column: 3 / span 2;
}
$increment: 3;
#for $i from 1 through 10 {
.layout-scale__items:nth-child(#{$i*10}) {
grid-row: #{$increment} / span 2;
}
$increment: $increment + 4;
}