<h1>JS-Less Floaty Labels</h1>
<div class="inputs">
<label class="input">
<input class="input__field" type="email" placeholder="somoething" value="" />
<span class="input__label">Some fancy label man</span>
<span class="input__error">Something went horribly wrong</span>
<span class="input__info">Sometimes there is something here</span>
</label>
<label class="input">
<input required class="input__field" type="text" placeholder=" " value="" />
<span class="input__label">Some dancy label man</span>
</label>
<label class="input">
<input class="input__field" type="text" placeholder=" " value="Has a value already" />
<span class="input__label">Some dancy label man</span>
</label>
</div>
<p>The JS is only needed for MS Edge (as long as its not Chromeium yet)</p>
@import url('https://rsms.me/inter/inter.css');
:root, input {
--font: 'Inter var', sans-serif;
font-family: var(--font);
font-feature-settings: "dlig" 0, "numr" 0, "dnom" 0, "tnum" , "case" 0, "zero" 0, "frac", "sups" 0, "subs" 0, "cpsp" 0, "salt" 0, "ss01", "ss02" 0, "cv01" 0, "cv02" 0, "cv03" 0, "cv04" 0, "cv05" 0, "cv06" 0, "cv07" 0, "cv08" 0, "cv09" 0, "cv10" 0, "calt", "liga", "kern";
}
:root {
padding: 1rem;
}
p {
margin-top: 4rem;
}
.inputs {
--size-inline: 1rem;
display: flex;
flex-wrap: wrap;
margin-left: calc(var(--size-inline) * -1);
& > .input {
flex: 1 0 calc(50% - var(--size-inline));
margin-left: var(--size-inline);
width: 50%;
}
}
.input {
--size-bezel-top: 1.4rem;
--size-bezel: .4rem;
--color-bg: transparent;
--color-bg--active: #aaf0d1;
position: relative;
display: block;
background: var(--color-bg);
margin-top: 1rem;
&__field {
opacity: 0;
display: block;
width: 100%;
box-sizing: border-box;
border: none;
background: transparent;
padding: var(--size-bezel-top) var(--size-bezel) var(--size-bezel);
box-shadow: 0 .2rem 0 0 #000;
transition: 200ms opacity ease-out;
&:focus {
background: var(--color-bg--active);
}
&:not(:placeholder-shown),
.placeHolderNotSown,
&:focus {
opacity: 1;
transition: 200ms opacity ease-out 100ms;
outline: none;
}
&:not(:placeholder-shown) + .input__label,
.placeHolderNotSown + .input__label,
&:focus + .input__label {
transform: scale(.8) translateY(-50%);
}
&:invalid:not(:placeholder-shown),
.placeHolderNotSown:invalid {
& + .input__label + .input__error {
display: block;
}
}
}
&__label {
position: absolute;
left: 0;
right: 0;
top: 0;
box-sizing: border-box;
padding: var(--size-bezel-top) var(--size-bezel) var(--size-bezel);
transform-origin: 0 50%;
transition: 200ms transform ease-out;
}
&__error,
&__info {
display: block;
padding: calc(2 * var(--size-bezel)) var(--size-bezel);
font-size: .6em;
}
&__error {
display: none;
background: red;
color: #fff;
}
}
View Compiled
// edge fallback, works without it in IE11
function checkIfEmpty (e) {
const $target = e.target;
if ($target.value) {
$target.classList.remove('placeHolderNotSown');
} else {
$target.classList.add('placeHolderNotSown');
}
}
document.addEventListener('focus', checkIfEmpty, true);
document.addEventListener('blur', checkIfEmpty, true);
View Compiled
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.