Flipping Login/Sign up Form Only with CSS

来源:转载

Reading Time: 13 minutes

Are you bored with using the same old login and sign up forms? Would you rather enhance the ux of your project? What about creating single card containing both, login and also sign up form? If you think that this is not possible, today I will show you that you are wrong. In this tutorial you will learn to create awesome flipping card with login form on one side and sign up form on the other. And, by the way, no JavaScript is needed. So, are you interested?

You can see the form from this tutorial in action on Codepen and download the source files from Github repository .

Gathering Assets

As a regular reader of this blog, you know what is the first step of every tutorial. We have to put together all necessary assets used in this tutorial. Since this form doesn’t use any framework, the only thing you will need is font awesome to render icons I used for labels. The font used for labels and links is “Open sans” hosted on Google fonts CDN . As always, you can either work locally and download the assets described or work remotely (use CDN) and just include the links in your project. The last two things I used in this tutorial are reset stylesheet and autoprefixer plugin.

Creating the Form Structure

Structure of the form will compose of two main parts, one for login and second for sign up form. Both of these parts will be wrapped inside a container. This container will be a generic div element with class of “form__container”. It will be placed right after hidden checkbox with class , id and name “flipper__checkbox” we are going to use to flip th is form container. This whole thing will be wrapped inside outer-most div with class “wrapper”. Inside the “ form__container ” div will be another two divs , one with class “form__login” and second “form__signup”.

<div class="wrapper"> <input type="checkbox" name="flipper__checkbox" id="flipper__checkbox" class="flipper__checkbox" hidden /> <div class="form__container"> <!-- Front side --> <div class="form__login"></div> <!-- Back side --> <div class="form__signup"></div> </div></div>

Both forms will start with appropriate heading followed by form element to that will contain the login, respectively sign up, form. Form intended for login will contain four fieldset elements. First two fieldsets , for email and password, will compose of label with span , used as a placeholder for icon s provided by font awesome, followed by input element. Remember to use the same id and for attributes to connect the labels with the right input fields. Also, you should use the right input type, “email” and “password”, to use right HTML5 validation and to allow mobile users to use right type of keyboard on their devices.

T hird fieldset is for letting user decide whether to remember his login session or not. This option will compose of checkbox and label . In the same fieldset will be also a link for “Forgot your password?” option floated to the right.

T he last fieldset contain only one input , a button, for submitting the form. I also placed a small element below this fieldset . This element is for users who are not members. It contain s a label wired to our “flipper__checkbox” checkbox and will flip the form on click. That’s all for login form.

HTML s tructure of the login form:

<div class="form__login"> <h1 class="form__header">Login</h1> <form id="loginForm" action="#" method="post" class="form"> <fieldset class="form__group"> <label for="mail"><span class="label__icon fa fa-at"></span></label> <input id="mail" name="mail" class="form__element" type="email" placeholder="Email" required /> </fieldset> <fieldset class="form__group"> <label for="password"><span class="label__icon fa fa-lock"></span></label> <input id="password" name="password" class="form__element" type="password" placeholder="Password" required /> </fieldset> <fieldset class="form__group"> <label for="checkbox"><input id="checkbox" name="checkbox" class="checkbox--forget" type="checkbox" /><span class="icon--checkbox fa fa-check"></span> Remember me</label> <a class="form__link link--right" href="#">Forgot your password?</a> </fieldset> <fieldset class="form__group"> <input class="form__button" type="submit" value="Login" /> </fieldset> <small>Not a member yet? <label for="flipper__checkbox" class="form__link">Create your account</label>.</small> </form></div>

N ext is we have to create a structure for sign up version of the form that will be placed on the “opposite” side. In this case, I used five fieldset elements for “full name”, “email”, “password” and “repeat password” inputs . As in login form, there will be label with span for icon and appropriate input element. The last fieldset will be again used as a container for submit button ( input type “submit”) . Below this fieldset will be also small element, now for users who are actually members. The label within it will be also wired to “ flipper__checkbox ” checkbox .

