Empty overlapping css grid cell prevents clicks in Firefox and Edge - html

In one page of our app we have a grid with two cells stacked one on top of the other.
On Chrome the middle textbox in the grid shown below is clickable, but in Firefox and Edge(17) it cannot be clicked.
I'm curious about which browser has the bug or whether this is undefined behaviour?
More immediately though is there a workaround for Firefox?
Thanks.
.grid {
display: grid;
align-items: stretch;
justify-items: stretch;
grid-template-rows: [first] repeat(2, minmax(auto, auto)) [last];
}
input {
width: 100%;
}
.a {
grid-area: 1 / 1 / span 1 / span 4;
}
.b {
grid-area: 1 / 5 / span 1 / span 4;
}
.c {
grid-area: 1 / 5 / span 1 / span 4;
}
.d {
grid-area: 1 / 9 / span 1 / span 4;
}
<div class="grid">
<div class="a">
<input>
</div>
<div class="b">
<input>
</div>
<div class="c">
</div>
<div class="d">
<input>
</div>
</div>
Stackblitz link: https://stackblitz.com/edit/js-pukd5g?file=index.html

you can reset pointer-events to allow clicking through an element, or reset position to bring an element on top of static elements:
pointer-events:
.grid {
display: grid;
align-items: stretch;
justify-items: stretch;
grid-template-rows: [first] repeat(2, minmax(auto, auto)) [last];
}
input {
width: 100%;
}
.a {
grid-area: 1 / 1 / span 1 / span 4;
}
.b {
grid-area: 1 / 5 / span 1 / span 4;
}
.c {
grid-area: 1 / 5 / span 1 / span 4;
pointer-events:none;/* here it won't catch mouse events */
}
.d {
grid-area: 1 / 9 / span 1 / span 4;
}
<div class="grid">
<div class="a">
<input>
</div>
<div class="b">
<input>
</div>
<div class="c">
</div>
<div class="d">
<input>
</div>
</div>
position
.grid {
display: grid;
align-items: stretch;
justify-items: stretch;
grid-template-rows: [first] repeat(2, minmax(auto, auto)) [last];
}
input {
width: 100%;
position:relative;/* will be at front of static positionned elements */
}
.a {
grid-area: 1 / 1 / span 1 / span 4;
}
.b {
grid-area: 1 / 5 / span 1 / span 4;
}
.c {
grid-area: 1 / 5 / span 1 / span 4;
}
.d {
grid-area: 1 / 9 / span 1 / span 4;
}
<div class="grid">
<div class="a">
<input>
</div>
<div class="b">
<input>
</div>
<div class="c">
</div>
<div class="d">
<input>
</div>
</div>

I'm not sure if it's a bug or just a difference in rendering behavior among browsers.
But a simple workaround is to layer the clickable element over the empty element using z-index.
Add this to your code:
.b {
z-index: 1;
}
.grid {
display: grid;
grid-template-rows: [first] repeat(2, minmax(auto, auto)) [last];
}
input {
width: 100%;
}
.a {
grid-area: 1 / 1 / span 1 / span 4;
}
.b {
grid-area: 1 / 5 / span 1 / span 4;
z-index: 1; /* new */
}
.c {
grid-area: 1 / 5 / span 1 / span 4;
}
.d {
grid-area: 1 / 9 / span 1 / span 4;
}
<div class="grid">
<div class="a">
<input>
</div>
<div class="b">
<input>
</div>
<div class="c">
</div>
<div class="d">
<input>
</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>

Irregular grid lines on one part of css grid

