How to style form with line numbers using CSS Grid Layout? - html

I would like to create a form, which has a line number on each line and several form fields on each line. If the fields don't fit into one line, they should wrap into a new line while the line number stays at the top of the line. Here's an illustration of this form:
(The dark blue lines describe the explicit grid areas, the light blue line implicit grid areas for the different form fields.)
I know CSS Grid Layout is meant to solve use cases like this, though it is not clear to me, how to generate the form mentioned above with it.
What I've tried so far is:
HTML:
<div class="form">
<div class="row">
<div class="lineNumber">1</div>
<label for="field1">Field 1 <input id="field1"/></label>
<label for="field2">Field 2 <input id="field2"/></label>
<label for="field3">Field 3 <input id="field3"/></label>
</div>
<div class="row">
<div class="lineNumber">2</div>
<label for="field1">Field 4 <input id="field1"/></label>
</div>
</div>
CSS:
.row {
display: grid;
grid-template-columns: 50px 1fr 1fr;
grid-auto-rows: 30px;
}
.row > * {
padding: 4px;
}
.lineNumber {
grid-row-end: line-number span;
}
What I don't get yet, how can I achieve to let the row number column span over the whole height of the row while the other columns wrap between lines. I assume it must be possible defining the line-number named area using grid-template-rows. Though how?
EDIT:
I'm aware that it may be possible by using display: table-row; / display: table-cell;, though my main point is to achieve this using CSS Grid Layout.
2ND EDIT:
Note that some months after I asked this question here and Grid Layout implementations stabilized showing this feature is not available yet, I requested it at the CSS Working Group. Since then a similar request for spanning explicit and implicit tracks was made.

In my opinion, css counters should meet your question
#import "https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css";
form {
counter-reset: form;
border: 2px solid cyan;
}
fieldset {
position: relative;
display: block;
padding: 1em 1em 1em 3em !important;
border-bottom: 2px solid cyan;
}
fieldset::before {
counter-increment: form;
content: counter(form);
position: absolute;
left: 5px;
top: 5px;
font-weight: bolder;
}
.sp-b { margin-bottom: 1em }
<form>
<fieldset>
<div class="row">
<div class="col-xs-6 sp-b"><input type="text" class="form-control"></div>
<div class="col-xs-6"><input type="text" class="form-control"></div>
</div>
<div class="row">
<div class="col-xs-12"><input type="text" class="form-control"></div>
</div>
</fieldset>
<fieldset>
<div class="row">
<div class="col-xs-12"><input type="text" class="form-control"></div>
</div>
</fieldset>
<fieldset>
<div class="row">
<div class="col-xs-12"><input type="text" class="form-control"></div>
</div>
</fieldset>
<fieldset>
<div class="row">
<div class="col-xs-12"><input type="text" class="form-control"></div>
</div>
</fieldset>
</form>

You can use display:table/table-cell to achieve what you want
Snippet
*,
*:before,
*:after {
box-sizing: border-box;
}
.form {
display: table;
table-layout: fixed;
width: 100%;
border: 1px solid #000;
}
.row {
display: table-row
}
.lineNumber,
.fields {
display: table-cell;
vertical-align: top;
padding: 10px 0;
}
.lineNumber {
border: 1px solid #000;
border-width: 0 1px 1px 0;
width: 20px;
text-align: center
}
.fields {
border-bottom: 1px solid #000;
/*fix inline-block gap*/
font-size: 0
}
label {
padding: 0 10px;
/*whatever you want */
font-size: 16px;
}
.row:first-of-type label {
width: 50%;
display: inline-block
}
.row:first-of-type label:not(:last-of-type) {
border-bottom: 1px solid red;
padding-bottom: 10px
}
.row:first-of-type label:last-of-type {
margin-top: 10px
}
.row:last-of-type .lineNumber,
.row:last-of-type .fields {
border-bottom: 0
}
<div class="form">
<div class="row">
<div class="lineNumber">1</div>
<div class="fields">
<label for="field1">Field 1
<input id="field1" />
</label>
<label for="field2">Field 2
<input id="field2" />
</label>
<label for="field3">Field 3
<input id="field3" />
</label>
</div>
</div>
<div class="row">
<div class="lineNumber">2</div>
<div class="fields">
<label for="field1">Field 4
<input id="field1" />
</label>
</div>
</div>
</div>

Related

CSS for different device sizes

I have a simple page that consists of a form. There is a string for what the input box should be, and then the input box.
I want two different behaviors. When a cell phone is accessing the page, I want everything to be stacked on top of each other, but when the page is accessed via a computer I want multiple rows consisting of the the title, followed by the input box on the same row.
I've researched media queries by I still don't understand it enough to get through.
<html>
<head>
<style>
</style>
</head>
<body>
<form>
<center>
<div class="left">
First name:
</div>
<div class="right">
<input type="text" name="firstname"/>
</div>
<div class="left">
Last name:
</div>
<div class="right">
<input type="text" name="lastname"/>
</div>
<div class="left">
Email Address:
</div>
<div class="right">
<input type="text" name="email"/>
</div>
<div class="left">
Address:
</div>
<div class="right">
<input type="text" name="address"/>
</div>
<div class="left">
I've practiced yoga for at least one year:
</div>
<div class="right">
<input type="checkbox" name="oneyear"/>
</div>
<div class="right">
<input type="submit" name="submit" value="submit"/>
</div>
</center>
</form>
</body>
</html>
You have multiple choice: using Bootstrap to easily display your grid in different ways on window resize.
You can also use media queries, combine with a grid layout like Flexbox or Grid.
Or even use Jquery and the windworesize function.
Personnaly, i would choose Flexbox and the flex-direction propriety when the window reach the size of a smartphone or tablet.
To write a media querie, you just have to type something like #media screen and (max-width: 640px) for instance and write your rules inside the curly brackets.
Here is a sample code.
<!DOCTYPE html>
<html>
<head>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html,
body {
height: 100%;
font-size: 16px;
line-height: 22px;
font-family: Arial, Helvetica, sans-serif;
background-color: #f5f5f5;
}
.clearfix::after {
content: "";
clear: both;
display: table;
}
.my-form {
width: 100%;
max-width: 920px;
margin: 0 auto;
padding: 20px;
}
.my-form .input {
width: 100%;
padding: 10px;
}
.my-form .input .left {
display: block;
width: 100%;
line-height: 24px;
padding: 3px 0;
margin-bottom: 5px;
}
.my-form .input .right {
width: 100%;
}
.my-form .input input[type='text'], .my-form .input input[type='email'], .my-form .input textarea {
display: block;
width: 100%;
height: 30px;
font-size: 16px;
padding: 3px;
line-height: 22px;
border: 1px solid rgba(0,0,0,.3);
}
.my-form .input textarea {
height: auto;
min-height: 60px;
resize: vertical;
}
.my-form .input input[type='submit'] {
display: block;
width: 100%;
padding: 15px;
background-color: navy;
color: #ffffff;
font-size: 16px;
line-height: 22px;
}
#media screen and (max-width: 1024px) {
.my-form .input:after {
content: "";
clear: both;
display: table;
}
.my-form .input .left {
float: left;
width: 35%;
padding-right: 10px;
margin-bottom: 0;
}
.my-form .input .right {
float: right;
width: 65%;
}
}
</style>
</head>
<body>
<form class="my-form">
<div class="input">
<label class="left" for="firstname">
First name:
</label>
<div class="right">
<input type="text" id="firstname" name="firstname" />
</div>
</div>
<div class="input">
<label class="left" for="lastname">
Last name:
</label>
<div class="right">
<input type="text" id="lastname" name="lastname" />
</div>
</div>
<div class="input">
<label class="left" for="email">
Email Address:
</label>
<div class="right">
<input type="email" id="email" name="email" />
</div>
</div>
<div class="input">
<label class="left" for="address">
Address:
</label>
<div class="right">
<textarea cols="10" rows="5" id="address" name="address"></textarea>
</div>
</div>
<div class="input">
<div class="left"></div>
<div class="right">
<label for="oneyear"><input type="checkbox" id="oneyear" name="oneyear" /> I've practiced yoga for at least one year:</label>
</div>
</div>
<div class="input">
<input type="submit" name="submit" value="submit" />
</div>
</form>
</body>
</html>
You need Media Query for this. Media query is basically writing different CSS for devices with different widths. You can learn more from here- https://www.w3schools.com/css/css3_mediaqueries_ex.asp
Also check out this article- https://css-tricks.com/snippets/css/media-queries-for-standard-devices/
You can also use jQuery for the same using matchmedia..
Here is a JSbin example for you- https://jsbin.com/kutacuzece/edit
(function($) {
/*
* We need to turn it into a function.
* To apply the changes both on document ready and when we resize the browser.
*/
function mediaSize() {
/* Set the matchMedia */
if (window.matchMedia('(min-width: 768px)').matches) {
/* Changes when we reach the min-width */
$('body').css('background', '#222');
$('strong').css('color', 'tomato');
} else {
/* Reset for CSS changes – Still need a better way to do this! */
$('body, strong').removeAttr('style');
}
};
/* Call the function */
mediaSize();
/* Attach the function to the resize event listener */
window.addEventListener('resize', mediaSize, false);
})(jQuery);
OR you can use something as simple as this-
if ($(window).width() < 960) {
$(selector).css({property:value, property:value, ...})
}
else if ($(window).width() < 768) {
$(selector).css({property:value, property:value, ...})
}
else {
$(selector).css({property:value, property:value, ...})
}

How to group an icon and an input element

I'm trying to achieve the following:
Create 3 input elements in a row
Each should have a logo to the left of it, centered perfectly.
Each should have a border-bottom that spans the logo as well.
Like the following image:
However with my current code the images can't be centered and the border doesn't span them. Here's my code:
input {
border: none;
width: 250px;
background-color: #393d49;
border-bottom: 1px solid #767D93;
padding: 10px;
}
form img {
width: 24px;
height: 24px;
}
<form>
<img src="assets/images/envelope.png" alt="Envelope icon indicating user's E-Mail.">
<input type="email" placeholder="E-Mail"><br>
<img src="assets/images/locked.png" alt="Lock icon indicating user's Password.">
<input type="password" placeholder="Password"><br>
<img src="assets/images/avatar.png" alt="Avatar icon indicating user's Name.">
<input type="text" placeholder="Username"><br>
</form>
As it was suggested, I would also use the font-awesome library. But if your not comfortable with that idea, here is how you can do without.
form, .form-row, input {
background-color: #051024;
}
.input-icon, label, input {
display: inline-block;
}
form {
padding: 0.8em 1.2em;
}
.form-row {
padding: 0.8em 0;
padding-bottom: 0.2em;
}
.form-row:not(:last-child) {
border-bottom: solid #18273a 1px; /* Only the last row has a border */
}
.input-icon {
width: 15px;
height: 15px;
margin: 0 10px;
}
label {
max-width:4em; /* Or the maximum width you want your lebel to be */
min-width:4em; /* Same */
color:white;
font-weight: 100;
}
input {
border:none;
padding: 0.8em 0.5em;
color: #6691c9;
font-size: 15px;
outline: none; /* No glowing borders on chrome */
}
<form>
<div class="form-row">
<!-- Put your image here, like so -->
<img class="input-icon" src="http://1.bp.blogspot.com/-QTgDeozeWws/VLztRSNkMEI/AAAAAAAAKkQ/mrxdCfxWfvU/s1600/1f499.png" alt="oops"/>
<label for="form-email">Email</label>
<input id="form-email" type="email">
</div>
<div class="form-row">
<img class="input-icon" src="http://1.bp.blogspot.com/-QTgDeozeWws/VLztRSNkMEI/AAAAAAAAKkQ/mrxdCfxWfvU/s1600/1f499.png" alt="oops"/>
<label for="form-password">Password</label>
<input id="form-password"type="password" placeholder="(8 characters min)">
</div>
<div class="form-row">
<img class="input-icon" src="http://1.bp.blogspot.com/-QTgDeozeWws/VLztRSNkMEI/AAAAAAAAKkQ/mrxdCfxWfvU/s1600/1f499.png" alt="oops"/>
<label for="form-user">User</label>
<input id="form-user" type="text"><br>
</div>
</form>
If you're feeling adventurous
Try bootstrap, it has all you need to create cool web sites (it also includes the font-awesome library).

