Search code examples
htmlcssflexboxradio-buttonalignment

Why does align-items in a button change the position of the button?


I'm building a website that contains quizzes and surveys, and I'm trying to make an html layout page for all the surveys(there will be a lot). It's 95% done, the questions and answers are plugged in to the html page with JavaScript and presented as buttons. The user selects the answers they think is correct and then confirms with a separate button. However, whenever one of the options is too long to fit on a single line, it wraps around and then the button itself drops down like 5px.

I want to know why the button's position is changing and how to prevent it from moving. The buttons are flex elements and they are inside divs that are inline blocks. Here is the html for it.

.surveyOptions {
  padding-top: 10px;
  max-height: 80px;
}

.surveyOptions div {
  width: 49.5%;
  height: 80px;
  display: inline-block;
  padding-bottom: 5px;
}

input[type="radio"] {
  display: none;
}

label {
  background-color: #f0f4fa;
  border-radius: 15px;
  border: 2px solid #2867ae;
  font-size: 20px;
  font-weight: 400px;
  width: 100%;
  height: 100%;
  padding: 10px;
  color: #2867ae;
  font-weight: bold;
  margin: auto;
  text-align: center;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  overflow: visible;
}

input[type="radio"]:hover+label {
  background-color: #CEDDEF;
}

input[type="radio"]:checked+label {
  background-color: #2867ae;
  color: #f0f4fa;
}

.nextButton {
  background-color: #2867ae;
  border: none;
  color: #f0f4fa;
  border-radius: 15px;
  font-size: 20px;
  font-weight: 400px;
  width: 100%;
  max-width: 600px;
  height: 90px;
  font-weight: bold;
  display: block;
  margin: auto;
  text-align: center;
  cursor: pointer;
}

.nextButton:hover {
  background-color: #164B86;
}
<div style="margin-left: auto; margin-right: auto; padding-top: 4px; padding-bottom: 4px;">
  <div class="surveyOptions">
    <div>
      <input type="radio" name="answer" id="a" class="answer">
      <label for="a" id="a_text">Answer</label>
    </div>
    <div>
      <input type="radio" name="answer" id="b" class="answer">
      <label for="b" id="b_text">Answer</label>
    </div>
  </div>
  <div class="surveyOptions">
    <div>
      <input type="radio" name="answer" id="c" class="answer">
      <label for="c" id="c_text">Answer</label>
    </div>
    <div>
      <input type="radio" name="answer" id="d" class="answer">
      <label for="d" id="d_text">Answer</label>
    </div>
  </div>
</div>
<div style="padding-top: 20px;">
  <button type="button" id="submit" class="nextButton">Next</button>
</div>

Yes, I'm fully aware that my organization is a mess. I'm a beginner to HTML and CSS so right now I'm only working on getting a working version of my website before I optimize and organize.

I've tried removing align-items: center, which does stop the button from moving, but also affects the placement of the text so not ideal. Any ideas on how to get the best of both worlds?


