Just a handy login-signup modal window
Article and download on Cody: http://codyhouse.co/gem/loginsignup-modal-window/
<body> | |
<header role="banner"> | |
<div id="cd-logo"><a href="#0"><img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/148866/cd-logo_1.svg" alt="Logo"></a></div> | |
<nav class="main-nav"> | |
<ul> | |
<!-- inser more links here --> | |
<li><a class="cd-signin" href="#0">Sign in</a></li> | |
<li><a class="cd-signup" href="#0">Sign up</a></li> | |
</ul> | |
</nav> | |
</header> | |
<div class="cd-user-modal"> <!-- this is the entire modal form, including the background --> | |
<div class="cd-user-modal-container"> <!-- this is the container wrapper --> | |
<ul class="cd-switcher"> | |
<li><a href="#0">Sign in</a></li> | |
<li><a href="#0">New account</a></li> | |
</ul> | |
<div id="cd-login"> <!-- log in form --> | |
<form class="cd-form"> | |
<p class="fieldset"> | |
<label class="image-replace cd-email" for="signin-email">E-mail</label> | |
<input class="full-width has-padding has-border" id="signin-email" type="email" placeholder="E-mail"> | |
<span class="cd-error-message">Error message here!</span> | |
</p> | |
<p class="fieldset"> | |
<label class="image-replace cd-password" for="signin-password">Password</label> | |
<input class="full-width has-padding has-border" id="signin-password" type="text" placeholder="Password"> | |
<a href="#0" class="hide-password">Hide</a> | |
<span class="cd-error-message">Error message here!</span> | |
</p> | |
<p class="fieldset"> | |
<input type="checkbox" id="remember-me" checked> | |
<label for="remember-me">Remember me</label> | |
</p> | |
<p class="fieldset"> | |
<input class="full-width" type="submit" value="Login"> | |
</p> | |
</form> | |
<p class="cd-form-bottom-message"><a href="#0">Forgot your password?</a></p> | |
<!-- <a href="#0" class="cd-close-form">Close</a> --> | |
</div> <!-- cd-login --> | |
<div id="cd-signup"> <!-- sign up form --> | |
<form class="cd-form"> | |
<p class="fieldset"> | |
<label class="image-replace cd-username" for="signup-username">Username</label> | |
<input class="full-width has-padding has-border" id="signup-username" type="text" placeholder="Username"> | |
<span class="cd-error-message">Error message here!</span> | |
</p> | |
<p class="fieldset"> | |
<label class="image-replace cd-email" for="signup-email">E-mail</label> | |
<input class="full-width has-padding has-border" id="signup-email" type="email" placeholder="E-mail"> | |
<span class="cd-error-message">Error message here!</span> | |
</p> | |
<p class="fieldset"> | |
<label class="image-replace cd-password" for="signup-password">Password</label> | |
<input class="full-width has-padding has-border" id="signup-password" type="text" placeholder="Password"> | |
<a href="#0" class="hide-password">Hide</a> | |
<span class="cd-error-message">Error message here!</span> | |
</p> | |
<p class="fieldset"> | |
<input type="checkbox" id="accept-terms"> | |
<label for="accept-terms">I agree to the <a href="#0">Terms</a></label> | |
</p> | |
<p class="fieldset"> | |
<input class="full-width has-padding" type="submit" value="Create account"> | |
</p> | |
</form> | |
<!-- <a href="#0" class="cd-close-form">Close</a> --> | |
</div> <!-- cd-signup --> | |
<div id="cd-reset-password"> <!-- reset password form --> | |
<p class="cd-form-message">Lost your password? Please enter your email address. You will receive a link to create a new password.</p> | |
<form class="cd-form"> | |
<p class="fieldset"> | |
<label class="image-replace cd-email" for="reset-email">E-mail</label> | |
<input class="full-width has-padding has-border" id="reset-email" type="email" placeholder="E-mail"> | |
<span class="cd-error-message">Error message here!</span> | |
</p> | |
<p class="fieldset"> | |
<input class="full-width has-padding" type="submit" value="Reset password"> | |
</p> | |
</form> | |
<p class="cd-form-bottom-message"><a href="#0">Back to log-in</a></p> | |
</div> <!-- cd-reset-password --> | |
<a href="#0" class="cd-close-form">Close</a> | |
</div> <!-- cd-user-modal-container --> | |
</div> <!-- cd-user-modal --> | |
</body> |
Just a handy login-signup modal window
Article and download on Cody: http://codyhouse.co/gem/loginsignup-modal-window/
jQuery(document).ready(function($){ | |
var $form_modal = $('.cd-user-modal'), | |
$form_login = $form_modal.find('#cd-login'), | |
$form_signup = $form_modal.find('#cd-signup'), | |
$form_forgot_password = $form_modal.find('#cd-reset-password'), | |
$form_modal_tab = $('.cd-switcher'), | |
$tab_login = $form_modal_tab.children('li').eq(0).children('a'), | |
$tab_signup = $form_modal_tab.children('li').eq(1).children('a'), | |
$forgot_password_link = $form_login.find('.cd-form-bottom-message a'), | |
$back_to_login_link = $form_forgot_password.find('.cd-form-bottom-message a'), | |
$main_nav = $('.main-nav'); | |
//open modal | |
$main_nav.on('click', function(event){ | |
if( $(event.target).is($main_nav) ) { | |
// on mobile open the submenu | |
$(this).children('ul').toggleClass('is-visible'); | |
} else { | |
// on mobile close submenu | |
$main_nav.children('ul').removeClass('is-visible'); | |
//show modal layer | |
$form_modal.addClass('is-visible'); | |
//show the selected form | |
( $(event.target).is('.cd-signup') ) ? signup_selected() : login_selected(); | |
} | |
}); | |
//close modal | |
$('.cd-user-modal').on('click', function(event){ | |
if( $(event.target).is($form_modal) || $(event.target).is('.cd-close-form') ) { | |
$form_modal.removeClass('is-visible'); | |
} | |
}); | |
//close modal when clicking the esc keyboard button | |
$(document).keyup(function(event){ | |
if(event.which=='27'){ | |
$form_modal.removeClass('is-visible'); | |
} | |
}); | |
//switch from a tab to another | |
$form_modal_tab.on('click', function(event) { | |
event.preventDefault(); | |
( $(event.target).is( $tab_login ) ) ? login_selected() : signup_selected(); | |
}); | |
//hide or show password | |
$('.hide-password').on('click', function(){ | |
var $this= $(this), | |
$password_field = $this.prev('input'); | |
( 'password' == $password_field.attr('type') ) ? $password_field.attr('type', 'text') : $password_field.attr('type', 'password'); | |
( 'Hide' == $this.text() ) ? $this.text('Show') : $this.text('Hide'); | |
//focus and move cursor to the end of input field | |
$password_field.putCursorAtEnd(); | |
}); | |
//show forgot-password form | |
$forgot_password_link.on('click', function(event){ | |
event.preventDefault(); | |
forgot_password_selected(); | |
}); | |
//back to login from the forgot-password form | |
$back_to_login_link.on('click', function(event){ | |
event.preventDefault(); | |
login_selected(); | |
}); | |
function login_selected(){ | |
$form_login.addClass('is-selected'); | |
$form_signup.removeClass('is-selected'); | |
$form_forgot_password.removeClass('is-selected'); | |
$tab_login.addClass('selected'); | |
$tab_signup.removeClass('selected'); | |
} | |
function signup_selected(){ | |
$form_login.removeClass('is-selected'); | |
$form_signup.addClass('is-selected'); | |
$form_forgot_password.removeClass('is-selected'); | |
$tab_login.removeClass('selected'); | |
$tab_signup.addClass('selected'); | |
} | |
function forgot_password_selected(){ | |
$form_login.removeClass('is-selected'); | |
$form_signup.removeClass('is-selected'); | |
$form_forgot_password.addClass('is-selected'); | |
} | |
//REMOVE THIS - it's just to show error messages | |
$form_login.find('input[type="submit"]').on('click', function(event){ | |
event.preventDefault(); | |
$form_login.find('input[type="email"]').toggleClass('has-error').next('span').toggleClass('is-visible'); | |
}); | |
$form_signup.find('input[type="submit"]').on('click', function(event){ | |
event.preventDefault(); | |
$form_signup.find('input[type="email"]').toggleClass('has-error').next('span').toggleClass('is-visible'); | |
}); | |
//IE9 placeholder fallback | |
//credits http://www.hagenburger.net/BLOG/HTML5-Input-Placeholder-Fix-With-jQuery.html | |
if(!Modernizr.input.placeholder){ | |
$('[placeholder]').focus(function() { | |
var input = $(this); | |
if (input.val() == input.attr('placeholder')) { | |
input.val(''); | |
} | |
}).blur(function() { | |
var input = $(this); | |
if (input.val() == '' || input.val() == input.attr('placeholder')) { | |
input.val(input.attr('placeholder')); | |
} | |
}).blur(); | |
$('[placeholder]').parents('form').submit(function() { | |
$(this).find('[placeholder]').each(function() { | |
var input = $(this); | |
if (input.val() == input.attr('placeholder')) { | |
input.val(''); | |
} | |
}) | |
}); | |
} | |
}); | |
//credits http://css-tricks.com/snippets/jquery/move-cursor-to-end-of-textarea-or-input/ | |
jQuery.fn.putCursorAtEnd = function() { | |
return this.each(function() { | |
// If this function exists... | |
if (this.setSelectionRange) { | |
// ... then use it (Doesn't work in IE) | |
// Double the length because Opera is inconsistent about whether a carriage return is one character or two. Sigh. | |
var len = $(this).val().length * 2; | |
this.setSelectionRange(len, len); | |
} else { | |
// ... otherwise replace the contents with itself | |
// (Doesn't work in Google Chrome) | |
$(this).val($(this).val()); | |
} | |
}); | |
}; |
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script> |
@import "bourbon"; | |
// variables - colors | |
$main-text: #505260; // main text | |
$background: #fff; // body background color | |
$color-1: #343642; // blue-dark | |
$color-2: #2f889a; // blue-light | |
$color-3: #d2d8d8; // grey | |
$red: #d76666; // error messages | |
// variables - fonts | |
$primary-font: 'PT Sans', sans-serif; | |
// variables - z-index | |
$header-zindex: 2; | |
$modal-zindex: 3; | |
// variables - header | |
$header-height-S: 50px; | |
$header-height-M: 80px; | |
// mixins - rem fallback - credits: http://zerosixthree.se/ | |
@function calculateRem($size) { | |
$remSize: $size / 16px; | |
@return $remSize * 1rem; | |
} | |
@mixin font-size($size) { | |
font-size: $size; | |
font-size: calculateRem($size); | |
} | |
// mixins - center vertically and/or horizontally an absolute positioned element | |
@mixin center($xy:xy) { | |
@if $xy == xy { | |
left: 50%; | |
top: 50%; | |
bottom: auto; | |
right: auto; | |
@include transform(translateX(-50%) translateY(-50%)); | |
} | |
@else if $xy == x { | |
left: 50%; | |
right: auto; | |
@include transform(translateX(-50%)); | |
} | |
@else if $xy == y { | |
top: 50%; | |
bottom: auto; | |
@include transform(translateY(-50%)); | |
} | |
} | |
// mixins - border radius | |
@mixin border-radius($radius:.25em) { | |
border-radius: $radius; | |
} | |
// layout - breakpoints | |
$S: 600px; | |
$M: 768px; | |
$L: 1170px; | |
// layout - media queries | |
@mixin MQ($canvas) { | |
@if $canvas == S { | |
@media only screen and (min-width: $S) { @content; } | |
} | |
@else if $canvas == M { | |
@media only screen and (min-width: $M) { @content; } | |
} | |
@else if $canvas == L { | |
@media only screen and (min-width: $L) { @content; } | |
} | |
} | |
// layout - super light grid - it works with the .cd-container class | |
@mixin column($percentage, $float-direction:left) { | |
width: 100% * $percentage; | |
float: $float-direction; | |
} | |
/* -------------------------------- | |
Primary style | |
-------------------------------- */ | |
html * { | |
-webkit-font-smoothing: antialiased; | |
-moz-osx-font-smoothing: grayscale; | |
} | |
*, *:after, *:before { | |
@include box-sizing(border-box); | |
} | |
body { | |
font: { | |
size: 100%; | |
family: $primary-font; | |
} | |
color: $main-text; | |
background-color: $background; | |
} | |
a { | |
color: $color-2; | |
text-decoration: none; | |
} | |
img { | |
max-width: 100%; | |
} | |
input, textarea { | |
font-family: $primary-font; | |
@include font-size(16px); | |
&::-ms-clear { | |
display: none; | |
} | |
} | |
/* -------------------------------- | |
Main components | |
-------------------------------- */ | |
header[role=banner] { | |
position: relative; | |
height: $header-height-S; | |
background: $color-1; | |
#cd-logo { | |
float: left; | |
margin: 4px 0 0 5%; | |
/* reduce logo size on mobile and make sure it is left aligned with the transform-origin property */ | |
@include transform-origin(0 50%); | |
@include transform(scale(.8)); | |
img { | |
display: block; | |
} | |
} | |
&::after { /* clearfix */ | |
content: ''; | |
display: table; | |
clear: both; | |
} | |
@include MQ(M) { | |
height: $header-height-M; | |
#cd-logo { | |
margin: 20px 0 0 5%; | |
@include transform(scale(1)); | |
} | |
} | |
} | |
.main-nav { | |
float: right; | |
margin-right: 5%; | |
width: 44px; | |
height: 100%; | |
background: url('https://s3-us-west-2.amazonaws.com/s.cdpn.io/148866/cd-icon-menu.svg') no-repeat center center; | |
cursor: pointer; | |
ul { | |
position: absolute; | |
top: 0; | |
left: 0; | |
width: 100%; | |
@include transform(translateY(-100%)); | |
&.is-visible { | |
@include transform(translateY($header-height-S)); | |
} | |
} | |
a { | |
display: block; | |
height: $header-height-S; | |
line-height: $header-height-S; | |
padding-left: 5%; | |
background: darken($color-1, 5%); | |
border-top: 1px solid lighten($color-1, 3%); | |
color: #FFF; | |
} | |
@include MQ(M) { | |
width: auto; | |
height: auto; | |
background: none; | |
cursor: auto; | |
ul { | |
position: static; | |
width: auto; | |
@include transform(translateY(0)); | |
line-height: $header-height-M; | |
&.is-visible { | |
@include transform(translateY(0)); | |
} | |
} | |
li { | |
display: inline-block; | |
margin-left: 1em; | |
&:nth-last-child(2) { | |
margin-left: 2em; | |
} | |
} | |
a { | |
display: inline-block; | |
height: auto; | |
line-height: normal; | |
background: transparent; | |
&.cd-signin, &.cd-signup { | |
padding: .6em 1em; | |
border: 1px solid rgba(#FFF, .6); | |
border-radius: 50em; | |
} | |
&.cd-signup { | |
background: $color-2; | |
border: none; | |
} | |
} | |
} | |
} | |
/* -------------------------------- | |
xsigin/signup popup | |
-------------------------------- */ | |
.cd-user-modal { | |
position: fixed; | |
top: 0; | |
left: 0; | |
width: 100%; | |
height: 100%; | |
background: rgba($color-1, .9); | |
z-index: $modal-zindex; | |
overflow-y: auto; | |
cursor: pointer; | |
visibility: hidden; | |
opacity: 0; | |
@include transition(opacity .3s 0, visibility 0 .3s); | |
&.is-visible { | |
visibility: visible; | |
opacity: 1; | |
@include transition(opacity .3s 0, visibility 0 0); | |
.cd-user-modal-container { | |
@include transform(translateY(0)); | |
} | |
} | |
} | |
.cd-user-modal-container { | |
position: relative; | |
width: 90%; | |
max-width: 600px; | |
background: #FFF; | |
margin: 3em auto 4em; | |
cursor: auto; | |
@include border-radius; | |
@include transform(translateY(-30px)); | |
@include transition-property (transform); | |
@include transition-duration(.3s); | |
.cd-switcher { | |
@include clearfix; | |
li { | |
@include column(.5); | |
text-align: center; | |
&:first-child a { | |
border-radius: .25em 0 0 0; | |
} | |
&:last-child a { | |
border-radius: 0 .25em 0 0; | |
} | |
} | |
a { | |
display: block; | |
width: 100%; | |
height: 50px; | |
line-height: 50px; | |
background: $color-3; | |
color: darken($color-3, 30%); | |
&.selected { | |
background: #FFF; | |
color: $main-text; | |
} | |
} | |
} | |
@include MQ(S) { | |
margin: 4em auto; | |
.cd-switcher a { | |
height: 70px; | |
line-height: 70px; | |
} | |
} | |
} | |
.cd-form { | |
padding: 1.4em; | |
.fieldset { | |
position: relative; | |
margin: 1.4em 0; | |
&:first-child { | |
margin-top: 0; | |
} | |
&:last-child { | |
margin-bottom: 0; | |
} | |
} | |
label { | |
@include font-size(14px); | |
&.image-replace { | |
/* replace text with an icon */ | |
display: inline-block; | |
position: absolute; | |
left: 15px; | |
@include center(y); | |
height: 20px; | |
width: 20px; | |
overflow: hidden; | |
text-indent: 100%; | |
white-space: nowrap; | |
color: transparent; | |
text-shadow: none; | |
background-repeat: no-repeat; | |
background-position: 50% 0; | |
} | |
&.cd-username { | |
background-image: url('https://s3-us-west-2.amazonaws.com/s.cdpn.io/148866/cd-icon-username.svg'); | |
} | |
&.cd-email { | |
background-image: url('https://s3-us-west-2.amazonaws.com/s.cdpn.io/148866/cd-icon-email.svg'); | |
} | |
&.cd-password { | |
background-image: url('https://s3-us-west-2.amazonaws.com/s.cdpn.io/148866/cd-icon-password.svg'); | |
} | |
} | |
input { | |
margin: 0; | |
padding: 0; | |
@include border-radius; | |
&.full-width { | |
width: 100%; | |
} | |
&.has-padding { | |
padding: 12px 20px 12px 50px; | |
} | |
&.has-border { | |
border: 1px solid $color-3; | |
@include appearance(none); | |
&:focus { | |
border-color: $color-1; | |
box-shadow: 0 0 5px rgba($color-1, .1); | |
outline: none; | |
} | |
} | |
&.has-error { | |
border: 1px solid $red; | |
} | |
&[type=password] { | |
/* space left for the HIDE button */ | |
padding-right: 65px; | |
} | |
&[type=submit] { | |
padding: 16px 0; | |
cursor: pointer; | |
background: $color-2; | |
color: #FFF; | |
font-weight: bold; | |
border: none; | |
@include appearance(none); | |
.no-touch &:hover, .no-touch &:focus { | |
background: lighten($color-2, 5%); | |
outline: none; | |
} | |
} | |
} | |
.hide-password { | |
display: inline-block; | |
position: absolute; | |
right: 0; | |
top: 0; | |
padding: 6px 15px; | |
border-left: 1px solid $color-3; | |
@include center(y); | |
@include font-size(14px); | |
color: $color-1; | |
} | |
.cd-error-message { | |
display: inline-block; | |
position: absolute; | |
left: -5px; | |
bottom: -35px; | |
background: rgba($red, .9); | |
padding: .8em; | |
z-index: 2; | |
color: #FFF; | |
@include font-size(13px); | |
@include border-radius; | |
/* prevent click and touch events */ | |
pointer-events: none; | |
visibility: hidden; | |
opacity: 0; | |
@include transition(opacity .2s 0, visibility 0 .2s); | |
&::after { | |
/* triangle */ | |
content: ''; | |
position: absolute; | |
left: 22px; | |
bottom: 100%; | |
@include triangle(16px, rgba($red, .9), up); | |
} | |
&.is-visible { | |
opacity: 1; | |
visibility: visible; | |
@include transition(opacity .2s 0, visibility 0 0); | |
} | |
} | |
@include MQ(S) { | |
padding: 2em; | |
.fieldset { | |
margin: 2em 0; | |
&:first-child { | |
margin-top: 0; | |
} | |
&:last-child { | |
margin-bottom: 0; | |
} | |
} | |
input.has-padding { | |
padding: 16px 20px 16px 50px; | |
} | |
input[type=submit] { | |
padding: 16px 0; | |
} | |
} | |
} | |
.cd-form-message { | |
padding: 1.4em 1.4em 0; | |
@include font-size(14px); | |
line-height: 1.4; | |
text-align: center; | |
@include MQ(S) { | |
padding: 2em 2em 0; | |
} | |
} | |
.cd-form-bottom-message { | |
position: absolute; | |
width: 100%; | |
left: 0; | |
bottom: -30px; | |
text-align: center; | |
@include font-size(14px); | |
a { | |
color: #FFF; | |
text-decoration: underline; | |
} | |
} | |
.cd-close-form { | |
/* form X button on top right */ | |
display: block; | |
position: absolute; | |
width: 40px; | |
height: 40px; | |
right: 0; | |
top: -40px; | |
background: url('https://s3-us-west-2.amazonaws.com/s.cdpn.io/148866/cd-icon-close.svg') no-repeat center center; | |
text-indent: 100%; | |
white-space: nowrap; | |
overflow: hidden; | |
@include MQ(L) { | |
display: none; | |
} | |
} | |
#cd-login, #cd-signup, #cd-reset-password { | |
display: none; | |
} | |
#cd-login.is-selected, #cd-signup.is-selected, #cd-reset-password.is-selected { | |
display: block; | |
} | |