Описание проекта
Прежде чем мы приступим к написанию кода, я хотел бы разбить нашу главную задачу на отдельные компоненты. Это поможет сделать код более понятным.
У нас есть 4 небольших экрана/поля внутри основного компонента (.container
):
- Форма Входа
- Форма Регистрации
- Оверлей (эффект наложения) Входа
- Оверлей Регистрации
Также, в конкретный момент времени вы увидите:
- Форму Входа вместе с оверлеем Регистрации
- Форму Регистрации вместе с оверлеем Входа
В оверлеях у нас будет текст и кнопка. Нажав на кнопку (button
), вы переключитесь на другую комбинацию экранов/полей и наоборот. Еще раз взгляните на GIF в начале статьи, чтобы понять, что я имею в виду.
Анимация оверлеев
В этой части статьи все будет немного сложнее, но я постараюсь объяснить настолько понятно, насколько смогу.
У нас есть следующие слои для оверлейного компонента:
overlay-container — будет отображать видимую область (подробнее об этом ниже) в определенный момент времени. Его ширина (width
) 50%
от общей ширины контейнера.
overlay — данный div имеет двойной показатель width
(200%
), поэтому он занимает всю ширину основного контейнера (200% * 50%= 100%
. 50% от вышеупомянутого .overlay-container
).
overlay-panels — это div’ы, содержащие в себе видимый на экране контент (текст и кнопку). И там и там свойство position
равняется значению absolute
. Это значит, что мы можем разместить их где угодно в компоненте .overlay
. Одна из панелей расположена слева (left
), а другая справа (right
). Обе имеют ширину 50%
от .overlay
компонента.
Вы можете спросить: “Зачем нам 3 слоя?”. Что же, давайте посмотрим, как будет выглядеть проект без первого слоя:
На изображении выше мы видим, что обе панели одновременно находятся в “видимом” состоянии, а это не то, чего мы хотим. Вот почему мы добавляем .overlay-container
. Он действует, как “область фокусировки” и позволяет нам скрыть панель, которая находится за пределами этой области. Также, по этой причине нам нужно, чтобы .overlay
был вдвое больше .overlay-container
. Двигая .overlay
вокруг .overlay-container
, у которого свойство position
равняется absolute
, мы можем скрыть или показать ту панель, которая нам нужна.
Соглашусь, объяснение сбивает с толку, но я надеюсь, что хоть немного прояснил ситуацию.?
Анимация форм
Здесь все куда легче. У нас опять есть два контейнера — .form-container
‘ы. Каждый имеет width
—50%
и position
— absolute
. И тот и тот мы одновременно перемещаем слева направо. Когда они окажутся позади .overlay-container
, сверху (пока они движутся) мы быстро меняем значение z-index
. Форма Регистрации (к примеру) будет перемещаться поверх формы Входа и наоборот.
HTML
Итак, пришло время увидеть HTML-код. Давайте начнем с основного скелета:
<div class="container" id="container">
<div class="form-container sign-up-container">
<!-- Sign Up form code goes here -->
</div>
<div class="form-container sign-in-container">
<!-- Sign In form code goes here -->
</div>
<div class="overlay-container">
<!-- The overlay code goes here -->
</div>
</div>
Основной div имеет класс .container
и id container
, потому что мы хотим использовать этот элемент в JavaScript (подробнее об этом ниже).?
Форма Регистрации
<div class="form-container sign-up-container">
<form action="#">
<h1>Create Account</h1>
<div class="social-container">
<a href="#" class="social"><i class="fab fa-facebook-f"></i></a>
<a href="#" class="social"><i class="fab fa-google-plus-g"></i></a>
<a href="#" class="social"><i class="fab fa-linkedin-in"></i></a>
</div>
<span>or use your email for registration</span>
<input type="text" placeholder="Name" />
<input type="email" placeholder="Email" />
<input type="password" placeholder="Password" />
<button>Sign Up</button>
</form>
</div>
Форма Входа
<div class="form-container sign-in-container">
<form action="#">
<h1>Sign in</h1>
<div class="social-container">
<a href="#" class="social"><i class="fab fa-facebook-f"></i></a>
<a href="#" class="social"><i class="fab fa-google-plus-g"></i></a>
<a href="#" class="social"><i class="fab fa-linkedin-in"></i></a>
</div>
<span>or use your account</span>
<input type="email" placeholder="Email" />
<input type="password" placeholder="Password" />
<a href="#">Forgot your password?</a>
<button>Sign In</button>
</form>
</div>
У нас есть несколько классов для каждого div:
- Класс
.form-container
будет содержать CSS, который дублируется, как для класса.sign-in-container
, так и для.sign-up-container
; - Два разных класса, упомянутых выше, будут содержать разный CSS-код
Таким образом, мы избегаем необходимости писать один и тот же CSS-код дважды.
Возможно, вы уже заметили, что у тегов i
есть несколько классов. Это потому, что мы используем FontAwesome для иконок социальных сетей.
Оверлей контейнер
<div class="overlay-container">
<div class="overlay">
<div class="overlay-panel overlay-left">
<h1>Welcome Back!</h1>
<p>
To keep connected with us please login with your personal info
</p>
<button class="ghost" id="signIn">Sign In</button>
</div>
<div class="overlay-panel overlay-right">
<h1>Hello, Friend!</h1>
<p>Enter your personal details and start journey with us</p>
<button class="ghost" id="signUp">Sign Up</button>
</div>
</div>
</div>
Та же самая ситуация: у нас есть общий класс .overlay-panel
и два разных класса .overlay-left
и .overlay-right
. Кроме этого, есть id
для кнопок, поскольку мы собираемся добавить onClick eventListener
для них в JavaScript
.
JavaScript
Обычно, перед JavaScript идет CSS, но на этот раз проще сначала показать и объяснить JS-код. Это поможет вам понять CSS, который будет немного позже.
const signUpButton = document.getElementById('signUp');
const signInButton = document.getElementById('signIn');
const container = document.getElementById('container');
signUpButton.addEventListener('click', () => {
container.classList.add('right-panel-active');
});
signInButton.addEventListener('click', () => {
container.classList.remove('right-panel-active');
});
Как упоминалось выше, мы добавляем прослушиватель событий (eventListener
). При нажатии на кнопки, мы добавляем (add
) или удаляем (remove
) класс .right-panel-active
. Этот класс будет использоваться для различного стиля subcomponent’ов, так как у нас два экрана.
CSS
Во-первых, у нас есть базовый CSS для основных компонентов:
h1 {
font-weight: bold;
margin: 0;
}
p {
font-size: 14px;
font-weight: 100;
line-height: 20px;
letter-spacing: 0.5px;
margin: 20px 0 30px;
}
span {
font-size: 12px;
}
a {
color: #333;
font-size: 14px;
text-decoration: none;
margin: 15px 0;
}
button {
border-radius: 20px;
border: 1px solid #ff4b2b;
background-color: #ff4b2b;
color: #ffffff;
font-size: 12px;
font-weight: bold;
padding: 12px 45px;
letter-spacing: 1px;
text-transform: uppercase;
transition: transform 80ms ease-in;
}
button:active {
transform: scale(0.95);
}
button:focus {
outline: none;
}
button.ghost {
background-color: transparent;
border-color: #ffffff;
}
form {
background-color: #ffffff;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
padding: 0 50px;
height: 100%;
text-align: center;
}
input {
background-color: #eee;
border: none;
padding: 12px 15px;
margin: 8px 0;
width: 100%;
}
.social-container {
margin: 20px 0;
}
.social-container a {
border: 1px solid #dddddd;
border-radius: 50%;
display: inline-flex;
justify-content: center;
align-items: center;
margin: 0 5px;
height: 40px;
width: 40px;
}
Несколько вещей, которые стоит отметить:
- Мы стилизуем теги
h1, p, a
напрямую, без добавления классов. Обычно, никто так не делает, рискуя смешать одни стили с другими. Но в данном примере все работает нормально, поскольку на странице у нас есть только эти элементы. - Мы добавили элементу
button
свойствоtransition
. При нажатии, кнопка становится немного меньше своего первоначального размера. Хороший и простой эффект нажатия! form
представляет из себяflex
-контейнер, так как мы хотим центрировать все внутри него, а это легко сделать при помощиflexbox
. Ниже вы увидите, что он используется еще несколько раз.
.container
CSS:
.container {
background-color: #ffffff;
border-radius: 10px;
box-shadow: 0 14px 28px rgba(0, 0, 0, 0.25), 0 10px 10px rgba(0, 0, 0, 0.22);
position: relative;
overflow: hidden;
width: 768px;
max-width: 100%;
min-height: 480px;
}
- Свойство
position
стоит наRelative
, потому что дочерние элементы уже стоят на значенииabsolute
. - Свойство
Overflow
установлено на значенииhidden
, потому что мы установилиborder-radius
и не хотим, чтобы дочерние элементы нарушали этот радиус и отображались за пределами.container
.
Теперь самое интересное — .form-container
и связанные с ним стили:
.form-container {
position: absolute;
top: 0;
height: 100%;
transition: all 0.6s ease-in-out;
}
.sign-in-container {
left: 0;
width: 50%;
z-index: 2;
}
.sign-up-container {
left: 0;
width: 50%;
opacity: 0;
z-index: 1;
}
.container.right-panel-active .sign-in-container {
transform: translateX(100%);
}
.container.right-panel-active .sign-up-container {
transform: translateX(100%);
opacity: 1;
z-index: 5;
animation: show 0.6s;
}
@keyframes show {
0%,
49.99% {
opacity: 0;
z-index: 1;
}
50%,
100% {
opacity: 1;
z-index: 5;
}
}
Обратите внимание на следующее:
animation
(show
) отвечает за изменение свойстваz-index
.form-container’ов
, как обсуждалось выше. Мы получаем 1 z-index из0-49.99%
и 5 из50-100%
. Используются именно такие диапазоны, потому что мы хотим, чтобы они быстро менялись.- Мы используем класс
.right-panel-active
для перемещения по.form-container’ам
при нажатии кнопок.
И наконец, .overlay-container
и связанные с ним стили:
.overlay-container {
position: absolute;
top: 0;
left: 50%;
width: 50%;
height: 100%;
overflow: hidden;
transition: transform 0.6s ease-in-out;
z-index: 100;
}
.container.right-panel-active .overlay-container {
transform: translateX(-100%);
}
.overlay {
background: #ff416c;
background: -webkit-linear-gradient(to right, #ff4b2b, #ff416c);
background: linear-gradient(to right, #ff4b2b, #ff416c);
background-repeat: no-repeat;
background-size: cover;
background-position: 0 0;
color: #ffffff;
position: relative;
left: -100%;
height: 100%;
width: 200%;.overlay-container {
position: absolute;
top: 0;
left: 50%;
width: 50%;
height: 100%;
overflow: hidden;
transition: transform 0.6s ease-in-out;
z-index: 100;
}
.container.right-panel-active .overlay-container {
transform: translateX(-100%);
}
.overlay {
background: #ff416c;
background: -webkit-linear-gradient(to right, #ff4b2b, #ff416c);
background: linear-gradient(to right, #ff4b2b, #ff416c);
background-repeat: no-repeat;
background-size: cover;
background-position: 0 0;
color: #ffffff;
position: relative;
left: -100%;
height: 100%;
width: 200%;
transform: translateX(0);
transition: transform 0.6s ease-in-out;
}
.container.right-panel-active .overlay {
transform: translateX(50%);
}
.overlay-panel {
position: absolute;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
padding: 0 40px;
text-align: center;
top: 0;
height: 100%;
width: 50%;
transform: translateX(0);
transition: transform 0.6s ease-in-out;
}
.overlay-left {
transform: translateX(-20%);
}
.container.right-panel-active .overlay-left {
transform: translateX(0);
}
.overlay-right {
right: 0;
transform: translateX(0);
}
.container.right-panel-active .overlay-right {
transform: translateX(20%);
}
transform: translateX(0);
transition: transform 0.6s ease-in-out;
}
.container.right-panel-active .overlay {
transform: translateX(50%);
}
.overlay-panel {
position: absolute;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
padding: 0 40px;
text-align: center;
top: 0;
height: 100%;
width: 50%;
transform: translateX(0);
transition: transform 0.6s ease-in-out;
}
.overlay-left {
transform: translateX(-20%);
}
.container.right-panel-active .overlay-left {
transform: translateX(0);
}
.overlay-right {
right: 0;
transform: translateX(0);
}
.container.right-panel-active .overlay-right {
transform: translateX(20%);
}
- у
.overlay
есть градиентный фон. Чтобы этого добиться, я использовал UI Gradients; .overlay-left
и.container.right-panel-active .overlay-right
имеют-20%
и20%
смещения по оси X. Я сделал это, потому что хотел добавить небольшой эффект к тесту, будто бы он появляется из ниоткуда, когда отображается ?;
Кроме этого…Ничего! Мы все сделали. Ничего не забыли!?
Заключение
Эта статья была довольно сложной, не так ли? ? Тем не менее, я надеюсь, что вы кое-чему научились.
Перевод статьи Florin Pop: How to build a double slider sign-in and sign-up form