Tab contents are not consuming space, so html tags defined later are not actually rendered after tab contents

I'm trying to build tabs using pure HTML and CSS. I've got the tab functionality working, so when you click a tab label the corresponding content shows.
But in my design I've 2 tab areas, 1 for request and 1 for response. For some reason my request seems to overlap the response area, why is this so?
The <hr> tag that separates the 2 areas should always be below the request area's shown content.
http://jsfiddle.net/bobbyrne01/pgzt6nbf/
Current output (content tab) ..
Current output (header tab) ..
Desired output ..
html ..
<div id="main">
<div class="left w60">
<div class="center">
<h2>Request</h2>
</div>
<div>
<div>
<input id="url" placeholder="Request URL .." class="w100" />
</div>
<br/>
<div>
<select id="method">
<option value="0">GET</option>
<option value="1">HEAD</option>
</select>
<button type="button" id="submit">Submit</button>
</div>
<br/>
<div class="tabs">
<div class="tab">
<input type="radio" id="tab-1a" name="tab-group-1" hidden checked />
<label class="tabLabel" for="tab-1a">Headers</label>
<div class="content">
<div id="headersRequest">
<table id="headersRequestTable" class="w100">
<tr>
<th>Name</th>
<th>Value</th>
<th>
<input type="button" id="newHeaderButton" value="+" />
</th>
</tr>
</table>
</div>
</div>
</div>
<div class="tab">
<input type="radio" id="tab-2a" name="tab-group-1" hidden checked />
<label class="tabLabel" for="tab-2a">Body content</label>
<div class="content">
<div id="bodyRequest">
<textarea id="bodyRequestListItem" rows="10" class="w100"></textarea>
</div>
</div>
</div>
</div>
</div>
<hr>
<div class="center">
<h2>Response</h2>
</div>
<div class="tabs">
<div class="tab">
<input type="radio" id="tab-1b" name="tab-group-2" hidden checked />
<label class="tabLabel" for="tab-1b">Headers</label>
<div class="content">
<div id="headers"></div>
</div>
</div>
<div class="tab">
<input type="radio" id="tab-2b" name="tab-group-2" hidden checked />
<label class="tabLabel" for="tab-2b">Body content</label>
<div class="content">
<button id="clipboard" style="display: none;">Copy to clipboard</button>
<br/>
<div id="bodyContent"></div>
</div>
</div>
<div class="tab">
<input type="radio" id="tab-3b" name="tab-group-2" hidden checked />
<label class="tabLabel" for="tab-3b" id="statusListItem">Status</label>
<div class="content">
<div id="status"></div>
</div>
</div>
</div>
</div>
<div class="right w30">
<div class="center">
<h2>History</h2>
<table id="historyContainer"></table>
</div>
</div>
</div>
css ..
.left {
float: left;
}
.right {
float: right;
}
.center {
text-align: center;
}
.w30 {
width: 30%;
}
.w40 {
width: 40%;
}
.w50 {
width: 50%;
}
.w60 {
width: 60%;
}
.w100 {
width: 100%;
}
.bCollapse {
border-collapse: collapse;
}
/*
* Tabs
*/
.tabs {
position: relative;
height: 100%;
clear: both;
margin: 35px 0 25px;
}
.tab {
float: left;
}
.tabLabel {
background: #eee;
padding: 10px;
border: 1px solid #ccc;
margin-left: -1px;
position: relative;
left: 1px;
top: -20px;
}
.content {
position: absolute;
top: 2px;
left: 0;
right: 0;
bottom: 0;
padding: 20px;
opacity: 0;
}
[type=radio]:checked ~ label {
background: white;
border-bottom: 1px solid white;
z-index: 2;
}
[type=radio]:checked ~ label ~ .content {
z-index: 1;
opacity: 1;
}
Try to add min-height for tabs Demo
.tabs {
position: relative;
height: 100%;
min-height: 200px;
clear: both;
margin: 35px 0 25px;
display:block;
}
I remember a year or 2 back, before I learned JS, when I was heavily invested in creating functioning tabs using only HTML and CSS. They can be done, but at a cost of being unable to use animations on them (you cannot animate from display: none to display: block).
Anyway, the issue you are having if because your element with the class "content" has its position set to "absolute". By definition, you are telling this element to not consume space. Remove this, or change the position to "relative", and you should see a more desired behaviour.

