I am creating a form for my site that is center-aligned on my page. However, I want to ignore the labels when center aligning, such that the input boxes are center-aligned, with the labels right aligned up-against the inputs.
Here is a simplified snippet from my code, just to display the issue.
body {
text-align: center;
}
<!DOCTYPE html>
<html>
<body>
<h1>Login</h1>
<form>
<label for="email">Email:</label>
<input type="email" id="email" name="email" required>
<br><br>
<label for="password">Password:</label>
<input type="password" id="password" name="password" required>
<br><br>
<button class = 'button' id ='loginbutton' type="submit">Login</button>
</form>
</body>
</html>
By reading other questions, I saw one recommendation of setting the display to inline block and the width to 0. That properly aligned my input boxes, but my labels are now behind the text.
body {
text-align: center;
}
label {
display: inline-block;
width: 0;
}
<!DOCTYPE html>
<html>
<body>
<h1>Login</h1>
<form>
<label for="email">Email:</label>
<input type="email" id="email" name="email" required>
<br><br>
<label for="password">Password:</label>
<input type="password" id="password" name="password" required>
<br><br>
<button class = 'button' id ='loginbutton' type="submit">Login</button>
</form>
</body>
</html>
I know I could achieve this through a table, but I was wondering if there was any simpler way? Here is the code showing my desired look.
body {
text-align: center;
}
#table-form {
display: flex;
justify-content: center;
text-align: right;
}
td {
width: 10rem
}
<!DOCTYPE html>
<html>
<body>
<h1>Login</h1>
<form>
<div id = 'table-form'>
<table>
<tr>
<td> <label for="email">Email:</label> </td>
<td> <input type="email" id="email" name="email" required> </td>
<td> </td>
</tr>
<tr>
<td> <label for="password">Password:</label> </td>
<td> <input type="password" id="password" name="password" required> </td>
<td> </td>
</tr>
</table>
</div>
<br>
<button class = 'button' type="submit">Login</button>
</form>
</body>
</html>
If the table is the best way to address this, just let me know :) Thanks for the help!
CodePudding user response:
One approach, with explanatory comments in the code, is below:
/* we use this width a couple of times, so we cache it as
a CSS custom property (to allow for easier updating in
the future): */
:root {
--inputWidth: 15em;
}
/* hugely simple/naive reset, to have all elements' dimensions
calculated as including the width of borders and padding, and
removing default margin and padding: */
*,
::before,
::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
/* to center align: */
h1 {
text-align: center;
}
/* using flex-layout: */
form {
display: flex;
/* shorthand for:
flex-direction: column;
flex-wrap: nowrap;
*/
flex-flow: column nowrap;
/* shorthand for:
justify-content: center;
align-content: center;
*/
place-items: center;
/* to place a 2em gap between adjacent elements,
whether horizontally or vertically; shorthand for:
gap: 2em 2em;
which is shorthand for:
column-gap: 2em;
row-gap: 2em;
*/
gap: 2em;
/* applies a margin along the block axis (in a
language such as English that's top and bottom): */
margin-block: 1em;
/* applies an auto margin along the inline axis (in a
language such as English that's left and right), this
causes the <form> element to be centered on the inline
axis: */
margin-inline: auto;
/* using the clamp() function to set a preferred width
of 60vw, with a minimum permitted width of 20em and
a maximum permitted width of 1000px: */
width: clamp(20em, 60vw, 1000px);
}
label {
/* centering the content of the <label> element: */
justify-content: center;
/* using flex layout: */
display: flex;
/* and assigning a position of relative, in order
to absolutely position a descendant: */
position: relative;
}
label > span {
/* position: absolute takes the element out of the
document flow and layout calculations: */
position: absolute;
/* aligning the text to the end of the inline axis,
in English that's equivalent to 'right': */
text-align: end;
/* translating the element 95% of its own width,
the -95% moves it towards the start of the
inline axis (left in a left-to-right language): */
transform: translateX(-95%);
/* setting the width to be equal to the width of
the <input>: */
width: var(--inputWidth);
}
/* styling the pseudo-element to automatically display
a presentational ':' character following the
content: */
label > span::after {
content: ':';
}
input {
width: var(--inputWidth);
}
/* styling the <button> so as not to have it span the full
width of the flex parent: */
button {
padding-block: 0.25em;
padding-inline: 0.5em;
width: fit-content;
}
<h1>Login</h1>
<form>
<!-- I've moved the <input> inside the <label>, and wrapped its text-content in a <span> for
styling purposes: -->
<label for="email">
<span>Email</span>
<input type="email" id="email" name="email" required>
</label>
<label for="password">
<span>Password</span>
<input type="password" id="password" name="password" required>
</label>
<button class='button' id='loginbutton' type="submit">Login</button>
</form>
References: