Arton Hoxha
Arton Hoxha

Reputation: 373

CSS grid align items not same size

I want to recreate the same design as the second image below using CSS grid. I got a problem with the alignment, of course because of the two spans the inputs are not aligned like they should be. I am almost there with CSS grid but i can't figure it out. Is there a way to do it with grid or is there another solution for this?

Render in react Adobe xd design

 <div className="grade-card">
            <div className="grade-card-header">
                <span className="title">{this.props.title}</span>
            </div>
            <div className="grade-card-body">
                <div className="grade-input">
                    <span>I</span>
                    <input type="text"/>
                    <span>1x</span>
                </div>
                <div className="grade-input">
                    <span>I</span>
                    <input type="text"/>
                    <span>Min</span>
                </div>
                <div className="grade-input">
                    <span>I</span>
                    <input type="text"/>
                    <span>1x</span>
                </div>
                <div className="grade-input">
                    <span>I</span>
                    <input type="text"/>
                </div>
                <div className="grade-input">
                    <span>I</span>
                    <input type="text"/>
                </div>
                <div className="grade-input">
                    <input type="text"/>
                </div>
            </div>
        </div>
.grade-card{
  width: 349px;
  height: 384px;
  background-color: white;
  border-radius: 28px;

  .grade-card-header{
    display: flex;
    align-items: center;
    justify-content: center;
    height: 20%;
    border-radius: 28px 28px 0 0;
    background-color: #1089FF;

    .title{

      color: white;
      font-size: 1.5em;
    }
  }

  .grade-card-body{
    height: 80%;
    cursor: pointer;
    display: grid;
    grid-template-columns: repeat(2, 174.5px);
    grid-template-rows: repeat(3, 102.4px);
    justify-items: center;//horizontally
    align-items: center;//vertically

    input{
      outline: none;
      width: 74px;
      height: 51px;
      border: 1px solid #707070;
      border-radius: 6px;
      font-size: 1.3em;
      text-align: center;
    }

    .grade-input:last-child{
      input{
        width: 117px;
        height: 69px;
      }
    } 
  }
}

Upvotes: 0

Views: 678

Answers (2)

Henrique Erzinger
Henrique Erzinger

Reputation: 1147

This is a little of a variation on @Brice's answer, because in his version:

  1. you need to adjust for each variation of the label text
  2. if the font is rendered different, it will break (zoom, differences between platforms, etc).

This version solves it, but the idea to use absolute positioning to escape the flow is the same.

/*********** begin changes **********/

.grade-input {
  position: relative;
}

.label {
  position: absolute;
  top: 50%;
}

.label-left {
  transform: translate(calc(-100% - 6px), -50%);
}

.label-right {
  transform: translate(6px, -50%);
}

/*********** end changes **********/


.grade-card {
  width: 349px;
  height: 384px;
  background-color: white;
  border-radius: 28px;
}

.grade-card .grade-card-header {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 20%;
  border-radius: 28px 28px 0 0;
  background-color: #1089ff;
}

.grade-card .grade-card-header .title {
  color: white;
  font-size: 1.5em;
}

.grade-card .grade-card-body {
  height: 80%;
  cursor: pointer;
  display: grid;
  grid-template-columns: repeat(2, 174.5px);
  grid-template-rows: repeat(3, 102.4px);
  justify-items: center;
  align-items: center;
}

.grade-card .grade-card-body input {
  outline: none;
  width: 74px;
  height: 51px;
  border: 1px solid #707070;
  border-radius: 6px;
  font-size: 1.3em;
  text-align: center;
}

.grade-card .grade-card-body .grade-input:last-child input {
  width: 117px;
  height: 69px;
}
<div class="grade-card">
  <div class="grade-card-header">
    <span class="title">{this.props.title}</span>
  </div>

  <div class="grade-card-body">
    <div class="grade-input">
      <span class="label label-left">I</span>
      <input type="text"/>
      <span class="label label-right">1x</span>
    </div>

    <div class="grade-input">
      <span class="label label-left">I</span>
      <input type="text"/>
      <span class="label label-right">Min</span>
    </div>

    <div class="grade-input">
      <span class="label label-left">I</span>
      <input type="text"/>
      <span class="label label-right">1x</span>
    </div>

    <div class="grade-input">
      <span class="label label-left">I</span>
      <input type="text"/>
    </div>

    <div class="grade-input">
      <span class="label label-left">I</span>
      <input type="text"/>
    </div>
    <div class="grade-input">
      <input type="text"/>
    </div>
  </div>
</div>

Upvotes: 1

Brice
Brice

Reputation: 96

Because the spans are different values, your .grade-input divs are becoming different widths and that is throwing off your alignment.

EDITED to get inputs aligned exactly centered:

If you make the spans position: absolute;, then you would be able to just align the inputs.

Try below HTML:

<div className="grade-card">
        <div className="grade-card-header">
            <span className="title">{this.props.title}</span>
        </div>
        <div className="grade-card-body">
            <div className="grade-input">
                <span className="left-absolute">I</span>
                <input type="text"/>
                <span className="right-absolute oneX">1x</span>
            </div>
            <div className="grade-input">
                <span className="left-absolute">I</span>
                <input type="text"/>
                <span className="right-absolute min">Min</span>
            </div>
            <div className="grade-input">
                <span className="left-absolute">I</span>
                <input type="text"/>
                <span className="right-absolute oneX">1x</span>
            </div>
            <div className="grade-input">
                <span className="left-absolute">I</span>
                <input type="text"/>
            </div>
            <div className="grade-input">
                <span className="left-absolute">I</span>
                <input type="text"/>
            </div>
            <div className="grade-input">
                <input type="text"/>
            </div>
        </div>
    </div>

Add below to your css file:

.grade-input {
  position: relative;
}

.left-absolute {
    position: absolute;
    left: -7px;
    top: 20px;
}

.right-absolute.oneX {
    position: absolute;
    right: -15px;
    top: 20px;
}
.right-absolute.min {
    position: absolute;
    right: -27px;
    top: 20px;
}

Upvotes: 0

Related Questions