HTML Form misplaced

I have a simple HTML form with some validations but the text labels get misplaced when the form appears.
This is the form before (PLEASE NOTE: The red square around it is not part of the form, I just placed it with Paint to help you see the problem quick):
And after:
Any hint to keep the label aligned with the text field please?
UPDATE:
This is the code:
<form name="senstageaddform">
<div class="form-element">
<label for="ed_senStartDate" class="text-label">
{{i18n "EDUCATION_SEN_START_DATE"}} <span class="required">*</span>
</label>
<input type="text" class="date standard-text-field" maxlength="16" id="ed_senStartDate" name="startDate"/>
</div>
<div class="form-element">
<label for="ed_senEndDate" class="text-label">{{i18n "EDUCATION_SEN_END_DATE"}}</label>
<input type="text" class="date standard-text-field" maxlength="16" id="ed_senEndDate" name="endDate"/>
</div>
</form>
Here is the CSS:
.form-element {
display: inline-block; margin: 5px; width: 98%; clear: both; vertical-align:top
.text-label {
width: 20%; text-align: right; display: inline-block; padding: 3px 5px 0px 1px;
}
.standard-text-field {
width: 10em;
}

Two column grid without using row class

I am generating HTML pages at run time with the help of freemarker. This poses some limitation on the HTML generation part.
Currently to show input fields in two grid column, I need to define each row and place my fields in it.
Current HTML
<body class="container">
<div class="section-outline">
<div class="row-fluid show-grid">
<div class="span6 form-inline"><label class="pocLabel">First Name:</label><input type="text" required/></div>
<div class="span6 form-inline"><label class="pocLabel">Middle Initial:</label><input type="text" /></div>
</div>
<div class="row-fluid show-grid">
<div class="span6 form-inline"><label class="pocLabel">Last Name:</label><input type="text" required/></div>
<div class="span6 form-inline"><label class="pocLabel">Social Security Number:</label><input type="text"/></div>
</div>
Can I get same result without putting span6 divs in a row? I want same result with something like:
<div class="span6 form-inline"><label class="pocLabel">First Name:</label><input type="text" required/></div>
<div class="span6 form-inline"><label class="pocLabel">Middle Initial:</label><input type="text" /></div>
<div class="span6 form-inline"><label class="pocLabel">Last Name:</label><input type="text" required/></div>
<div class="span6 form-inline"><label class="pocLabel">Social Security Number:</label><input type="text"/></div>
Here
.show-grid [class*="span"] {
text-align: left;
-webkit-border-radius: 3px;
-moz-border-radius: 3px;
border-radius: 3px;
min-height: 40px;
line-height: 40px;
margin-top: 10px;
display: inline;
}
label.pocLabel {
width: 200px;
vertical-align: middle;
}
.section-outline {
position: relative;
margin: 15px 0;
padding: 39px 19px 14px;
background-color: #fff;
border: 1px solid #ddd;
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
border-radius: 4px;
}
is this what you are looking for : http://jsfiddle.net/wa2YQ/
.span6.form-inline {
display:inline-block;
width:49%;
}
.span6.form-inline label {
width:200px;
display:inline-block;
}
or
http://jsfiddle.net/wa2YQ/1/
.span6.form-inline {
float:left;
width:50%;
}
.span6.form-inline label {
width:200px;
display:inline-block;
}
or else ?
You can use the :nth-child, but this is only supported in recent browsers
.show-grid .span:odd {
/* Your css for left floating */
}
.show-grid .span:even {
/* Your css for right floating */
}
If you need to support older browsers you can change the order of the fields and float them left next to each other.
if you want do do that without placing span6 inside row then you first need to get rid of row-fluid you are using in the main container div. Just use row there and and apply offset to to move the required div to the right.like this pen http://www.codepen.io/anon/pen/wfFnG
First Name:
Middle Initial:
Last Name:
Social Security Number: