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:
Screenshot with non-empty .formula
, notice the different height:
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: