Communities

Writing
Writing
Codidact Meta
Codidact Meta
The Great Outdoors
The Great Outdoors
Photography & Video
Photography & Video
Scientific Speculation
Scientific Speculation
Cooking
Cooking
Electrical Engineering
Electrical Engineering
Judaism
Judaism
Languages & Linguistics
Languages & Linguistics
Software Development
Software Development
Mathematics
Mathematics
Christianity
Christianity
Code Golf
Code Golf
Music
Music
Physics
Physics
Linux Systems
Linux Systems
Power Users
Power Users
Tabletop RPGs
Tabletop RPGs
Community Proposals
Community Proposals
tag:snake search within a tag
answers:0 unanswered questions
user:xxxx search by author id
score:0.5 posts with 0.5+ score
"snake oil" exact phrase
votes:4 posts with 4+ votes
created:<1w created < 1 week ago
post_type:xxxx type of post
Search help
Notifications
Mark all as read See all your notifications »
Q&A

Welcome to Software Development on Codidact!

Will you help us build our independent community of developers helping developers? We're small and trying to grow. We welcome questions about all aspects of software development, from design to code to QA and more. Got questions? Got answers? Got code you'd like someone to review? Please join us.

Why is my last input box not centering (class: powerwall-battery-input)?

+2
−0

I found a form I wanted to duplicate on a roof construction website.

All my input boxes are centered except the last one that's a bit off and I cannot figure out why.

Here is my code:

HTML

<main class="calc-wrapper">
      <!-- Solar Roof Data Inputs -->

      <form class="calc-form" action="form-results.html" method="get">
        <label for="first-name" class="label first-name-label">
          First Name
        </label>
        <input type="text" class="first-name-input" />
        <label for="last-name" class="label last-name-label"> Last Name </label>
        <input type="text" class="last-name-input" />

        <!-- Google API Address Autocomplete Section -->
        <label class="label addr-sec-label" for="addr-sec"
          >Address Selection*</label
        >
        <input type="text" class="input" placeholder="Address" id="location" />
        <input
          type="text"
          class="input"
          placeholder="Apt, Suite, etc (optional)"
        />
        <input type="text" class="input" placeholder="City" id="locality" />

        <input
          type="text"
          class="input"
          placeholder="State/Province"
          id="administrative_area_level_1"
        />

        <input
          type="text"
          class="input"
          placeholder="Zip/Postal code"
          id="postal_code"
        />

        <input type="text" class="input" placeholder="Country" id="country" />
        <div class="map" id="map"></div>

        <!-- End - Google API Address Autocomplete Section -->

        <div class="roof-complexity">
          <label class="label roof-complexity-label" for="roof-complexity"
            >Roof Complexity Type*</label
          >
          <select
            class="roof-complexity-input"
            id="roof-complexity-input"
            name="roof-complexity"
          >
            <option selected disabled hidden>Select an Option</option>
            <option id="simple" value="simple">Simple</option>
            <option id="moderate" value="moderate">Moderate</option>
            <option id="complex" value="complex">Complex</option>
          </select>
        </div>

        <div class="system-size">
          <label class="label system-size-label" for="system-size"
            >Select System Size*</label
          >
          <button class="btn calc-form-btn system-size-minus-btn" type="button">
            -
          </button>
          <input
            class="system-size-input"
            id="system-size-input"
            value="4.0"
          />
          <button class="btn calc-form-btn system-size-plus-btn" type="button">
            +
          </button>
        </div>

        <div class="powerwall-battery">
          <label class="label powerwall-battery-label" for="powerwall-battery"
            >Select Powerwall Battery Storage (in units)*</label
          >
          <button
            class="btn calc-form-btn powerwall-battery-minus-btn"
            type="button"
          >
            -
          </button>
          <input class="powerwall-battery-input" id="powerwall-battery-input" />
          <button
            class="btn calc-form-btn powerwall-battery-plus-btn"
            type="button"
          >
            +
          </button>
        </div>
      </form>

      <!-- Totals and Incentives Calculations -->

      <div class="totals-section">
        <label class="label roof-before-itc" for="roof-before-itc"
          >Solar Roof Price Before Incentives</label
        >
        <input type="text" class="input" id="roof-price-before-itc" />

        <label
          class="label powerwall-price-before-itc"
          for="powerwall-price-before-itc"
          >Powerwall Price Before Incentives</label
        >
        <input class="input" id="powerwall-price-before-itc" value=" " />

        <label class="label est-total-before-itc" for="est-total-before-itc"
          >Estimated Total Price Before Incentives</label
        >
        <input type="text" class="input" id="est-total-before-itc" />

        <label class="label est-itc" for="est-itc">Estimated Solar ITC</label>
        <input type="text" class="input" id="est-itc" />
      </div>
    </main>

