Search code examples
htmlcssgrid-layout

Weird behavior of first Row of a Grid Container


To get my head around front-end, I decided to create a simple calculator. It seemed like a good idea to use the grid-layout since the content is pretty well known upfront, won't change and since I wanted to be able to use different sized buttons as well vertically as horizontally. With a 4x6 grid, I was able to lay out everything as I wanted.

To better visualize my issue, I have created a Codepen.io for it. My issue is that although I'm using a grid-layout, the row-height is different for the first row.

Here's the CSS:

.calculator-grid-container {
      height: 70vh;
      width: 60vw;
      max-width: 50vh;
      border-style: solid;
      border-width: 3px;
      border-color: white;
      background-color:#2e323a;
      border-radius: 1%;
      box-shadow: 0 0 10px whitesmoke;
      /* grid container config */
      display: grid;
      grid-template-columns: auto auto auto auto;
      grid-gap: 0px;
      padding: 10px;
    }

I'm setting the class on a div and rendering the buttons and the display inside of it:

render() {
    return (
      <div className='calculator-grid-container'>
        <Display current={this.state.current} formula={this.state.formula}></Display>

        <Button name='AC' handleButtonPressed={this.handleButtonPressed}></Button>
        <Button name='/' handleButtonPressed={this.handleButtonPressed}></Button>
        <Button name='*' handleButtonPressed={this.handleButtonPressed}></Button>

        <Button name='1' handleButtonPressed={this.handleButtonPressed}></Button>
        <Button name='2' handleButtonPressed={this.handleButtonPressed}></Button>
        <Button name='3' handleButtonPressed={this.handleButtonPressed}></Button>
        <Button name='-' handleButtonPressed={this.handleButtonPressed}></Button>

        <Button name='4' handleButtonPressed={this.handleButtonPressed}></Button>
        <Button name='5' handleButtonPressed={this.handleButtonPressed}></Button>
        <Button name='6' handleButtonPressed={this.handleButtonPressed}></Button>
        <Button name='+' handleButtonPressed={this.handleButtonPressed}></Button>

        <Button name='7' handleButtonPressed={this.handleButtonPressed}></Button>
        <Button name='8' handleButtonPressed={this.handleButtonPressed}></Button>
        <Button name='9' handleButtonPressed={this.handleButtonPressed}></Button>
        <Button name='=' handleButtonPressed={this.handleButtonPressed}></Button>

        <Button name='0' handleButtonPressed={this.handleButtonPressed}></Button>
        <Button name='.' handleButtonPressed={this.handleButtonPressed}></Button>
      </div>
    );
  }

And on the buttons, I'm using the flex-layout to center the text:

.button {
  display: flex;
  justify-content: center; /* align horizontal */
  align-items: center; /* align vertical */
}

And of course to let them span accordingly, for example:

.AC-button {
  grid-column-start: 1;
  grid-column-end: 3;
}

Now, my issue is with the first row, which is a div-container with two p-elements:

render() {
    return (
      <div className='display'>
        <p className='formula'>
          {this.props.formula}
        </p>
        <p className='current' id='display'>
          {this.props.current}
        </p>
      </div>
    );
  }

Their CSS:

.display {
  background-color: black;
  text-align: right;
  font-family: digital;
  padding: 5px 10px 0 0;
  /* grid config */
  grid-column-start: 1;
  grid-column-end: 5;
  /* flex-layout inside the div to align the p-elements */
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: right;
}

.formula {
  opacity: 0.5;
  overflow-wrap: break-word;
  word-wrap: break-word; 
}

.current {
  font-size: 46px;
}

Problems with above aproache: 1. The height of the first row (the .display) seems to differ a lot from all the other rows. I want all the rows to have exactly same height. 2. The size of the .display seems to vary with the font-size of .formula and .current, I don't want it to grow when I change the font-size of the containing p-elements. 3. The size of the .display varies radically if the .formula element is empty (i.e. ''). It seems like the p-element would be non-existent if it is empty. I don't want the size to vary if the p element is empty.

Maybe I'm missing something. Can someone help?

Screenshot with empty .formula (p-elem = ''), notice the height: enter image description here

Screenshot with non-empty .formula, notice the different height: enter image description here


Solution

  • I came up with the following solution, which does solve all the above mentioned issues (1. all rows have fixed and equal hight, 2. the height of the .display-div does not vary regardless of the content of the .formula p-tag and 3. regardless of the font-size set on them).

    grid-template-rows: repeat(6, 1fr);
    

    This is creating 6 rows, each occupying 1 equal fraction of the available free space (one caveat on using fr: the free space is calculated after any non-flexible items).

    So apparently the thing that I was missing was actually specifying the fact that I wanted all the rows to be of equal height.

    Thank you @arieljuod for pointing out in the comment on the default margins on the p-tag!

    p {
      margin-top: 0; /* remove default margins */
      margin-bottom: 0;  /* remove default margins */
      min-height: 25%; /* avoid dropping height to 0 for empty p-tags */
    }
    

    I noticed that the p-tag still collapsed to a height of 0 when when it had no content, even though the row-height did not change anymore. This still lead to a kind of unclean behavior where the lower p-element was 'jumping' up when the upper p-element was reset to occupy the available height and then back down on a button pressed when the upper p-tag height was getting set and hence the height reclaimed by the upper p-element.

    To avoid that, I added min-height: 25% to the p-tag, so now the height is never dropping below 25% of the available space which avoids the above mentioned behavior of the lower p-element.

    Here's how this now looks like:

    enter image description here