Dynamically changing the number of rows in a CSS Grid

守給你的承諾、 提交于 2019-12-11 07:44:20

问题


I have a webpage designed using CSS Grid. This is how it looks like -

There are certain cases where I want to remove the Username - CSS Grid User such that the rendered page looks like this -

I am using this in a react/redux project. Based on a variable, I have to show/hide the username of the user.

Thus I want to change the number of rows of the grid, I tried making the class display: none like so

.username {
  display: none;
}

However, all it does is removes the CSS Grid User string, but the row exists, leaving a blank space.

Is there any way where I would be able to change the number of rows/columns dynamically. I don't want to use CSS in JS solutions. I have a plain CSS file that sets styles to the react component.

.layout {
  display: grid;
  grid-template-columns: minmax(200px, auto) minmax(200px, 300px) minmax(900px, auto) minmax(200px, auto);
  grid-template-rows: 60px 60px 60px minmax(700px, auto);
  grid-gap: 5px;
  height: calc(100vh);
}

.navbar {
  grid-column: 1 / -1;
  grid-row: 1 / 2;
  background-color: #3a3f51;
  border-bottom: 1px solid #797d89;
  text-align: center;
  color: aliceblue;
}

.username {
  grid-column: 1 / -1;
  grid-row: 2 / 3;
  background-color: #f7f9f9;
  border-bottom: 1px solid #dee5e7;
  text-align: center;
}

.statement-list {
  grid-column: 2 / 3;
  grid-row: 3 / 5;
  max-height: 600px;
  overflow-y: auto;
}

.title {
  grid-column: 3 / 4;
  grid-row: 3 / 4;
}

.content {
  grid-column: 3 / 4;
  grid-row: 4 / 5;
  overflow-x: auto;
  overflow-y: auto;
}
<body class="layout">
  <div class="navbar">About</div>
  <div class="username">CSS Grid User</div>
  <div class="title">Lorem Ipsum</div>
  <div class="statement-list">
    Phasellus commodo sit amet eros non pharetra. Phasellus consequat augue est, ornare finibus lectus auctor non. Praesent rutrum odio tortor. Proin id massa magna. Phasellus commodo sit amet eros non pharetra. Phasellus consequat augue est, ornare finibus
    lectus auctor non. Praesent rutrum odio tortor. Proin id massa magna.
  </div>
  <div class="content">
    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean laoreet a odio quis commodo. In nisl justo, tincidunt vel aliquet eget, mollis eget lorem. Aenean sit amet nibh eget nunc sodales vestibulum id ac ante. Nullam eleifend sodales ipsum, sed
    porta tellus posuere molestie. Vestibulum congue porta odio sed iaculis. Phasellus varius sodales ullamcorper. Praesent consectetur ante eget turpis pretium, eget sagittis leo volutpat. Aenean posuere, sapien quis placerat pulvinar, lectus est interdum
    dui, at pretium risus sapien et neque. Sed eu fringilla turpis. Ut viverra, nisl non euismod sollicitudin, tellus lectus finibus leo, in ornare sem mauris non eros. Fusce augue est, rhoncus vitae tristique in, malesuada nec libero. Sed venenatis vehicula
    ultricies. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Fusce interdum auctor ante a fermentum. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Aliquam malesuada
    scelerisque tortor ac faucibus. Integer pharetra eget velit a tempus. Aenean at lobortis massa, vel accumsan ligula.
  </div>
</body>

回答1:


You could set a class on the div.layout element (or some other parent tag) based on the username variable you are setting, and then adjust your CSS grid to redefine the CSS grid columns/rows based on that class.

(I'm not super familiar with React, but if memory serves you can set a class conditionally like this)

<div className={"layout " + (this.props.usernameShown ? 'username-avail' : 'username-unavail')}>

Then in your CSS file, you can define your CSS grid such as

.layout {
    display: grid;
    grid-template-columns: minmax(200px, auto) minmax(200px, 300px) minmax(900px, auto) minmax(200px, auto);
    grid-gap: 5px;
    height: calc(100vh);
}

.username-avail.layout {
    /* Four rows */
    grid-template-rows: 60px 60px 60px minmax(700px, auto);
}

.username-unavail.layout {
    /* Three rows */
    grid-template-rows: 60px 60px minmax(700px, auto);
}



回答2:


Once you create explicit tracks, which are rows and columns created using the following properties:

  • grid-template-rows
  • grid-template-columns
  • grid-template-areas
  • grid (a shorthand)

... you are stuck with those tracks. They don't go away.

Your attempt to remove an explicit row with display: none on a grid item (.username) cannot work. The command is operating at the item level, but the row was created at the container level.

If you want to build a grid that has a dynamic inflow and outflow of tracks, then use implicit, not explicit, tracks.

Implicit tracks are rows and columns created automatically to accommodate grid items that are positioned outside of the explicit grid.

When there is no grid item to occupy an implicit track, that track simply doesn't exist.

I've posted two examples below, based on your code.

  • the first example displays a row for .username, the other example does not;
  • grid-template-rows has been removed, so there are no explicit rows; all rows are implicit;
  • heights previously set on grid-template-rows have been moved to their respective grid items;
  • implicit row heights are governed by grid-auto-rows, whose initial value is auto (content-based), so it works well with the previous point; and,
  • because you're dealing with implicit tracks, source order matters.

with username row

.layout {
  display: grid;
  grid-template-columns: minmax(200px, auto) minmax(200px, 300px) minmax(900px, auto) minmax(200px, auto);
  grid-gap: 5px;
  height: 100vh;
}


/* implicit first row */
.navbar {
  height: 60px;
  grid-column: 1 / -1;
  background-color: #3a3f51;
  border-bottom: 1px solid #797d89;
  text-align: center;
  color: aliceblue;
}


/* implicit second row */
.username {
  /* display: none; */
  height: 60px;
  grid-column: 1 / -1;
  background-color: #f7f9f9;
  border-bottom: 1px solid #dee5e7;
  text-align: center;
}


/* implicit third row (start) */
.statement-list {
  height: 60px;
  grid-column: 2 / 3;
  max-height: 600px;
}


/* implicit third row */
.title {
  height: 60px;
  grid-column: 3 / 4;
  grid-row: 3 / 4;
}

.content {
  min-height: 700px;
  grid-column: 3 / 4;
  overflow-x: auto;
  overflow-y: auto;
}

body {
  margin: 0;
}
<body class="layout">
  <div class="navbar">About</div>
  <div class="username">CSS Grid User</div>
  <div class="title">Lorem Ipsum</div>
  <div class="statement-list">
    Phasellus commodo sit amet eros non pharetra. Phasellus consequat augue est, ornare finibus lectus auctor non. Praesent rutrum odio tortor. Proin id massa magna. Phasellus commodo sit amet eros non pharetra. Phasellus consequat augue est, ornare finibus
    lectus auctor non. Praesent rutrum odio tortor. Proin id massa magna.
  </div>
  <div class="content">
    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean laoreet a odio quis commodo. In nisl justo, tincidunt vel aliquet eget, mollis eget lorem. Aenean sit amet nibh eget nunc sodales vestibulum id ac ante. Nullam eleifend sodales ipsum, sed
    porta tellus posuere molestie. Vestibulum congue porta odio sed iaculis. Phasellus varius sodales ullamcorper. Praesent consectetur ante eget turpis pretium, eget sagittis leo volutpat. Aenean posuere, sapien quis placerat pulvinar, lectus est interdum
    dui, at pretium risus sapien et neque. Sed eu fringilla turpis. Ut viverra, nisl non euismod sollicitudin, tellus lectus finibus leo, in ornare sem mauris non eros. Fusce augue est, rhoncus vitae tristique in, malesuada nec libero. Sed venenatis vehicula
    ultricies. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Fusce interdum auctor ante a fermentum. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Aliquam malesuada
    scelerisque tortor ac faucibus. Integer pharetra eget velit a tempus. Aenean at lobortis massa, vel accumsan ligula.
  </div>

without username row (by just adding display: none)

.layout {
  display: grid;
  grid-template-columns: minmax(200px, auto) minmax(200px, 300px) minmax(900px, auto) minmax(200px, auto);
  grid-gap: 5px;
  height: 100vh;
}


/* implicit first row */
.navbar {
  height: 60px;
  grid-column: 1 / -1;
  background-color: #3a3f51;
  border-bottom: 1px solid #797d89;
  text-align: center;
  color: aliceblue;
}


/* implicit second row */
.username {
  display: none; /* ADDED */
  height: 60px;
  grid-column: 1 / -1;
  background-color: #f7f9f9;
  border-bottom: 1px solid #dee5e7;
  text-align: center;
}


/* implicit third row (start) */
.statement-list {
  height: 60px;
  grid-column: 2 / 3;
  max-height: 600px;
}


/* implicit third row */
.title {
  height: 60px;
  grid-column: 3 / 4;
  grid-row: 3 / 4;
}

.content {
  min-height: 700px;
  grid-column: 3 / 4;
  overflow-x: auto;
  overflow-y: auto;
}

body {
  margin: 0;
}
<body class="layout">
  <div class="navbar">About</div>
  <div class="username">CSS Grid User</div>
  <div class="title">Lorem Ipsum</div>
  <div class="statement-list">
    Phasellus commodo sit amet eros non pharetra. Phasellus consequat augue est, ornare finibus lectus auctor non. Praesent rutrum odio tortor. Proin id massa magna. Phasellus commodo sit amet eros non pharetra. Phasellus consequat augue est, ornare finibus
    lectus auctor non. Praesent rutrum odio tortor. Proin id massa magna.
  </div>
  <div class="content">
    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean laoreet a odio quis commodo. In nisl justo, tincidunt vel aliquet eget, mollis eget lorem. Aenean sit amet nibh eget nunc sodales vestibulum id ac ante. Nullam eleifend sodales ipsum, sed
    porta tellus posuere molestie. Vestibulum congue porta odio sed iaculis. Phasellus varius sodales ullamcorper. Praesent consectetur ante eget turpis pretium, eget sagittis leo volutpat. Aenean posuere, sapien quis placerat pulvinar, lectus est interdum
    dui, at pretium risus sapien et neque. Sed eu fringilla turpis. Ut viverra, nisl non euismod sollicitudin, tellus lectus finibus leo, in ornare sem mauris non eros. Fusce augue est, rhoncus vitae tristique in, malesuada nec libero. Sed venenatis vehicula
    ultricies. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Fusce interdum auctor ante a fermentum. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Aliquam malesuada
    scelerisque tortor ac faucibus. Integer pharetra eget velit a tempus. Aenean at lobortis massa, vel accumsan ligula.
  </div>

Spec references:

  • § 7.1 The Explicit Grid
  • § 7.5 The Implicit Grid



回答3:


Personally, I like to write my own functions. So this would be my approach ...

JavaScript

function removeElementsByClass(className){
    var elements = document.getElementsByClassName(className);
    while(elements.length > 0){
        elements[0].parentNode.removeChild(elements[0]);
    }
}

Then just ...

removeElementsByClass('.username')

Of course, there's no shame in taking the easy option (but it's helpful to know what happens behind the scenes).

jQuery

$('.username').remove();

NOTE: This will only remove the element with the assigned class name. So, you'll either need to give a class name to the targeted row, or drill back further by including an additional parentNode ...

elements[0].parentNode.parentNode.removeChild(elements[0]);


来源:https://stackoverflow.com/questions/50217730/dynamically-changing-the-number-of-rows-in-a-css-grid

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!