CSS

/** Set Global Styling Variables **/

:root {
  /** Fonts **/
  --mainFont: "Arial";
  --textFont: "Open Sans", sans-serif;
  --secondaryFont: "Raleway", sans-serif;

  /** Colors **/
  --primary: #4f5449;
  --darkGray: #2f2e2e;
  --lightGray: #ebebeb;
  --white: #fff;
  --black: #000;
  --darkorange: orange;
}

/** Apply Natural Box Layout Model to All Elements - Allow Components to Change **/

*,
*:before,
*:after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

html {
  font-size: 62.5%; /* Now 10px = 1rem! */
}

body {
  font-family: var(--mainFont);
  font-size: 1.6rem;
  line-height: 2;
}

.calc-wrapper {
  display: flex;
  justify-content: center;
  align-items: center;
  width: 100%;
}

/** Calculator Form 1 Styles **/

/** Use Flexbox to Limit the Use of Media Queries and to Center the Main Element on All Devices**/

.calc-form {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  margin-top: 5rem;
  margin-bottom: 5rem;
  width: 50%;
  padding: 5rem;
}

.first-name-input {
  width: 50%;
  padding: 2rem;
}

.last-name-input {
  width: 50%;
  padding: 2rem;
}

/** Style Calculator Form Input and Label Sections 
System Size Input area was not given a class of 'input'
so the buttons would remain inline with the input field. 
It was given only and ID to target for a one off style and
for JS **/

/** Style Google API Address Autocomplete Section **/

.sb-title {
  font-family: var(--mainFont);
  font-weight: bold;
}

/** Style Form Address Section **/

.addr-sec-input {
  width: 100%;
  padding: 2rem;
}

.input {
  width: 50%;
  padding: 2rem;
  text-align: center;
}

.label {
  margin-top: 2rem;
  font-weight: bold;
  text-align: center;
  display: block;
}

/** Style Home Size Section **/

.home-size-input {
  padding: 2rem;
  text-align: center;
}

/** Style Roof Complexity Section **/

.roof-complexity-input {
  padding: 2rem;
  text-align: center;
}

/** Style Form System Size Section **/

.system-size {
  display: block;
}

.system-size-input {
  padding: 2rem;
  text-align: center;
}

/** Style Form Powerwall Battery Storage **/
.powerwall-battery {
  display: block;

}

.powerwall-battery-input {
  padding: 2rem;
  text-align: center;
}

.calc-form-btn {
  background-color: var(--primary);
  border: none;
  color: var(--white);
  padding: 0 1.5rem;
  text-align: center;
  text-decoration: none;
  font-size: 2rem;
  border-radius: 0.5rem;
  cursor: pointer;
}

/** Calculator Form 2 Styles **/
.totals-section {
  border: var(--black);
  border-style: solid;
  background: var(--darkorange);
  width: 50%;
  margin-right: 5rem;
  border-width: 1px;
  padding: 5rem;
  display: flex;
  flex-direction: column;
  align-items: center;
  width: 25%;
}

.submit-section {
  text-align: center;
  margin-bottom: 5rem;
}

.submit-btn {
  border-style: solid;
  border-width: 1px 1px 1px 1px;
  border-color: #FFFFFF;
  color: #FFFFFF;
  background-color: var(--primary);
  padding: 4rem;
  font-size: 2rem;
  text-transform: uppercase;
  border-radius: 1rem;
  width: 10%;
}

.submit-btn {
  cursor: pointer;
}
History
Why does this post require moderator attention?
You might want to add some details to your flag.
Why should this post be closed?

0 comment threads

1 answer

+4
−0

To investigate such problems, open the developer tools of your browser, and use the inspect this element feature to inspect the bounding boxes of the various elements.

in Chrome:

  • press F12 to open dev tools
  • click the icon at the very top left of the dev tools, which has a tooltip that reads "select this element to inspect it")
  • hover over the offending element to see its bounding box highlighted