HTML s tructure of the sign up form:

<div class="form__signup"> <h1 class="form__header">Sign Up</h1> <form id="signupForm" action="#" method="post" class="form"> <fieldset class="form__group"> <label for="signUpName"><span class="label__icon fa fa-user"></span></label> <input id="signUpName" name="signUpName" class="form__element" type="text" placeholder="Full Name" required /> </fieldset> <fieldset class="form__group"> <label for="signUpMail"><span class="label__icon fa fa-at"></span></label> <input id="signUpMail" name="signUpMail" class="form__element" type="email" placeholder="Email" required /> </fieldset> <fieldset class="form__group"> <label for="signUpPassword"><span class="label__icon fa fa-lock"></span></label> <input id="signUpPassword" name="signUpPassword" class="form__element" type="password" placeholder="Password" required /> </fieldset> <fieldset class="form__group"> <label for="signUpPasswordRepeat"><span class="label__icon fa fa-lock"></span></label> <input id="signUpPasswordRepeat" name="signUpPasswordRepeat" class="form__element" type="password" placeholder="Repeat Password" required /> </fieldset> <fieldset class="form__group"> <input class="form__button" type="submit" value="Sign up" /> </fieldset> <small>Are you a member? <label for="flipper__checkbox" class="form__link">Click here to login</label>.</small> </form></div>

That’s it for the HTML part. Here you have the c omplete structure when used together :

<div class="wrapper"> <input type="checkbox" name="flipper__checkbox" id="flipper__checkbox" class="flipper__checkbox" hidden /> <div class="form__container"> <!-- Front side --> <div class="form__login"> <h1 class="form__header">Login</h1> <form action="#" method="post" class="form"> <fieldset class="form__group"> <label for="mail"><span class="label__icon fa fa-at"></span></label> <input id="mail" name="mail" class="form__element" type="email" placeholder="Email" required /> </fieldset> <fieldset class="form__group"> <label for="password"><span class="label__icon fa fa-lock"></span></label> <input id="password" name="password" class="form__element" type="password" placeholder="Password" required /> </fieldset> <fieldset class="form__group"> <label for="checkbox"><input id="checkbox" name="checkbox" class="checkbox--forget" type="checkbox" /><span class="icon--checkbox fa fa-check"></span> Remember me</label> <a class="form__link link--right" href="#">Forgot your password?</a> </fieldset> <fieldset class="form__group"> <input class="form__button" type="submit" value="Login" /> </fieldset> <small>Not a member yet? <label for="flipper__checkbox" class="form__link">Create your account</label>.</small> </form> </div> <!-- Back side --> <div class="form__signup"> <h1 class="form__header">Sign Up</h1> <form action="#" method="post" class="form"> <fieldset class="form__group"> <label for="signUpName"><span class="label__icon fa fa-user"></span></label> <input id="signUpName" name="signUpName" class="form__element" type="text" placeholder="Full Name" required /> </fieldset> <fieldset class="form__group"> <label for="signUpMail"><span class="label__icon fa fa-at"></span></label> <input id="signUpMail" name="signUpMail" class="form__element" type="email" placeholder="Email" required /> </fieldset> <fieldset class="form__group"> <label for="signUpPassword"><span class="label__icon fa fa-lock"></span></label> <input id="signUpPassword" name="signUpPassword" class="form__element" type="password" placeholder="Password" required /> </fieldset> <fieldset class="form__group"> <label for="signUpPasswordRepeat"><span class="label__icon fa fa-lock"></span></label> <input id="signUpPasswordRepeat" name="signUpPasswordRepeat" class="form__element" type="password" placeholder="Repeat Password" required /> </fieldset> <fieldset class="form__group"> <input class="form__button" type="submit" value="Sign up" /> </fieldset> <small>Are you a member? <label for="flipper__checkbox" class="form__link">Click here to login</label>.</small> </form> </div> </div></div> Adding Styles

