octocatstartv

Pen Settings

CSS Base

Vendor Prefixing

Add External CSS

These stylesheets will be added in this order and before the code you write in the CSS editor. You can also add another Pen here, and it will pull the CSS from it. Try typing "font" or "ribbon" below.

Quick-add: + add another resource

Add External JavaScript

These scripts will run in this order and before the code in the JavaScript editor. You can also link to another Pen here, and it will run the JavaScript from it. Also try typing the name of any popular library.

Quick-add: + add another resource

Code Indentation

     

Save Automatically?

If active, Pens will autosave every 30 seconds after being saved once.

Auto-Updating Preview

If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.

            
              <!-- <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"/> -->

<h1><span>Best Practice</span> Forms</h1>
<h2>This example meets following requirements</h2>
<ul>
  <li>Container independent, flexible widths in percent</li>
  <li>Responsive, linearizable, mobile-ready</li>
  <li>Browser support: IE8 and up, Chrome latest, Safari latest, Firefox latest, Opera latest, major mobile browsers</li>
  <li>2 variants: labels left (for most forms) and labels above (small or narrow forms)</li>
  <li>Doesn't break with multi-line labels</li>
  <li>Client-side validation via HTML5 input types and JavaScript support</li>
  <li>Inline error messages</li>
  <li>Backend/templating friendly
    <ul>
      <li>Suitable for using label/input/error includes/snippets</li>
      <li>Slim and flexible markup</li>
    </ul>
  </li>
