Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
A Better Form™

A Better Form™

Don't mind this. I made it because I was mad about a specific thing that I saw on the Internet.

A Pen by EJ Mason on CodePen.

License.

<div class="form-wrapper">
<h1 id="form-heading">Register Now</h1>
<form id="form" class="custom-form stack-small" aria-labelledby="form-heading">
<div class="custom-form-group">
<label for="first-name" class="custom-label">
First name
</label>
<input type="text" id="first-name" class="custom-input" name="firstName" v-model="firstName" />
</div>
<div class="custom-form-group">
<label for="last-name" class="custom-label">
Last name
</label>
<input type="text" id="last-name" name="lastName" class="custom-input" v-model="lastName" />
</div>
<button class="custom-button" type="submit">Submit</button>
</form>
</div>
const FORM_INIT_OPTS = {
el: "#form",
data() {
return {
firstName: "",
lastName: ""
};
},
computed: {
classObj() {
return;
}
},
methods: {
hasError: function(fieldName = "") {
return {
"custom-form-group__error":
this.errors && this.erros[fieldName].hasError
};
}
}
};
const FIELD_PROPS_MIXIN = {
is: String,
id: {
type: String,
required: true
},
name: {
type: String,
required: true
},
value: {
type: String,
required: true
},
class: String
}
const FIELD_INIT_OPTS = {
template: `
<label for="first-name" class="custom-label">
First name
</label>
<component type="text" id="first-name" class="custom-input" name="firstName" v-model="firstName" />
</div>`,
mixins: [ FIELD_PROPS_MIXIN ]
},
const vm = new Vue(FORM_INIT_OPTS);
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.min.js"></script>
$system-font-stack: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji",
"Segoe UI Symbol";
$color-body: #0b0c0c;
$color-primary: #00703c;
$color-primary__hover: #005a30;
$color-focus: #fd0;
$color-error: #d4351c;
/**
* RESETS
*/
html {
font-size: 10px;
font-size: 62.5%;
}
body {
font-size: 1.6rem;
font-family: $system-font-stack;
line-height: 1.25;
}
/**
* END RESETS
*/
.form-wrapper {
width: 95%;
max-width: 30rem;
margin: 0 auto;
}
/*
* LAYOUT
*/
[class^="stack"] > * {
margin-top: 0;
margin-bottom: 0;
}
.stack-small > * + * {
margin-top: 1.25rem;
}
.stack-large > * + * {
margin-top: 2.5rem;
}
/*
* END LAYOUT
*/
/*
* GLOBALS
*/
:focus {
outline: 3px dashed $color-focus;
outline-offset: 0;
}
button:-moz-focusring,
[type="button"]:-moz-focusring,
[type="reset"]:-moz-focusring,
[type="submit"]:-moz-focusring {
outline: none;
}
/*End resets*/
/*custom form styles*/
.custom-form-group {
&.custom-form-group__error {
padding-left: 1.5rem;
border-left: 0.5rem solid $color-error;
& > [class*="error"] {
display: block;
}
}
}
.custom-input,
.custom-button {
font-family: inherit;
font-size: 100%;
line-height: 1.15;
appearance: none;
border-radius: 0;
}
.custom-label {
display: block;
margin-bottom: 0.5rem;
}
.custom-input {
width: 100%;
border: 2px solid $color-body;
padding: 5px;
&:focus {
box-shadow: inset 0 0 0 2px;
}
}
.custom-button {
display: inline-block;
position: relative;
width: 100%;
padding: 0.8rem 1rem 0.7rem;
border: 2px solid transparent;
color: #fff;
background-color: $color-primary;
box-shadow: 0 2px 0 $color-body;
text-align: center;
vertical-align: top;
cursor: pointer;
&:active {
top: 2px;
}
&:hover {
background-color: $color-primary__hover;
}
&:focus {
outline: 3px solid transparent;
border-color: $color-focus;
box-shadow: inset 0 0 0 1px $color-focus;
}
&:focus:not(:active):not(:hover) {
background-color: $color-focus;
color: $color-body;
box-shadow: 0 2px 0 $color-body;
}
}
.custom-form-error {
color: $color-error;
font-weight: bold;
display: none;
margin-bottom: 1.5rem;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/modern-normalize/0.6.0/modern-normalize.min.css" rel="stylesheet" />
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment