Background
After reading Vasudha Mamtani’s blog about sign-up pages, I realized I had been taking them for granted.
Having a solid sign-up page affects whether or not someone uses your website. Would you enter your email into a wonky looking sign-up form?
After looking through the examples in Mamtani’s blog, I decided to try my hand at making a better sign-in page. I came up with this:
The plan here is for a user to only see the abstract image when switching between signing in and creating an account.
I’m trying to imply that there’s a complicated inner working to this website. We are capable of great and complicated things. Trust us!
Tutorial
In the following, I’ll explain how to code one of these sign-up pages using React and CSS.
Table of Contents
- Preliminary Junk
- Container Layout
- Banner and Form Transitions
- Conditionally Render Sign-In / Sign-Up
- Conclusion
Preliminary Junk
First, as has become ritual for these blogs, I installed a create-react-app
, deleted default stuff, and set up a file structure and components.
File Structure
As you can see, there are three main components. Container.js
is my outermost element. Inside it, there are two divs for the form side and the banner side.
Then, there are two form components for whether you are signing in or creating a new account, SignIn.js
and SignUp.js
respectively. These are conditionally rendered on the form side of Container.js
.
I added a CSS class called cfb
(center flexbox). To reduce repetition, whenever I need contents of a div centered, I throw on a cfb
. As needed, I add other flex-related properties, like flex-direction
, to the specific element.
.cfb{
width: 100%;
display: flex;
justify-content: center;
align-items: center;
}
Container Layout
Container div
I style the main div in Container.js
like this:
.Container{
position: relative;
width: 50%;
height: 60%;
box-shadow: 1px 2px 2px #592941;
border: 0.1em solid #592941;
border-radius: 0.5em;
background-image: url('./shapes.jpg');
}
Form Side and Banner Side
Next, I create the divs for the banner and form side of Container.js
.
.banner-side{
position: absolute;
z-index: 2;
right: 65%;
border: 0.1em solid #592941;
border-radius: 0.5em;
width: 35%;
height: 100%;
flex-direction: column;
background-color: #035E7B;
opacity: 1;
color: #EEFCF8;
text-align: center;
transition: 2s;
}
.form-side{
position: absolute;
z-index: 1;
right: 0;
border: 0.1em solid #592941;
border-radius: 0.5em;
width: 65%;
height: 100%;
background-color: #EEFCF8;
opacity: 1;
font-weight: bold;
color: #035E7B;
transition: 2s;
}
Banner and Form Transitions
Positioning
So the transitions work properly, I set up CSS properties for position
, right
, z-index
, and transition
.
To make the divs free to move, they must be styled with a position: absolute;
. Then, they will align themselves within the nearest positioned parent element. This means I also must style the main div in Container.js
to have a position: relative;
.
I’ve styled the size of the divs with percentages. I use these same sizes to set how far right
they should be.
First, the form-side
is set at right: 0;
. It will sit flush on the right side of the container.
Because the form-side
is 65%
of the parent element, I set the banner-side
to be right: 65%;
. It starts where the form-side
ends.
To get banner-side
to hover over form-side
, I give banner-side
a z-index: 2;
and the form-side
a z-index: 1;
.
Finally, I give them each a transition: 2s;
. When I change their right
properties, they will move fluidly from their starting place to the next for the duration of two seconds.
Triggering Transitions by Updating Classes
The positioning of banner-side
and form-side
will be based on whether I am rendering a sign-in or sign-up form.
I set up two new classes for where the banner-side
and form-side
will be when they are reversed.
.send-right{
right: 0;
}
.send-left{
right: 35%;
}
I apply these new classes with functions.
const Container = () => {
const [welcome, setWelcome] = useState(false);
const setBannerClass = () => {
const classArr = ["banner-side cfb"]
if (welcome) classArr.push('send-right')
return classArr.join(' ')
};
const setFormClass = () => {
const classArr = ["form-side cfb"]
if (welcome) classArr.push('send-left')
return classArr.join(' ')
};
return (
<div className="Container cfb">
<div className={setBannerClass()}>
</div>
<div className={setFormClass()}>
</div>
</div>
);
}
My useState
hook contains a boolean called welcome
. When welcome
is updated, the component will re-render and the classes will be updated based based on that boolean.
Finally, I put up a button in the banner to trigger setWelcome()
in the useState
hook.
<button onClick={()=> setWelcome(!welcome)}>
~Change~
</button>
Conditionally Render Sign-In / Sign-Up
The final touch is to change the forms and and banner text based on whether our user intends to sign-in or create a new account. To do this, I used the same welcome
from my useState
hook.
return (
<div className="Container cfb">
<div className={setBannerClass()}>
{welcome ?
<h2>Hello, New Friend!</h2>
: <h2>Welcome Back</h2>}
<button onClick={()=> setWelcome(!welcome)}>
{welcome ?
"Sign In"
: "Create Account"}
</button>
</div>
<div className={setFormClass()}>
{welcome ?
<SignUp />
: <SignIn/>
}
</div>
</div>
);
Because this is a dummy project, I didn’t do anything specific with the forms themselves. If you’d like, you can check them out on GitHub.
Conclusion
This was a fun one to figure out. The newest concept for me was a deeper understanding of position
and z-index
.
I've used this properties before, but I had been flying by the seat of my pants. I’m happy for my newfound confidence with them.
Taking this project further, I would also animate the rendering of the text and forms themselves. A smooth transition would improve the page.
As always, thanks for reading. I hope this helped you somehow.
Top comments (0)