(other browser's dev tools work similarly)

If you do so here, you'll notice that for the last form item, the label is wider than the input beneath, while for the others, the labels are exactly as wide as the input, with the label text centered in the available space. You'll also notice that the last label is exactly as wide as the text it contains - it has grown to accommodate its content.

So apparently, the centering in this form works by centering the label text within the area occupied by the label, but it does not center the input in the area beneath.

In fact, looking more closely at the last input we see that the empty space to its right is not occupied by any element - so while the label stretched to fill the available space (by virtue of display: block), the input doesn't. That's because the input doesn't have a display set, so it defaults to display: inline, which stands for inline text, flowing from left to right like text does. And since text is left-justified by default, it squishes towards the left of the available space, which was carved out by that overly long label.

There are various ways of solving this, but seeing how ugly that form is, with the first inputs stretching to fill available space, and later inputs all at different sizes, I think we'd best be a bit more consistent about the layout modes we choose to use.

If your intent is for the form to stretch to fill available space, a flex layout would be the tool of choice. In fact, this is what the form is already using, and it works just fine for the first elements.

But the later elements, for some reason I can not fathom, are enclosed by an additional div, which defaults to display: block. So the contents of the div are first laid out as a block of text, and that block of text is then horizontally centered (rather than each individual line being centered)

If you remove those unnecessary divs, the elements in the form (the labels, buttons, selects, and input), are shown underneath each other, with each horizontally aligned to the center, as we intend.

But, I hear you say, I don't want the buttons and inputs to be on separate lines. Ok, then group those into a new element rather than throwing the label in as well. And since we're doing the entire form with flex layout, we might use a flex layout for that, too:

		<label class="label system-size-label" for="system-size"
			>Select System Size*</label
		>
		<div class="buttongroup">
			<button class="btn calc-form-btn system-size-minus-btn" type="button">
				-
			</button>
			<input
				class="system-size-input"
				id="system-size-input"
				value="4.0"
			/>
			<button class="btn calc-form-btn system-size-plus-btn" type="button">
				+
			</button>
		</div>

and then tell the browser how to layout that div:

.buttongroup {
	display: flex; /* use flex layout mode */
	flex-direction: row; /* lay out contents from left to right */
	gap: 1rem; /* with a 1rem gap between elements */
}
.buttongroup input {
	flex-grow: 1; /* make the element stretch to fill available space */
}

Combined with removing all those explicit widths on the elements, the form displays nicely:

<!DOCTYPE html>
<head>
	<style>
		/** Set Global Styling Variables **/

:root {
  /** Fonts **/
  --mainFont: "Arial";
  --textFont: "Open Sans", sans-serif;
  --secondaryFont: "Raleway", sans-serif;

  /** Colors **/
  --primary: #4f5449;
  --darkGray: #2f2e2e;
  --lightGray: #ebebeb;
  --white: #fff;
  --black: #000;
  --darkorange: orange;
}

/** Apply Natural Box Layout Model to All Elements - Allow Components to Change **/

*,
*:before,
*:after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

html {
  font-size: 62.5%; /* Now 10px = 1rem! */
}

body {
  font-family: var(--mainFont);
  font-size: 1.6rem;
  line-height: 2;
}

.calc-wrapper {
  display: flex;
  justify-content: center;
  align-items: center;
  width: 100%;
}

/** Calculator Form 1 Styles **/

/** Use Flexbox to Limit the Use of Media Queries and to Center the Main Element on All Devices**/

.calc-form {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: stretch;
  margin-top: 5rem;
  margin-bottom: 5rem;
  padding: 5rem;
}

.buttongroup {
	display: flex; /* use flex layout mode */
	flex-direction: row; /* lay out contents from left to right */
	gap: 1rem; /* with a 1rem gap between elements */
}
.buttongroup input {
	flex-grow: 1; /* make the element stretch to fill available space */
}

/** Style Calculator Form Input and Label Sections 
System Size Input area was not given a class of 'input'
so the buttons would remain inline with the input field. 
It was given only and ID to target for a one off style and
for JS **/

/** Style Google API Address Autocomplete Section **/

.sb-title {
  font-family: var(--mainFont);
  font-weight: bold;
}

/** Style Form Address Section **/

.addr-sec-input {
  width: 100%;
  padding: 2rem;
}

input {
  padding: 2rem;
  text-align: center;
}

.label {
  margin-top: 2rem;
  font-weight: bold;
  text-align: center;
  display: block;
}

/** Style Home Size Section **/

.home-size-input {
  padding: 2rem;
  text-align: center;
}

/** Style Roof Complexity Section **/

.roof-complexity-input {
  padding: 2rem;
  text-align: center;
}

/** Style Form System Size Section **/

.system-size {
  display: block;
}

.system-size-input {
  padding: 2rem;
  text-align: center;
}

/** Style Form Powerwall Battery Storage **/
.powerwall-battery {
  display: block;

}

.powerwall-battery-input {
  padding: 2rem;
  text-align: center;
}

.calc-form-btn {
  background-color: var(--primary);
  border: none;
  color: var(--white);
  padding: 0 1.5rem;
  text-align: center;
  text-decoration: none;
  font-size: 2rem;
  border-radius: 0.5rem;
  cursor: pointer;
}

/** Calculator Form 2 Styles **/
.totals-section {
  border: var(--black);
  border-style: solid;
  background: var(--darkorange);
  width: 50%;
  margin-right: 5rem;
  border-width: 1px;
  padding: 5rem;
  display: flex;
  flex-direction: column;
  align-items: center;
  width: 25%;
}

.submit-section {
  text-align: center;
  margin-bottom: 5rem;
}

.submit-btn {
  border-style: solid;
  border-width: 1px 1px 1px 1px;
  border-color: #FFFFFF;
  color: #FFFFFF;
  background-color: var(--primary);
  padding: 4rem;
  font-size: 2rem;
  text-transform: uppercase;
  border-radius: 1rem;
  width: 10%;
}

.submit-btn {
  cursor: pointer;
}
	</style>
</head>
<body>
	<main class="calc-wrapper">
		<!-- Solar Roof Data Inputs -->
	
		<form class="calc-form" action="form-results.html" method="get">
			<label for="first-name" class="label first-name-label">
				First Name
			</label>
			<input type="text" class="first-name-input" />
			<label for="last-name" class="label last-name-label"> Last Name </label>
			<input type="text" class="last-name-input" />
	
			<!-- Google API Address Autocomplete Section -->
			<label class="label addr-sec-label" for="addr-sec"
				>Address Selection*</label
			>
			<input type="text" class="input" placeholder="Address" id="location" />
			<input
				type="text"
				class="input"
				placeholder="Apt, Suite, etc (optional)"
			/>
			<input type="text" class="input" placeholder="City" id="locality" />
	
			<input
				type="text"
				class="input"
				placeholder="State/Province"
				id="administrative_area_level_1"
			/>
	
			<input
				type="text"
				class="input"
				placeholder="Zip/Postal code"
				id="postal_code"
			/>
	
			<input type="text" class="input" placeholder="Country" id="country" />
			<div class="map" id="map"></div>
	
			<!-- End - Google API Address Autocomplete Section -->
	
			<label class="label roof-complexity-label" for="roof-complexity"
				>Roof Complexity Type*</label
			>
			<select
				class="roof-complexity-input"
				id="roof-complexity-input"
				name="roof-complexity"
			>
				<option selected disabled hidden>Select an Option</option>
				<option id="simple" value="simple">Simple</option>
				<option id="moderate" value="moderate">Moderate</option>
				<option id="complex" value="complex">Complex</option>
			</select>
	
			<label class="label system-size-label" for="system-size"
				>Select System Size*</label
			>
			<div class="buttongroup">
				<button class="btn calc-form-btn system-size-minus-btn" type="button">
					-
				</button>
				<input
					class="system-size-input"
					id="system-size-input"
					value="4.0"
				/>
				<button class="btn calc-form-btn system-size-plus-btn" type="button">
					+
				</button>
			</div>
	
			<label class="label powerwall-battery-label" for="powerwall-battery"
				>Select Powerwall Battery Storage (in units)*</label
			>
			<div class="buttongroup">
				<button
					class="btn calc-form-btn powerwall-battery-minus-btn"
					type="button"
				>
					-
				</button>
				<input class="powerwall-battery-input" id="powerwall-battery-input" />
				<button
					class="btn calc-form-btn powerwall-battery-plus-btn"
					type="button"
				>
					+
				</button>
			</div>			
		</form>
	
		<!-- Totals and Incentives Calculations -->
	
		<div class="totals-section">
			<label class="label roof-before-itc" for="roof-before-itc"
				>Solar Roof Price Before Incentives</label
			>
			<input type="text" class="input" id="roof-price-before-itc" />
	
			<label
				class="label powerwall-price-before-itc"
				for="powerwall-price-before-itc"
				>Powerwall Price Before Incentives</label
			>
			<input class="input" id="powerwall-price-before-itc" value=" " />
	
			<label class="label est-total-before-itc" for="est-total-before-itc"
				>Estimated Total Price Before Incentives</label
			>
			<input type="text" class="input" id="est-total-before-itc" />
	
			<label class="label est-itc" for="est-itc">Estimated Solar ITC</label>
			<input type="text" class="input" id="est-itc" />
		</div>
	</main>
</body>

Note that if you prefer the form not to stretch horizontally, all you have to do is change align-items: stretch to align-items: center in .calc-form.

Bottom line:

  • The root cause of your layout bug was accidentally mixing different layout modes which do alignment differently.
  • When introducing wrapper elements, think about whether the grouping makes visual sense, and check that the wrapper element uses an appropriate layout mode.
  • Flex layouts are great for laying out elements in rows or columns, and stretching to fill available space.
  • More generally, web developers should understand the various layout modes CSS offers (inline, block, flex, and grid are most common), and what each is used for. Good references to CSS layout include the CSS specification, specifically the section Visual Formatting Model for inline and inline-block and block, and the css-tricks tutorials for flex and grid.
History
Why does this post require moderator attention?
You might want to add some details to your flag.

1 comment thread

Firefox developer tools (1 comment)

Sign up to answer this question »