</ul>
<form action="#" method="get">
  <fieldset class="wideform">
    <h3 class="legend">Form kitchen sink</h3>
    <p><b>Labels left:</b> Suitable for most forms<br/>
      <b>Labels above:</b> Better for short or narrow forms</p>
    <a href="javascript://" class="primary button js_toggleLabelPosition">Switch label position</a>
    
    <hr/>
    
    <div class="formrow">
      <div class="formitem">
        <div class="label req">Salutation</div>
        <div class="ticks">
          <label>
            <input type="radio" name="salutation" value="mrs" required="required"/>
            <span>Mrs.</span>
          </label>
          <label>
            <input type="radio" name="salutation" value="mr" required="required"/>
            <span>Mr.</span>
          </label>
          <label>
            <input type="radio" name="salutation" value="miss" required="required"/>
            <span>Miss</span>
          </label>
          <label>
            <input type="radio" name="salutation" value="jack" required="required"/>
            <span>Jack</span>
          </label>
          <label>
            <input type="radio" name="salutation" value="queen" required="required"/>
            <span>Queen</span>
          </label>
          <label>
            <input type="radio" name="salutation" value="king" required="required"/>
            <span>King</span>
          </label>
          <label>
            <input type="radio" name="salutation" value="sir" required="required"/>
            <span>Sir</span>
          </label>
          <label>
            <input type="radio" name="salutation" value="lord" required="required"/>
            <span>Lord</span>
          </label>
          <label>
            <input type="radio" name="salutation" value="master" required="required"/>
            <span>Master</span>
          </label>
          <label>
            <input type="radio" name="salutation" value="president" required="required"/>
            <span>President</span>
          </label>
        </div>
      </div>
    </div>
    <div class="formrow">
      <label class="label req" for="firstname">First/last name</label>
      <div class="formitem col1of2">
        <label class="label req" for="firstname">First name</label>
        <input type="text" name="firstname" id="firstname" placeholder="Placeholder" required="required" x-autocompletetype="given-name"/>
      </div>
      <div class="formitem col1of2">
        <label class="label req" for="firstname">Last name</label>
        <input type="text" name="lastname" id="lastname" placeholder="... with polyfill" required="required" x-autocompletetype="family-name"/>
      </div>
    </div>
    <div class="formrow">
      <div class="formitem col1of3">
        <label class="label" for="zip">Zip</label>
        <input type="text" name="zip" id="zip" pattern="[0-9]{5}" x-autocompletetype="postal-code"/>
      </div>
      <div class="formitem col2of3">
        <label class="label" for="zip">City</label>
        <input type="text" name="city" id="city" x-autocompletetype="city"/>
      </div>
    </div>
    <div class="formrow">
      <div class="formitem col1of2">
        <label class="label" for="email">Email</label>
        <input type="email" name="email" id="email" x-autocompletetype="email"/>
      </div>
      <div class="formitem col1of2">
        <label class="label" for="phone">Phone... Some more text for testing super long labels. It will happen, clients will do that. Lorem ipsum dolor sit amet, consectetuer adipiscing elit...</label>
        <input type="tel" name="phone" id="phone" x-autocompletetype="tel"/>
      </div>
    </div>
    <div class="formrow">
      <div class="formitem col1of2">
        <label class="label" for="website">Your website, blog, Ihr Google Plus, Twitter or Facebook profile, whatever. Lots of text for testing really long labels, you know...</label>
        <input type="url" name="website" id="website" x-autocompletetype="url"/>
      </div>
      <div class="formitem col1of2">
        <a href="javascript://" class="button">Link button</a>
        <button type="button" class="button disabled" disabled="disabled">Disabled button</button>
      </div>
    </div>
    <div class="formrow">
      <div class="formitem col1of2">
        <label class="label" for="password">Password</label>
        <input type="password" placeholder="Password" name="password" id="password"/>
      </div>
      <div class="formitem col1of2">
        <input type="password" placeholder="Password again" name="passwordagain" id="passwordagain"/>
      </div>
    </div>
    <div class="formrow">
      <div class="formitem">
        <label class="label req" for="message">Message</label>
        <textarea name="message" id="message" cols="40" rows="5" required="required"></textarea>
      </div>
    </div>
    <div class="formrow">
      <div class="formitem">
        <div class="label req">Your rating</div>
        <div class="rating">
          <input type="radio" name="rating" value="5" id="rating5" required="required"/>
          <label for="rating5" class="star">
            <span>5 stars</span>
          </label>
          <input type="radio" name="rating" value="4" id="rating4" required="required"/>
          <label for="rating4" class="star">
            <span>4 stars</span>
          </label>
          <input type="radio" name="rating" value="3" id="rating3" required="required"/>
          <label for="rating3" class="star">
            <span>3 stars</span>
          </label>
          <input type="radio" name="rating" value="2" id="rating2" required="required"/>
          <label for="rating2" class="star">
            <span>2 stars</span>
          </label>
          <input type="radio" name="rating" value="1" id="rating1" required="required"/>
          <label for="rating1" class="star">
            <span>1 star</span>
          </label>
        </div>
      </div>
    </div>
    <div class="formrow">
      <div class="formitem col1of2">
        <label class="label" for="country">Country</label>
        <select name="country" id="country" x-autocompletetype="country-name">
          <option selected="selected">please choose</option>
          <option>U.S.A.</option>
          <option>France</option>
          <option>Italy</option>
          <option>Spain</option>
          <option>Germany</option>
        </select>
      </div>
    </div>
    <div class="formrow">
      <div class="formitem">
        <div class="ticks">
          <label>
            <input type="checkbox" name="terms" class="error" required="required"/>
            <span>Yes, of course I agree to your monstrous <a href="javascript://">terms and conditions</a> and I allow every possible and impossible use of the data I will ever provide you with. This checkbox has an error class preset to simulate backend-side validation. And the text is looong so it makes a great click target and won't ever be read completely.</span>
          </label>
        </div>
        <label for="terms" class="error">Please agree to our terms of service to proceed.</label>
      </div>
    </div>
  </fieldset>
  
  <div class="buttons">
    <div class="forth">
      <input type="reset" value="Reset" class="button"/>
      <button class="primary button">Submit</button>
    </div>
    <div class="back">
      <button class="button" name="back">Back</button>
      <a href="javascript://">Text aligns nicely</a>
    </div>
  </div>
</form>
            
          
!
            
              @charset "UTF-8";

@font-face {
	font-family: 'FontAwesome';
	src: url('http://cdnjs.cloudflare.com/ajax/libs/font-awesome/3.0.2/font/fontawesome-webfont.eot?v=3.0.1');
	src: url('http://cdnjs.cloudflare.com/ajax/libs/font-awesome/3.0.2/font/fontawesome-webfont.eot?#iefix&v=3.0.1') format('embedded-opentype'),
		url('http://cdnjs.cloudflare.com/ajax/libs/font-awesome/3.0.2/font/fontawesome-webfont.woff?v=3.0.1') format('woff'),
		url('http://cdnjs.cloudflare.com/ajax/libs/font-awesome/3.0.2/font/fontawesome-webfont.ttf?v=3.0.1') format('truetype');
	font-weight: normal;
	font-style: normal;
}

@errorcolor: #d23;
@accentcolor: #59d;
@formgutterwidth: 10px;

#restoreFontsize() {
	font-size: 15px;
	line-height: 1.333;
	word-spacing: 0;
}
#removeWhitespace() {
	font-size: .1%; // 0 doesn't always work, e.g. Safari 5/win
	line-height: 0;
	word-spacing: -.3em; // needed by browser with min font-size > 0, e.g. Opera
}
#boxsizing(@model: border-box) {
	-moz-box-sizing: @model;
	box-sizing: @model;
}
#transition(@params: all .2s) {
	-moz-transition: @params;
	-webkit-transition: @params;
	transition: @params;
}
#visuallyHidden() {
	position: absolute;
	z-index: -1;
	opacity: 0;
	width: 1px;
	height: 1px;
	margin: -1px;
	padding: 0;
	border: 0;
	clip: rect(0 0 0 0);
	overflow: hidden;
}

#starOn() {
	&:before {
		font-family: "FontAwesome";
		content: "\f005";
		// content: "\2605";
	}
}
#starOff() {
	&:before {
		font-family: "FontAwesome";
		content: "\f006";
		// content: "\2606";
	}
}

body {
	max-width: 1280px;
	margin: 0 auto;
	padding: 20px;
	background: #f2f2f2;
}
a {
	#transition;
	color: darken(@accentcolor, 8%);
	&:hover {
		color: lighten(@accentcolor, 4%);
	}
}
h1, h2, h3 {
	font-family: Georgia, serif;
}
h1 {
	margin-top: 0;
	text-align: center;
	text-transform: uppercase;
	font-size: 3em;
	letter-spacing: -2px;
	&:after {
		content: "❦";
		display: block;
		margin: .3em 0 1.3em;
		text-align: center;
		font-weight: normal;
	}
	span {
		display: block;
		font-size: 40%;
		text-transform: none;
		font-weight: normal;
		letter-spacing: 0;
	}
}
hr {
	margin: 1em 0;
	border: none;
	border-top: 1px solid #d9d9d9;
}

body,
input,
button,
select,
textarea {
	#boxsizing;
	#restoreFontsize;
	font-family: "Helvetica Neue", Arial, Helvetica, sans-serif;
}
button::-moz-focus-inner,
input::-moz-focus-inner {
    border: 0;
    padding: 0;
}
.placeholder {
	color: #999;
	font-style: italic;
}
:-moz-placeholder { .placeholder; }
:-ms-input-placeholder { .placeholder; }
::-webkit-input-placeholder { .placeholder; }