I've got a really simple grid set up in CSS, but when I look at the grid lines in the inspector there's a strange irregularity at the bottom. I can't understand why this exists when the rest of the grid lines are all regular.
There's no special styling on div-4, it's just the same as the rest. Is it something to do with the margins produced by the h3 tag?
HTML
<div class="left-sidebar-grid">
<div class="div1">
<h3>Div1</h3>
</div>
<div class="div2">
<h3>Div2</h3>
</div>
<div class="div3">
<h3>Div3</h3>
</div>
<div class="div4">
<h3>Div4</h3>
</div>
</div>
CSS
.left-sidebar-grid {
height: 100%;
display: grid;
grid-template-columns: 1fr;
grid-template-rows: repeat(8, 1fr);
grid-gap: 16px;
}
.div1 { grid-area: 1 / 1 / 2 / 2; }
.div2 { grid-area: 2 / 1 / 4 / 2; }
.div3 { grid-area: 4 / 1 / 10 / 2; }
.div4 { grid-area: 10 / 1 / 11 / 2; }
You defined only 8 explicit rows and you have placed the div4 starting at line 10 which will create 2 extra rows so you will end up with 10 rows in total where only 8 are sized using the 1fr and 2 will have an auto size: the empty one you see and the one where you placed div4.
To avoid this use grid-auto-rows:1fr instead of your template in order to make sure all the rows are sized the same way:
.left-sidebar-grid {
height: 100%;
display: grid;
grid-template-columns: 1fr;
grid-auto-rows: 1fr;
grid-gap: 16px;
}
.div1 { grid-area: 1 / 1 / 2 / 2; }
.div2 { grid-area: 2 / 1 / 4 / 2; }
.div3 { grid-area: 4 / 1 / 10 / 2; }
.div4 { grid-area: 10 / 1 / 11 / 2; }
<div class="left-sidebar-grid">
<div class="div1">
<h3>Div1</h3>
</div>
<div class="div2">
<h3>Div2</h3>
</div>
<div class="div3">
<h3>Div3</h3>
</div>
<div class="div4">
<h3>Div4</h3>
</div>
</div>
You can also simplify your code like below:
.left-sidebar-grid {
display: grid;
grid-template-columns: 1fr;
grid-auto-rows: 1fr;
grid-gap: 16px;
}
.div1 {
grid-row:span 1;
}
.div2 {
grid-row:span 2;
}
.div3 {
grid-row:span 6;
}
.div4 {
grid-row:span 1;
}
<div class="left-sidebar-grid">
<div class="div1">
<h3>Div1</h3>
</div>
<div class="div2">
<h3>Div2</h3>
</div>
<div class="div3">
<h3>Div3</h3>
</div>
<div class="div4">
<h3>Div4</h3>
</div>
</div>

CSS Grid layout: specify grid position with less typing?

(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>

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;
}

Grid item not aligning as expected

I am trying to get the content of item to be in the middle column, but it does not seem to be moving.
.home-grid-container {
display: grid;
grid-template-columns: auto;
grid-template-rows: 0.10fr 0.98fr auto;
height: 100vh;
}
.home-header {
grid-column: 1 / span 3;
grid-row: 1 / span 1;
background: #3f51b5;
}
.home-main {
grid-column: 1 / span 3;
grid-row: 2 / span 3;
background: #81d4fa;
}
.item {
grid-column: 2 / span 1;
grid-row: 2 / span 3;
}
.home-footer {
grid-column: 1 / span 3;
grid-row: 5 / span 1;
background: #3f51b5;
div {
text-align: center;
margin: 2vh;
}
}
<div class="home-grid-container">
<div class="home-header">
<h1>
<img src="/src/imgs/sitelogo.png" />
</h1>
</div>
<div class="home-main">
<div class="item">
Simple, Fast, Powerful
<input type="button" value="100% Free" />
</div>
</div>
<div class="home-footer">
<div>All Rights Reserved</div>
</div>
</div>
https://css-tricks.com/snippets/css/complete-guide-grid/
The elements you want to center are descendants, but not children, of the grid container.
Because grid layout only extends between parent and child elements, the .item element is out of scope and will not accept grid properties.
But these elements are inline-level children of a block container, which means that text-align: center will work.
.home-grid-container {
display: grid;
grid-template-columns: auto;
grid-template-rows: 0.10fr 0.98fr auto;
height: 100vh;
}
.home-header {
grid-column: 1 / span 3;
grid-row: 1 / span 1;
background: #3f51b5;
}
.home-main {
grid-column: 1 / span 3;
grid-row: 2 / span 3;
background: #81d4fa;
}
.item {
grid-column: 2 / span 1;
grid-row: 2 / span 3;
text-align: center; /* NEW */
}
.home-footer {
grid-column: 1 / span 3;
grid-row: 5 / span 1;
background: #3f51b5;
}
<div class="home-grid-container">
<div class="home-header">
<h1>
<img src="http://i.imgur.com/60PVLis.png" width="50" height="50" alt="">
</h1>
</div>
<div class="home-main">
<div class="item">
Simple, Fast, Powerful
<input type="button" value="100% Free" />
</div>
</div>
<div class="home-footer">
<div>All Rights Reserved</div>
</div>
</div>
jsFiddle demo
If you want to use the grid for a child of your container, you can always just inherit the same properties.
.home-grid-container {
display: grid;
grid-template-columns: auto;
grid-template-rows: 0.10fr 0.98fr auto;
height: 100vh;
}
.home-header {
grid-column: 1 / span 3;
grid-row: 1 / span 1;
background: #3f51b5;
}
.home-main {
grid-column: 1 / span 3;
grid-row: 2 / span 3;
background: #81d4fa;
/* inherit the container-grid setup */
display: grid;
grid-template-columns: inherit;
grid-template-rows: inherit;
}
.item {
grid-column: 2 / span 1;
grid-row: 2 / span 3;
}
.home-footer {
grid-column: 1 / span 3;
grid-row: 5 / span 1;
background: #3f51b5;
div {
text-align: center;
margin: 2vh;
}
}
<div class="home-grid-container">
<div class="home-header">
<h1>
<img src="https://dummyimage.com/200x50/cccccc/ffffff.png" />
</h1>
</div>
<div class="home-main">
<div class="item">
Simple, Fast, Powerful
<input type="button" value="100% Free" />
</div>
</div>
<div class="home-footer">
<div>All Rights Reserved</div>
</div>
</div>
As others have pointed out, since the item element isn't a direct child of the grid container - you can't apply grid properties to it.
Obviously, to fix this you could pull the item out of the home-main div and make it a direct child of the grid - but I'm guessing that that's not a viable solution here :)
Grid Layout Module Level 2 - Subgrids are supposed to solve this problem.
Subgrid is currently only a draft spec, but fwiw, in your case you would do something like:
.home-main {
display: subgrid;
grid-column: span 3;
}
Nevertheless, there actually is a way to pull this off:
display: contents (caniuse)
From Caniuse:
display: contents causes an element's children to appear as if they
were direct children of the element's parent, ignoring the element
itself. This can be useful when a wrapper element should be ignored
when using CSS grid or similar layout techniques.
So in order for the grid placement properties to work on the item, you could simply add display: contents; to home-main (currently working in Firefox)
(NB: This will obviously render the grid properties on home-main useless - but then again - they aren't necessary to place the item)
.home-main {
display: contents;
...
}
.home-grid-container {
display: grid;
grid-template-columns: auto;
grid-template-rows: 0.10fr 0.98fr auto;
height: 100vh;
}
.home-header {
grid-column: 1 / span 3;
grid-row: 1 / span 1;
background: #3f51b5;
}
.home-main {
/*grid-column: 1 / span 3;
grid-row: 2 / span 3; */
display: contents;
background: #81d4fa;
}
.item {
grid-column: 2 / span 1;
grid-row: 2 / span 3;
background: salmon;
}
.home-footer {
grid-column: 1 / span 3;
grid-row: 5 / span 1;
background: #3f51b5;
}
.home-footer div {
text-align: center;
margin: 2vh;
}
<div class="home-grid-container">
<div class="home-header">
<h1>
<img src="/src/imgs/sitelogo.png" />
</h1>
</div>
<div class="home-main">
<div class="item">
Simple, Fast, Powerful
<input type="button" value="100% Free" />
</div>
</div>
<div class="home-footer">
<div>All Rights Reserved</div>
</div>
</div>