Solution

  • The issue seemed to be related to overflowing the height of 80px. The overflow happens on top and bottom with align-items: center and the button is centered in the text, but I couldn't figure out why there was extra space above the text.

    However, I think this may be a good case for using Grid on the surveyOptions container.

    The only adjustment I made with the HTML was to have all four answers in one surveyOptions container.

    In the CSS, I added the grid declarations to surveyOptions, added box-sizing: border-box to label, and commented out the declarations that were no longer needed.

    .surveyOptions {
        /* max-height: 80px; */
        display: grid;
        grid-template-columns: 50% 50%;
        grid-auto-rows: minmax(80px, max-content);
        gap: 5px;
    }
    
    .surveyOptions div {
        /* width: 49.5%; */
        /* height: 80px; */
        /* display: inline-block; */
        /* padding-bottom: 5px; */
    }
    
    label {
        box-sizing: border-box;
        /* width: 100%; */
        /* margin: auto; */
        /* overflow: visible; */
    }
    

    .surveyOptions {
        padding-top: 10px;
        /* max-height: 80px; */
        display: grid;
        grid-template-columns: 50% 50%;
        grid-auto-rows: minmax(80px, max-content);
        gap: 5px;
    }
    
    .surveyOptions div {
        /* width: 49.5%; */
        /* height: 80px; */
        /* display: inline-block; */
        /* padding-bottom: 5px; */
    }
    
    input[type="radio"] {
        display: none;
      }
    
    label {
        box-sizing: border-box;
        background-color: #f0f4fa;
        border-radius: 15px;
        border: 2px solid #2867ae;
        font-size: 20px;
        font-weight: 400px; /* invalid value; should be 400 w/o unit */
        /* width: 100%; */
        height: 100%;
        padding: 10px;
        color: #2867ae;
        font-weight: bold;
        /* margin: auto; */
        text-align: center;
        display: flex;
        align-items: center;
        justify-content: center;
        cursor: pointer;
        /* overflow: visible; */
    }
    
    input[type="radio"]:hover + label {
        background-color: #CEDDEF;
    }
    
    input[type="radio"]:checked + label {
        background-color: #2867ae; 
        color: #f0f4fa;
    }
    
    .nextButton {
        background-color: #2867ae; 
        border: none; 
        color: #f0f4fa;
        border-radius: 15px; 
        font-size: 20px; 
        font-weight: 400px; 
        width: 100%;
        max-width: 600px; 
        height: 90px;
        font-weight: bold;
        display: block;
        margin: auto;
        text-align: center;
        cursor: pointer;
    }
    
    .nextButton:hover {
        background-color: #164B86;
    }
    <div style="margin-left: auto; margin-right: auto; padding-top: 4px; padding-bottom: 4px;">
       <div class="surveyOptions">
            <div>
               <input type="radio" name="answer" id="a" class="answer">
               <label for="a" id="a_text">Answer</label>
            </div>
            <div>
               <input type="radio" name="answer" id="b" class="answer">
               <label for="b" id="b_text">A really long answer that expands the height of the button to more than 80px and needs to be contained instead of overflowing</label>
            </div>
            <div>
               <input type="radio" name="answer" id="c" class="answer">
               <label for="c" id="c_text">Answer</label>
            </div>
            <div>
               <input type="radio" name="answer" id="d" class="answer">
               <label for="d" id="d_text">Answer</label>
            </div>
       </div>
    </div>
    <div style="padding-top: 20px;">
       <button type="button" id="submit" class="nextButton">Next</button>
    </div>

    I decided to include an example using Flexbox on the surveyOptions container. You can look at the examples and decide which layout method works best for you.

    I encourage you to try different align-items values on the surveyOptions container to see which alignment you prefer.

    .surveyOptions {
        display: flex;
        flex-wrap: wrap;
        align-items: flex-end;
        gap: 5px;
    }
    
    .surveyOptions div {
        flex-basis: calc(50% - 2.5px);
    }
    
    label {
        min-height: 80px;
    }
    

    .surveyOptions {
        padding-top: 10px;
        /* max-height: 80px; */
        display: flex;
        flex-wrap: wrap;
        align-items: flex-end;
        gap: 5px;
    }
    
    .surveyOptions div {
        flex-basis: calc(50% - 2.5px);
        /* width: 49.5%; */
        /* height: 80px; */
        /* display: inline-block; */
        /* padding-bottom: 5px; */
    }
    
    input[type="radio"] {
        display: none;
      }
    
    label {
        min-height: 80px;
        box-sizing: border-box;
        background-color: #f0f4fa;
        border-radius: 15px;
        border: 2px solid #2867ae;
        font-size: 20px;
        font-weight: 400px; /* invalid value; should be 400 w/o unit */
        /* width: 100%; */
        height: 100%;
        padding: 10px;
        color: #2867ae;
        font-weight: bold;
        /* margin: auto; */
        text-align: center;
        display: flex;
        align-items: center;
        justify-content: center;
        cursor: pointer;
        /* overflow: visible; */
    }
    
    input[type="radio"]:hover + label {
        background-color: #CEDDEF;
    }
    
    input[type="radio"]:checked + label {
        background-color: #2867ae; 
        color: #f0f4fa;
    }
    
    .nextButton {
        background-color: #2867ae; 
        border: none; 
        color: #f0f4fa;
        border-radius: 15px; 
        font-size: 20px; 
        font-weight: 400px; 
        width: 100%;
        max-width: 600px; 
        height: 90px;
        font-weight: bold;
        display: block;
        margin: auto;
        text-align: center;
        cursor: pointer;
    }
    
    .nextButton:hover {
        background-color: #164B86;
    }
    <div style="margin-left: auto; margin-right: auto; padding-top: 4px; padding-bottom: 4px;">
       <div class="surveyOptions">
            <div>
               <input type="radio" name="answer" id="a" class="answer">
               <label for="a" id="a_text">Answer</label>
            </div>
            <div>
               <input type="radio" name="answer" id="b" class="answer">
               <label for="b" id="b_text">A really long answer that expands the height of the button to more than 80px and needs to be contained instead of overflowing</label>
            </div>
            <div>
               <input type="radio" name="answer" id="c" class="answer">
               <label for="c" id="c_text">Answer</label>
            </div>
            <div>
               <input type="radio" name="answer" id="d" class="answer">
               <label for="d" id="d_text">Answer</label>
            </div>
       </div>
    </div>
    <div style="padding-top: 20px;">
       <button type="button" id="submit" class="nextButton">Next</button>
    </div>