The first I did was to create a function , remy, to convert pixels to rems and define few variables for colors and border-radius . To customize the form to suit your project, change these variables.

// [email protected] remy($value) { @return ($value / 16px) * 1rem;}// Variables:$color--text: #6b8d9f;$color--border: #e1e1e1;$radius: 2px;

Next step is to style thebase. Meaning adding min-height to the html , body , setting the font , color and background-color of the body . Let’s also add a transition for links , buttons . Jut for case, let’s add a fallback for IE 9 and older that doesn’t support hidden attribute. The last thing to include in base part of stylesheet if some styles for small element.

Note: Remember, “reset” stylesheet will reset the font-size of small element.

/** * Base */html,body {min-height: 100%;}body { font: 100% / 1.414 "Open sans", "Trebuchet MS", arial, sans-serif; color: $color--text; background: #f1f1f1;}a,input[type="submit"],.form__link {transition: all .25s ease;}/* Fallback for hidden attribute for older browsers – IE9 and lower */hidden {display: none;}small { display: block; margin-top: 1rem; font-size: remy(13px); text-align: center;}

To make the whole thing more classy, I added tiny animated bar on the top of forms. Thisanimation will change the background-position of gradient background used for the bar .

/** * Animation keyframes */@-webkit-keyframes gradient { 0%{background-position:0% 50%} 50%{background-position:100% 50%} 100%{background-position:0% 50%}}@-moz-keyframes gradient { 0%{background-position:0% 50%} 50%{background-position:100% 50%} 100%{background-position:0% 50%}}@keyframes gradient { 0%{background-position:0% 50%} 50%{background-position:100% 50%} 100%{background-position:0% 50%}}

Next comes the layout. This means sizing the “wrapper” div and centering in with margins and setting the entire animation area’s perspective . The “ form__container ” is the element that will flip, spinning 180 degrees, when the “ flipper__checkbox ” checkbox is checked. If you want to changing the rotation to reverse direction, just change the rotateY value from “180deg” to “-180deg”. You can control the transition speed by changing transition in “. form__container ” declaration block .

The flipping effect is created by positioning t he front (.form__login) and back (.form__signup) elements absolutely so they will basically overlay each other in the same position (top left corner) . In order to n ot display the back side of the form during the animation you will need to set the backface-visibility of these elements to “hidden”. To place the form for “ form__login” on top, you have to set its z-index higher than of the “ form__signup ”. The last step is to rotate “ form__signup ” for 180 degrees, so as to act as the back. Otherwise, it would be mirrored and a bit hard to use.

N ote: the “ margin-left: -3.95rem” declaration used in “. form__signup” declaration block is to “reset” left padding. Without this fix, the “ form__signup” element would always move for 3.95rems to the left. Simply said, the form cards would not be at the same place.

/** * Layout */.wrapper { position: relative; margin-top: 3rem; margin-right: auto; margin-left: auto; width: remy(320px); background: #fff; box-shadow: 3px 3px 32px rgba(0,0,0,.25); perspective: 1000;}.flipper__checkbox:checked + .form__container {transform: rotateY(180deg);}.form__container { position: relative; width: 100%; height: 100%; transform-style: preserve-3d; transition: transform .25s ease;}.form__container--inner {padding: 2rem;}.form__login,.form__signup { position: absolute; top: 0; left: 0; margin: 0; width: 100%; backface-visibility: hidden; background: #fff; box-shadow: 3px 3px 32px rgba(0,0,0,.25); &:after { content: ""; position: absolute; top: 0; left: 0; width: 100%; height: 6px; background: linear-gradient(270deg, #2196f3, lighten(#2196f3, 25%)); background-size: 400% 400%; animation: gradient 2s ease infinite; }}.form__login { z-index: 2; padding: 2rem; /* for firefox 31 */ transform: rotateY(0deg);}.form__signup { padding: 2rem; margin-left: -3.95rem; transform: rotateY(180deg);}

The last part of style section of this tutorial is to create some custom styles for form.

/** * Form default styling */.form__header { margin-bottom: 2rem; font-size: 1.618rem; font-weight: 700; text-align: center;}.form__group:nth-of-type(n+2) {margin-top: 1.5rem;}.label__icon { padding: .97rem 0; float: left; width: 3rem; font-size: 1.25rem; text-align: center; color: rgba(107,141,159,.25); border-top: 1px solid $color--border; border-bottom: 1px solid $color--border; border-left: 1px solid $color--border; border-top-left-radius: $radius; border-bottom-left-radius: $radius;}.form__element { padding-top: 1.11rem; padding-right: 1rem; padding-bottom: 1.11rem; width: remy(254px); border-top: 1px solid $color--border; border-right: 1px solid $color--border; border-bottom: 1px solid $color--border; border-left: 0; border-top-right-radius: $radius; border-bottom-right-radius: $radius; &:focus {outline: 0;}}[type="checkbox"] { position: relative; margin-right: .5rem; &:after { content: ""; position: absolute; top: 0; left: 0; border: 1px solid $color--border; width: 16px; height: 16px; background: #fff; border-radius: $radius; cursor: pointer; }}label[for="checkbox"] { position: relative; font-size: .9rem; font-weight: 700;}.checkbox--forget:checked + .icon--checkbox { opacity: 1; transform: scale(1);}.icon--checkbox { position: absolute; top: 4px; left: 6px; opacity: 0; cursor: pointer; transition: all .35s cubic-bezier(.91,.8,.84,2.81); transform: scale(0);}.form__link { font-size: .8rem; font-weight: bold; text-decoration: underline; color: rgba($color--text,.75); cursor: pointer; &:focus, &:hover {color: rgba($color--text,.95);}}.link--right {float: right;}.form__button { padding-top: 1rem; padding-bottom: 1rem; display: inline-block; width: 100%; font-size: 1rem; font-weight: 700; text-align: center; color: #fff; background-color: #2196f3; border: 0; border-radius: $radius; cursor: pointer; &:focus, &:hover {background-color: darken(#2196f3, 13%);}}

When put together, the code in s ass stylesheet is following :

// [email protected] remy($value) { @return ($value / 16px) * 1rem;}// Variables:$color--text: #6b8d9f;$color--border: #e1e1e1;$radius: 2px;/** * Base */html,body {min-height: 100%;}body { font: 100% / 1.414 "Open sans", "Trebuchet MS", arial, sans-serif; color: $color--text; background: #f1f1f1;}a,input[type="submit"],.form__link {transition: all .25s ease;}hidden {display: none;}small { display: block; margin-top: 1rem; font-size: remy(13px); text-align: center;}/** * Animation keyframes */@-webkit-keyframes gradient { 0%{background-position:0% 50%} 50%{background-position:100% 50%} 100%{background-position:0% 50%}}@-moz-keyframes gradient { 0%{background-position:0% 50%} 50%{background-position:100% 50%} 100%{background-position:0% 50%}}@keyframes gradient { 0%{background-position:0% 50%} 50%{background-position:100% 50%} 100%{background-position:0% 50%}}/** * Layout */.wrapper { position: relative; margin-top: 3rem; margin-right: auto; margin-left: auto; width: remy(320px); background: #fff; box-shadow: 3px 3px 32px rgba(0,0,0,.25); perspective: 1000;}.flipper__checkbox:checked + .form__container {transform: rotateY(180deg);}.form__container { position: relative; width: 100%; height: 100%; transform-style: preserve-3d; transition: transform .25s ease;}.form__container--inner {padding: 2rem;}.form__login,.form__signup { position: absolute; top: 0; left: 0; margin: 0; width: 100%; backface-visibility: hidden; background: #fff; box-shadow: 3px 3px 32px rgba(0,0,0,.25); &:after { content: ""; position: absolute; top: 0; left: 0; width: 100%; height: 6px; background: linear-gradient(270deg, #2196f3, lighten(#2196f3, 25%)); background-size: 400% 400%; animation: gradient 2s ease infinite; }}.form__login { z-index: 2; padding: 2rem; /* for firefox 31 */ transform: rotateY(0deg);}.form__signup { padding: 2rem; margin-left: -3.95rem; transform: rotateY(180deg);}/** * Form default styling */.form__header { margin-bottom: 2rem; font-size: 1.618rem; font-weight: 700; text-align: center;}.form__group:nth-of-type(n+2) {margin-top: 1.5rem;}.label__icon { padding: .97rem 0; float: left; width: 3rem; font-size: 1.25rem; text-align: center; color: rgba(107,141,159,.25); border-top: 1px solid $color--border; border-bottom: 1px solid $color--border; border-left: 1px solid $color--border; border-top-left-radius: $radius; border-bottom-left-radius: $radius;}.form__element { padding-top: 1.11rem; padding-right: 1rem; padding-bottom: 1.11rem; width: remy(254px); border-top: 1px solid $color--border; border-right: 1px solid $color--border; border-bottom: 1px solid $color--border; border-left: 0; border-top-right-radius: $radius; border-bottom-right-radius: $radius; &:focus {outline: 0;}}[type="checkbox"] { position: relative; margin-right: .5rem; &:after { content: ""; position: absolute; top: 0; left: 0; border: 1px solid $color--border; width: 16px; height: 16px; background: #fff; border-radius: $radius; cursor: pointer; }}label[for="checkbox"] { position: relative; font-size: .9rem; font-weight: 700;}.checkbox--forget:checked + .icon--checkbox { opacity: 1; transform: scale(1);}.icon--checkbox { position: absolute; top: 4px; left: 6px; opacity: 0; cursor: pointer; transition: all .35s cubic-bezier(.91,.8,.84,2.81); transform: scale(0);}.form__link { font-size: .8rem; font-weight: bold; text-decoration: underline; color: rgba($color--text,.75); cursor: pointer; &:focus, &:hover {color: rgba($color--text,.95);}}.link--right {float: right;}.form__button { padding-top: 1rem; padding-bottom: 1rem; display: inline-block; width: 100%; font-size: 1rem; font-weight: 700; text-align: center; color: #fff; background-color: #2196f3; border: 0; border-radius: $radius; cursor: pointer; &:focus, &:hover {background-color: darken(#2196f3, 13%);}}

If you are not familiar withSasspreprocessor, here you have CSS version of the code:

/** * Base */html,body { min-height: 100%;}body { font: 100% / 1.414 "Open sans", "Trebuchet MS", arial, sans-serif; color: #6b8d9f; background: #f1f1f1;}a,input[type="submit"],.form__link { -webkit-transition: all .25s ease; transition: all .25s ease;}hidden { display: none;}small { display: block; margin-top: 1rem; font-size: 0.8125rem; text-align: center;}/** * Animation keyframes */@-webkit-keyframes gradient { 0% { background-position: 0% 50%; } 50% { background-position: 100% 50%; } 100% { background-position: 0% 50%; }}@keyframes gradient { 0% { background-position: 0% 50%; } 50% { background-position: 100% 50%; } 100% { background-position: 0% 50%; }}/** * Layout */.wrapper { position: relative; margin-top: 3rem; margin-right: auto; margin-left: auto; width: 20rem; background: #fff; box-shadow: 3px 3px 32px rgba(0, 0, 0, 0.25); -webkit-perspective: 1000; perspective: 1000;}.flipper__checkbox:checked + .form__container { -webkit-transform: rotateY(180deg); transform: rotateY(180deg);}.form__container { position: relative; width: 100%; height: 100%; -webkit-transform-style: preserve-3d; transform-style: preserve-3d; -webkit-transition: -webkit-transform .25s ease; transition: transform .25s ease;}.form__container--inner { padding: 2rem;}.form__login,.form__signup { position: absolute; top: 0; left: 0; margin: 0; width: 100%; -webkit-backface-visibility: hidden; backface-visibility: hidden; background: #fff; box-shadow: 3px 3px 32px rgba(0, 0, 0, 0.25);}.form__login:after,.form__signup:after { content: ""; position: absolute; top: 0; left: 0; width: 100%; height: 6px; background: -webkit-linear-gradient(180deg, #2196f3, #9acffa); background: linear-gradient(270deg, #2196f3, #9acffa); background-size: 400% 400%; -webkit-animation: gradient 2s ease infinite; animation: gradient 2s ease infinite;}.form__login { z-index: 2; padding: 2rem; /* for firefox 31 */ -webkit-transform: rotateY(0deg); transform: rotateY(0deg);}.form__signup { padding: 2rem; margin-left: -3.95rem; -webkit-transform: rotateY(180deg); transform: rotateY(180deg);}/** * Form default styling */.form__header { margin-bottom: 2rem; font-size: 1.618rem; font-weight: 700; text-align: center;}.form__group:nth-of-type(n+2) { margin-top: 1.5rem;}.label__icon { padding: .97rem 0; float: left; width: 3rem; font-size: 1.25rem; text-align: center; color: rgba(107, 141, 159, 0.25); border-top: 1px solid #e1e1e1; border-bottom: 1px solid #e1e1e1; border-left: 1px solid #e1e1e1; border-top-left-radius: 2px; border-bottom-left-radius: 2px;}.form__element { padding-top: 1.11rem; padding-right: 1rem; padding-bottom: 1.11rem; width: 15.875rem; border-top: 1px solid #e1e1e1; border-right: 1px solid #e1e1e1; border-bottom: 1px solid #e1e1e1; border-left: 0; border-top-right-radius: 2px; border-bottom-right-radius: 2px;}.form__element:focus { outline: 0;}[type="checkbox"] { position: relative; margin-right: .5rem;}[type="checkbox"]:after { content: ""; position: absolute; top: 0; left: 0; border: 1px solid #e1e1e1; width: 16px; height: 16px; background: #fff; border-radius: 2px; cursor: pointer;}label[for="checkbox"] { position: relative; font-size: .9rem; font-weight: 700;}.checkbox--forget:checked + .icon--checkbox { opacity: 1; -webkit-transform: scale(1); -ms-transform: scale(1); transform: scale(1);}.icon--checkbox { position: absolute; top: 4px; left: 6px; opacity: 0; cursor: pointer; -webkit-transition: all 0.35s cubic-bezier(0.91, 0.8, 0.84, 2.81); transition: all 0.35s cubic-bezier(0.91, 0.8, 0.84, 2.81); -webkit-transform: scale(0); -ms-transform: scale(0); transform: scale(0);}.form__link { font-size: .8rem; font-weight: bold; text-decoration: underline; color: rgba(107, 141, 159, 0.75); cursor: pointer;}.form__link:focus, .form__link:hover { color: rgba(107, 141, 159, 0.95);}.link--right { float: right;}.form__button { padding-top: 1rem; padding-bottom: 1rem; display: inline-block; width: 100%; font-size: 1rem; font-weight: 700; text-align: center; color: #fff; background-color: #2196f3; border: 0; border-radius: 2px; cursor: pointer;}.form__button:focus, .form__button:hover { background-color: #0b74c7;} Final Words

Here you have awesome flipping form for your projects. The best of it is that you no longer need to create more space for two separate forms. What’s more, it works great even without JavaScript. However, there is one thing to keep in mind while implementing this design. Yes, you guessed it right. It’s about the support of IE browser. IE version 8 and 9 doesn’t support CSS3 3D transform at all. The same thing for Opera Mini (mobile browser). IE 10 and 11 doesn’t support “preserve-3d” property. Meaning, use modernizr and similar feature detection libraries and create fallbacks.

T hank you for your time. Now, if you like this tutorial, please share it .



分享给朋友:
您可能感兴趣的文章:
随机阅读: