Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CSS Grid. Hide unused area

Tags:

html

css

css-grid

I have grid-template-areas that builds on known elements, but not all elements can be fetched from the database. If I don’t get something from the database, then I don’t render the html element and I get an empty "dashed" rows with gaps. See the attached picture, empty rows are located under the blue boxes. Is it possible to hide unused areas or remove gaps from them?

Empty row with gaps

*{
 margin: 0;
 padding: 0;
}

.name {
  grid-area: name;
}

.lastname{
  grid-area: lastname;
}

.phone {
  grid-area: phone;
}

.wrapper {
  display: grid;
  grid-gap: 20px;
  grid-template-areas: 
    'name name name lastname lastname lastname'
    'somethingelse somethingelse somethingelse . . .'
    'phone phone phone phone phone phone'
    'email email email email email email';
}
<div class="wrapper">
  <div class="field name">
    <div class="titile">Name</div>
    <div class="description">Antony</div>
  </div>
  <div class="field lastname">
    <div class="titile">Last name</div>
    <div class="description">Lastnamed</div>
  </div>
  <div class="field phone">
    <div class="titile">Phone number</div>
    <div class="description">123 456 789</div>
  </div>
</div>

NOT RELATED TO MY QUESTION

This question is not related to mine, because I don't have empty item. I have empty row without html items with gaps

like image 369
Marty Avatar asked Jul 22 '20 18:07

Marty


People also ask

How to Hide Grid elements in grid template-areas?

You still need to use 'display: none;' or 'visibility: hidden' to hide the elements. The grid-template-areas property cannot hide grid items. It is designed to create grid areas.

How to hide the line numbers in CSS grid-column?

Select Hide line labels to hide the line numbers. You can select Show line names to view the line names instead of numbers. In this example, we have 4 lines with names: left, middle1, middle2 and right. In this demo, orange element spans from left to right, with CSS grid-column: left / right.

How to Hide Grid elements in a media query?

You still need to use 'display: none;' or 'visibility: hidden' to hide the elements. The grid-template-areas property cannot hide grid items. It is designed to create grid areas. But your media query can still be very simple. @media (max-width: 500px) { section:not (.a) { display: none; } }

What is the grid-area property?

Definition and Usage The grid-area property specifies a grid item's size and location in a grid layout, and is a shorthand property for the following properties:


Video Answer


3 Answers

I had the exact same problem a month ago. I didn't have empty borders, because I did not render the blocks I didn't get from the database (I use Angular's *ngIf to not render the blocks which would be empty), so only the excess gaps caused problem. I ended up not using grid-gap, I simply added right and bottom margins to the blocks, so I only got single "gaps", that is margins between blocks. It's OK for now, but it would be nice to have "collapsible grid-gap" :)

Here is my code, after extreme simplification, of course... and note that I use Angular.

HTML:

<div id="container">
  <div id="block-0-0" class="block" *ngIf="data[0][0]">
    <app-block [block-data]="data[0][0]"></app-block>
  </div>
  <div id="block-0-1" class="block" *ngIf="data[0][1]">
    <app-block [block-data]="data[0][1]"></app-block>
  </div>
  <div id="block-1-0" class="block" *ngIf="data[1][0]">
    <app-block [block-data]="data[1][0]"></app-block>
  </div>
  <div id="block-1-1" class="block" *ngIf="data[1][1]">
    <app-block [block-data]="data[1][1]"></app-block>
  </div>
  <!-- etc. -->
</div>

CSS:

div#container {
  display: grid;
  grid-template:
    "block-0-0 block-0-1" auto
    "block-1-0 block-1-1" auto
    /* etc. */
    / 300px 300px;
}

div.block {
  margin: 0 10px 10px 0;
  border: solid 1px gray;
}

div#block-0-0 {
  grid-area: block-0-0;
}

div#block-0-1 {
  grid-area: block-0-1;
}

div#block-1-0 {
  grid-area: block-1-0;
}

div#block-1-1 {
  grid-area: block-1-1;
}

/* etc. */

I'd like to emphasize that this is only a workaround. I'd be happy to see The Solution :)

like image 116
kol Avatar answered Oct 21 '22 07:10

kol


Do you need named template areas?

Could you just define how many columns certain grid items should span?

.name { 
  grid-column: span 3;
}

.lastname {
  grid-column: span 3;
}

.phone { 
  grid-column: span 6;
}

.wrapper {
  gap: 10px;
  display: grid;
  grid-template-columns: repeat(6, 1fr);
}
like image 1
hyperdrive Avatar answered Oct 21 '22 06:10

hyperdrive


So as I wrote in the comments, it seems like when using grid-gap with grid-template-areas, the template-row is being rendered even if there is no content in it, which makes grid-gap apply on it anyways. After digging a bit in the documentation and in the Editor's draft and I didn't see anything we can manipulate how grid-gap works and make it responsive to unused row tracks.

I guess grid-gap need some work, so you can open an issue to w3.org or at least bring it up.

My suggestions for now are:

Option 1

Best solution I can suggest (while still using areas names and grid-template-areas):

There are great alternatives for grid-gap, you can use padding or margin for each cell content, that will result exactly what you want:

*{
 margin: 0;
 padding: 0px;
}

.name {
  grid-area: name;
  margin: 0px 20px 20px 0px
}

.lastname{
  grid-area: lastname;
  margin: 0px 20px 20px 0px
}

.phone {
  grid-area: phone;
  margin: 0px 20px 20px 0px
}

.email {
  grid-area: email;
  margin: 0px 20px 20px 0px
}

.somethingelse {
  grid-area: somethingelse;
  margin: 0px 20px 20px 0px
}

.wrapper {
  display: grid;
  grid-template-areas: 
    'name name name lastname lastname lastname'
    'somethingelse somethingelse somethingelse . . .'
    'phone phone phone phone phone phone'
    'email email email email email email';
}
<div class="wrapper">
  <div class="field name">
    <div class="titile">Name</div>
    <div class="description">Antony</div>
  </div>
  <div class="field lastname">
    <div class="titile">Last name</div>
    <div class="description">Lastnamed</div>
  </div>
  
  
  <div class="field phone">
    <div class="titile">Phone number</div>
    <div class="description">123 456 789</div>
  </div>
  
  
  
</div>

Option 2

Using grid-gap as you want, but without using template-areas, instead render rows and cols depends on the elements that should be rendered.

Notice that in this solution, the position of the divs are important.

*{
 margin: 0;
 padding: 0px;
}

.name {
grid-row: 1fr;
  grid-column: 1 / 2;
}

.lastname{
grid-row: 1fr;
  grid-column: 2 / 3;
}

.phone {
grid-row: 1fr;
  grid-column: 1 / 2;
}

.email {
grid-row: 1fr;
  grid-column: 1 / 2;
}

.somethingelse {
grid-row: 1fr;
  grid-column: 1 / 2;
}

.wrapper {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  grid-gap: 20px;
}
<div class="wrapper">
  <div class="field name">
    <div class="titile">Name</div>
    <div class="description">Antony</div>
  </div>
  <div class="field lastname">
    <div class="titile">Last name</div>
    <div class="description">Lastnamed</div>
  </div>
  
  
  <div class="field phone">
    <div class="titile">Phone number</div>
    <div class="description">123 456 789</div>
  </div>
  
  
  
  
  
</div>

Option 3

This will not behave exactly as you want, but it is something you can check:

I thought about using the grid gap with units relative to the size of the grid (if more rows were generated, the gap between them will be bigger, and if no row will be generated, then the gap will "shrink" relatively).

So you could use percentage as a unit for grid-gap, instead of a fixed gap size.

*{
 margin: 0;
 padding: 0;
}

.name {
  grid-area: name;
}

.lastname{
  grid-area: lastname;
}

.phone {
  grid-area: phone;
}

.email {
  grid-area: email;
}

.somethingelse {
  grid-area: somethingelse;
}

.wrapper {
  display: grid;
  grid-gap: 20px;
  grid-template-areas: 
    'name name name lastname lastname lastname'
    'somethingelse somethingelse somethingelse . . .'
    'phone phone phone phone phone phone'
    'email email email email email email';
}
<div class="wrapper">
  <div class="field name">
    <div class="titile">Name</div>
    <div class="description">Antony</div>
  </div>
  <div class="field lastname">
    <div class="titile">Last name</div>
    <div class="description">Lastnamed</div>
  </div>
  <div class="field phone">
    <div class="titile">Phone number</div>
    <div class="description">123 456 789</div>
  </div>
  
</div>

Hope it helped you out somehow.

like image 1
SomoKRoceS Avatar answered Oct 21 '22 06:10

SomoKRoceS