input[type="text"],
input[type="password"],
input[type="number"],
input[type="tel"],
input[type="email"],
input[type="url"],
input[type="date"],
input[type="time"],
input[type="month"],
input[type="week"],
input[type="datetime"],
input[type="datetime-local"],
select,
textarea {
	display: inline-block;
	margin: 4px 0;
	border: 1px solid #d9d9d9;
	padding: 6px;
	line-height: normal; // allows same height across browsers
	outline: none;
	box-shadow: inset 0 1px 1px rgba(0,0,0,.07);
	background: #fafafa;
	&:hover {
		border-color: #c0c0c0;
	}
	&:focus {
		border-color: @accentcolor;
	}
	&.error {
		border: 1px solid @errorcolor;
		color: @errorcolor;
	}
}
select {
	padding: 5px;
}
textarea {
	overflow-y: auto; // IE fix for consistency
}
fieldset {
	margin: 20px -20px;
	border: none;
	padding: 15px 20px;
	box-shadow: 0 2px 20px rgba(0,0,0,.1);
	background: #fff;
	.legend { // use with headlines; legend element is a bitch to style
		margin-top: 0;
	}
}

// grid
.formrow {
	.label {
		font-size: 12px;
		font-weight: bold;
		&.req:after {
			content: "*";
			color: @errorcolor;
		}
	}
	> .label {
		display: none; // hide shared labels
	}
	.formitem {
		display: inline-block;
		vertical-align: baseline;
		width: 100%;
		padding: 0 0 15px;

		// following rules will be needed in side-by-side layouts, won't hurt here
		// float any child to avoid breaking baseline-alignment of .labels...
		> * {
			float: left;
		}
		// ... except .label, of course
		> .label {
			float: none;
			display: block;
		}

		input[type="text"],
		input[type="password"],
		input[type="number"],
		input[type="tel"],
		input[type="email"],
		input[type="url"],
		input[type="date"],
		input[type="time"],
		input[type="month"],
		input[type="week"],
		input[type="datetime"],
		input[type="datetime-local"],
		select,
		textarea {
			width: 100%;
		}
		label.error {
			clear: left;
			font-size: 11px;
			font-weight: bold;
			color: @errorcolor;
		}
		.ticks {
			padding: 5px 0 0;
			label {
				#transition;
				display: inline-block;
				color: #999;
				&:hover { color: #666; }
				input.checked ~ span { color: #000; } // class "checked" for IE8
				input:checked ~ span { color: #000; } // separate to not confuse IE8

				// version 1
				> span {
					display: block;
					margin: 0 15px 5px 20px;
					cursor: default;
				}
				input[type="checkbox"],
				input[type="radio"] {
					float: left;
					margin: 1px -9px 0 0; // ensure label text doesn't start below input
					&.error ~ span {
						color: @errorcolor;
					}
				}

				// version 2
				// position: relative;
				// padding: 0 15px 5px 20px;
				// input[type="checkbox"],
				// input[type="radio"] {
				// 	position: absolute;
				// 	left: 0;
				// 	margin: 1px;
				// 	&.error ~ span {
				// 		color: @errorcolor;
				// 	}
				// }
			}
		}
		.rating {
			padding: 5px 0 0;
			label {
				#starOff;
				float: right; // direction:rtl and non-static positioning of input breaks in IE8
				width: 42px;
				height: 42px;
				font-size: 42px;
				line-height: 1;
				cursor: pointer;
				span {
					display: none;
				}
			}
			input {
				#visuallyHidden; // display:none would prevent submitting the value
			}
			label:hover,
			label:hover ~ label,
			input.checked ~ label { // class "checked" for IE8
				#starOn;
			}
			input:checked ~ label { // separate to not confuse IE8
				#starOn;
			}
			&:hover {
				input {
					~ label { #starOff; }
				}
				label:hover,
				label:hover ~ label { #starOn; }
			}
		}
	}
}

// respond! IE8 friendly - we just set body classes via JS (no respond.js)
.gt480 {
	body { padding: 40px; }
	fieldset {
		margin: 40px 0;
		padding: 30px 40px;
	}

	.formrow {
		#removeWhitespace;
		margin-right: -@formgutterwidth;
		.formitem {
			#boxsizing;
			#restoreFontsize;
			padding-right: @formgutterwidth;

			&:last-child {
				margin-right: -99px; // needed for older webkits (e.g. Safari 5, Android 2 stock browser)
			}

			// fake element which aligns with other .labels if current formitem has no .label:
			&:before {
				content: "\00a0";
				display: block;
				font-size: 12px;
        font-weight: bold; // same parameters as .label
				line-height: 15px;
				height: 15px;
				margin-top: -15px; // font-size * line-height
			}

			.rating label {
				width: 24px;
				height: 24px;
				font-size: 24px;
			}
		}
		.col1of1 { width: 100%; }
		.col1of2 { width: 50%; }
		.col1of3 { width: 33.33%; }
		.col2of3 { width: 66.66%; }
		.col1of4 { width: 25%; }
		.col3of4 { width: 75%; }
		.col1of5 { width: 20%; }
		.col2of5 { width: 40%; }
		.col3of5 { width: 60%; }
		.col4of5 { width: 80%; }
	}
}
.gt800 {
	body { padding: 80px; }

	.wideform .formrow {
		@labelwidth: 25%;
		@indent: @labelwidth / (100% - @labelwidth) * 100%;
		// #boxsizing;
		// width: 100%;
		padding-left: @labelwidth;
		> .label {
			#boxsizing;
			#restoreFontsize;
			font-size: 12px;
			display: inline-block;
			vertical-align: top;
			margin-left: -@indent;
			padding: 13px @formgutterwidth 20px (@formgutterwidth * @indent / 100%);
			width: @indent;
		}
		.formitem {
			vertical-align: top;
			&:before {
				content: none;
			}
			> .label {
				display: none;
			}
			.ticks,
			.rating {
				padding-top: 10px;
			}
		}
	}
}
@media screen and (min-width:481px) {
	.gt480;
}
@media screen and (min-width:801px) {
	.gt800;
}

// buttons
.button {
	#transition;
	display: inline-block;
	margin: 4px 0;
	border: 1px solid transparent;
	border: 1px solid rgba(0,0,0,.15);
	padding: 7px 16px; // top/bottom should be equal
	text-decoration: none;
	background: #e0e0e0;
	color: #333;
	border-radius: 2px;
	font-size: 12px;
	line-height: normal; // for same height as inputs
	font-weight: bold;
	cursor: pointer;
	outline: none;
	&:hover {
		background: #e5e5e5;
		border-color: rgba(0,0,0,.25);
		color: #000;
	}
	&:focus {
		box-shadow: inset 0 0 0 1px #fff;
	}
	&:active {
		#transition(none);
		background: #e0e0e0;
		box-shadow: inset 0 1px 3px rgba(0,0,0,.2);
	}
	&.disabled {
		background: #f2f2f2;
		border-color: rgba(0,0,0,.1);
		color: #999;
		box-shadow: none;
		cursor: not-allowed;
	}

	&.primary {
		background: @accentcolor;
		color: #fff;
		&:hover {
			background: lighten(@accentcolor, 4%);
			color: #fff;
		}
		&:active {
			background: @accentcolor;
		}
	}
	.buttons &,
	.formitem & {
		margin-right: @formgutterwidth;
	}
}
.buttons {
	text-align: right;
	margin-right: -@formgutterwidth;
	.forth {
		float: right;
	}
	.back {
		text-align: left;
	}
}

            
          
!
            
              // http://lea.verou.me/2009/02/check-if-a-css-property-is-supported/
// http://jsfiddle.net/leaverou/Pmn8m/
// IE fixed and modified from selector to rule to allow for @media query check
function supportsCssRule(rule) {
	var el = document.createElement("div");
	el.innerHTML = ["&shy;", "<style type='text/css'>", rule, "</style>"].join("");
	el = document.body.appendChild(el);
	var style = el.getElementsByTagName("style")[0],
		ret = !!((style.sheet && style.sheet.cssRules) || style.styleSheet.rules)[0];
	document.body.removeChild(el);
	el = null;
	return ret;
}


// :checked polyfill
if (!supportsCssRule(":checked{}")) {
	var checkedPolyfill = function() {
		var $input = $(this);
		if ($input.is(":checked")) {
			if ($input.is(":radio")) {
				$("[name='" + $input.attr("name") + "']").removeClass("checked");
			}
			$input.addClass("checked");
		} else if ($input.is(":checkbox")) {
			$input.removeClass("checked");
		}
	}
	$(document).on("click", ":radio, :checkbox", checkedPolyfill);
	$(":radio, :checkbox").each(checkedPolyfill);
}


// @media query simulation
if (!supportsCssRule("@media min-width:1px{a{}}")) {
	var oldBodyClass = document.body.className;
	var checkWindowWidth = function() {
		if (document.body.clientWidth > 800) {
			document.body.className = oldBodyClass + " gt480 gt800";
		} else if (document.body.clientWidth > 480) {
			document.body.className = oldBodyClass + " gt480";
		} else {
			document.body.className = oldBodyClass;
		}
	};
	checkWindowWidth();
	$(window).resize(checkWindowWidth);
}


// Placeholder polyfill
if (!("placeholder" in document.createElement("input"))) {
	$("input[placeholder], textarea[placeholder]").each(function() {
		var $input = $(this);
		$input.data("placeholder", $input.attr("placeholder"));
		$input.removeAttr("placeholder");

		var $clone = $input.clone();
		if ($clone.attr("type") == "password") {
			$clone = $("<input type='text'/>");
			$clone.attr("class", $input.attr("class"));
			$clone.attr("size", $input.attr("size"));
		}
		$clone.data("placeholder", $input.data("placeholder"));
		$clone.attr("readonly", "readonly");
		$clone.val($input.data("placeholder"));
		$clone.removeAttr("name");
		$input.removeAttr("id");
		$clone.addClass("ignore placeholder");
		if (!!$clone.attr("type") && $clone.attr("type").toLowerCase() == "password") {
			$clone.attr("type", "text");
		}
		$clone.css("display", $input.css("display"));
		$input.data("placeholder-input", $clone);
		$clone.data("orig-input", $input);
		$clone.hide();
		$input.before($clone);

		if (this.value == "") {
			$input.hide();
			$clone.show();
		} else {
			$clone.hide();
			$input.show();
		}

		$clone.on("focus", function() {
			var $placeholder = $(this);
			var $input = $placeholder.data("orig-input");
			$clone.hide();
			$input.show().focus();
		});
		$input.on("blur", function() {
			if (this.value == "") {
				var $placeholder = $input.data("placeholder-input");
				$input.hide();
				$placeholder.show();
			}
		});
	});
}


// create shared labels if not already given
$(".formrow").each(function() {
	var $formrow = $(this);
	if (!$formrow.children(".label").length) {
		var required = false;
		var labels = $.map($formrow.find(".label"), function(el) {
			if (el.className.indexOf("req") > -1)
				required = true;
			return el.innerHTML;
		}).join(", ");
		$formrow.prepend(
			$("<label class='label" + (required ? ' req' : '') + "'/>")
			.attr("for", $formrow.find(".label:first").attr("for"))
			.html(labels)
		);
	}
});


// jQuery Validate
$.validator.addMethod("pattern", function(value, element, param) {
	if (this.optional(element)) {
		return true;
	}
	if (typeof param === 'string') {
		param = new RegExp('^(?:' + param + ')$');
	}
	return param.test(value);
}, "Invalid format.");

$("form").validate({
	errorPlacement: function($err, $el) {
		$err.appendTo($el.closest(".formitem"));
	},
	rules: {
		passwordagain: {
			equalTo: "#password"
		}
	},
	messages: {
		zip: {
			pattern: "Please enter a valid zip code (5 digits)."
		}
	}
});




// Toggle label position - for demonstration
$(".js_toggleLabelPosition").click(function() {
	$("fieldset").toggleClass("wideform");
});

            
          
!
999px
Close

Asset uploading is a PRO feature.

As a PRO member, you can drag-and-drop upload files here to use as resources. Images, Libraries, JSON data... anything you want. You can even edit them anytime, like any other code on CodePen.

Go PRO

Loading ..................

Console