Описание проекта

Прежде чем мы приступим к написанию кода, я хотел бы разбить нашу главную задачу на отдельные компоненты. Это поможет сделать код более понятным.

У нас есть 4 небольших экрана/поля внутри основного компонента (.container):

  1. Форма Входа
  2. Форма Регистрации
  3. Оверлей (эффект наложения) Входа
  4. Оверлей Регистрации

Также, в конкретный момент времени вы увидите: 

  • Форму Входа вместе с оверлеем Регистрации
  • Форму Регистрации вместе с оверлеем Входа

В оверлеях у нас будет текст и кнопка. Нажав на кнопку (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‘ы. Каждый имеет width50% и positionabsolute. И тот и тот мы одновременно перемещаем слева направо. Когда они окажутся позади .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;
}

Несколько вещей, которые стоит отметить:

  1. Мы стилизуем теги h1, p, a напрямую, без добавления классов. Обычно, никто так не делает, рискуя смешать одни стили с другими. Но в данном примере все работает нормально, поскольку на странице у нас есть только эти элементы.
  2. Мы добавили элементу button свойство transition. При нажатии, кнопка становится немного меньше своего первоначального размера. Хороший и простой эффект нажатия!
  3. 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;
    }
}

Обратите внимание на следующее:

  1. animation (show) отвечает за изменение свойства z-index .form-container’ов, как обсуждалось выше. Мы получаем 1 z-index из 0-49.99%и 5 из 50-100%. Используются именно такие диапазоны, потому что мы хотим, чтобы они быстро менялись.
  2. Мы используем класс .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

Предыдущая статьяНасколько хорошо вы разбираетесь в сетях?
Следующая статьяЧто значит быть креативным дизайнером