2

If I want to use the css-grid and make one of its child fill up the remaining width when the other child is not present on the screen, how would I do something like that?

var button = document.querySelector('.click');
var buttone = document.querySelector('.clicke')
var left = document.querySelector('.left');

button.addEventListener('click', function(e) {
  left.style.display = 'none';
})

buttone.addEventListener('click', function(e) {
  left.style.display = 'block';
})
html,
body {
  margin: 0;
}

.wrap {
  display: grid;
  width: 100vw;
  height: 100vh;
  background-color: black;
  grid-template-columns: 1fr 1fr;
  grid-template-areas: "left right"
}

.left {
  grid-area: left;
  background-color: green;
}

.right {
  grid-area: right;
  background-color: red
}
<div class='wrap'>
  <div class='left'>
    <button class='click'>HIDE ME</button>
  </div>
  <div class='right'>
    <button class='clicke'>SHOW HIM</button>
  </div>
</div>

For example, if the green's display becomes none, I would like for the red to fill up the remaining spot in the grid. I can use other displays to achieve this effect easily, but I wanted to know if there was a method to do this while using a grid display with its areas being specifically laid out.

Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
Iruss
  • 229
  • 4
  • 13
  • I submitted a solution but just read *"with its areas being specifically laid out"*. Do you just mean the columns behaving that way? Is it ok to remove the `grid-template-areas`? – Michael Coker Jul 24 '17 at 00:24
  • 1
    Sorry about the late comment. I was hoping I could keep the grid-template-areas to re-order the grid display in the future, but I think I can work around that. – Iruss Jul 24 '17 at 00:56
  • When one item is removed, set the other item to ***grid-column: 1 / -1***. https://stackoverflow.com/q/45070481/3597276 – Michael Benjamin Jul 24 '17 at 11:10
  • Or, instead of using *explicit* columns, use *implicit* columns set to ***1fr***. https://stackoverflow.com/q/43301949/3597276 – Michael Benjamin Jul 24 '17 at 11:13

3 Answers3

2

Don't define areas so that the columns can be flexible, set grid-template-columns: 1fr; with grid-auto-flow: column; and grid-auto-columns: 50%

var button = document.querySelector('.click');
var buttone = document.querySelector('.clicke')
var left = document.querySelector('.left');

button.addEventListener('click', function(e) {
  left.style.display = 'none';
})

buttone.addEventListener('click', function(e) {
  left.style.display = 'block';
})
html,
body {
  margin: 0;
}

.wrap {
  display: grid;
  width: 100vw;
  height: 100vh;
  background-color: black;
  grid-template-columns: 1fr;
  grid-auto-columns: 50%;
  grid-auto-flow: column;
}

.left {
  background-color: green;
}

.right {
  background-color: red
}
<div class='wrap'>
  <div class='left'>
    <button class='click'>HIDE ME</button>
  </div>
  <div class='right'>
    <button class='clicke'>SHOW HIM</button>
  </div>
</div>
Vadim Ovchinnikov
  • 13,327
  • 5
  • 62
  • 90
Michael Coker
  • 52,626
  • 5
  • 64
  • 64
  • Could that be made scaleable _i.e._ if there were multiple rows like the one above, could each row behave as it does without disrupting the grid? I just tried, and it was a mess (I know little about `grid` yet). – Fred Gandt Jul 24 '17 at 00:04
  • @FredGandt I'm not sure what you mean. Can you show me an example of your multiple row scenario? – Michael Coker Jul 24 '17 at 00:18
  • I think that would qualify as another question. I'll fiddle with it myself, and if I can't figure it out, I'll post a question and give you a heads-up here. Very late in UK; good night :-) – Fred Gandt Jul 24 '17 at 00:26
2

At least in this case, it's enough to set

gridColumnStart: 1;

to get the desired layout. The element occupies the named area and also the first column.

I am unsure however about the posibilities to make this solution more general

var button = document.querySelector('.click');
var buttone = document.querySelector('.clicke')
var left = document.querySelector('.left');
var right = document.querySelector('.right');

button.addEventListener('click', function(e) {
  left.style.display = 'none';
  right.style.gridColumnStart = '1';
})

buttone.addEventListener('click', function(e) {
  left.style.display = 'block';
  right.style.gridColumnStart = '';
})
html,
body {
  margin: 0;
}

.wrap {
  display: grid;
  width: 100vw;
  height: 100vh;
  background-color: black;
  grid-template-columns: 1fr 1fr;
  grid-template-areas: "left right"
}

.left {
  grid-area: left;
  background-color: green;
}

.right {
  grid-area: right;
  background-color: red
}
<div class='wrap'>
  <div class='left'>
    <button class='click'>HIDE ME</button>
  </div>
  <div class='right'>
    <button class='clicke'>SHOW HIM</button>
  </div>
</div>
vals
  • 61,425
  • 11
  • 89
  • 138
0

Change .wrap display to block when grid is redundant

Although you have stated that:

I can use other displays to achieve this effect easily, but I wanted to know if there was a method to do this while using a grid display with its areas being specifically laid out.

This method keeps the display: grid layout while it's needed, but scraps it in favour of display: block when it's not.

Cheating? This isn't code golf ;-)

const hide = document.querySelector( '.hide' ),
      show = document.querySelector( '.show' ),
      wrap = document.querySelector( '.wrap' );

hide.addEventListener( 'click', function() {
  wrap.classList.add( 'hidden' );
} );

show.addEventListener('click', function() {
  wrap.classList.remove( 'hidden' );
} );
html, body {
  margin: 0;
}
.wrap {
  display: grid;
  width: 100vw;
  height: 100vh;
  background-color: black;
  grid-template-columns: 1fr 1fr;
  grid-template-areas: "left right";
}
.wrap.hidden {
  display: block;
}
.wrap.hidden .left {
  display: none;
}
.wrap.hidden .right {
  height: 100vh;
}
.left {
  grid-area: left;
  background-color: green;
}
.right {
  grid-area: right;
  background-color: red;
}
<div class='wrap'>
  <div class='left'>
    <button class='hide'>HIDE ME</button>
  </div>
  <div class='right'>
    <button class='show'>SHOW HIM</button>
  </div>
</div>
Fred Gandt
  • 4,217
  • 2
  • 33
  • 41