Рубрики
Без рубрики

Как сделать горизонтальную скользящую навигацию

Этот учебник о создании меню навигации от разработчика бекона. Эта статья предназначена для PEO … Теги с учебником, HTML, CSS, JavaScript.

Этот учебник о создании меню навигации от разработчика бекона. Эта статья предназначена для людей, которые не знают Vue.js и были выделены из этого учебника. Существует использование SCSS, но будут примеры с помощью SCSS, так и с компиляционными CSS. JavaScript для этого учебника Используйте библиотеку Animejs Отказ Если вы хотите просто посмотреть код, вы можете найти его в примере кодепена или продолжить эту статью для примеров.

Смотрите ручку Скользящая навигация от разработчика бекона Бретт ( @brettanda ) на Кодепен Отказ

HTML

Давайте начнем с HTML для меню навигации. Пример HTML имеет все необходимые теги и необходимые для скрипта CSS, так и для JS, чтобы выглядеть так же, как BACON Developer. Эти могут быть изменены на все, что вам нравится (просто убедитесь, что вы измените его как в файле CSS, так и в файле JS).

SCSS и CSS

Этот первый пример – SCSS для меню навигации. Если вы не знакомы с SCSS, второй пример – это составленные SCSS к CSS.

// Based on this [snippet](https://css-tricks.com/snippets/sass/mixin-manage-breakpoints/) by Hugo Giraudel.
@mixin break($point) {
    @if map-has-key($breakpoints, $point) {
        @media screen and (max-width: map-get($breakpoints, $point)) {
            @content;
        }
    } @else {
        @warn 'Unfortunately, no value could be retrieved from `#{$breakpoint}`. '
            + 'Available breakpoints are: #{map-keys($breakpoints)}.';
    }
}

$breakpoints: (
    "sm": 800px,
    "md": 1000px
) !default;

.header,
.header * {
    box-sizing: border-box;
}

body {
    background-color: black;
}

nav[role="navigation"] {
    text-align: center;

    a {
        display: inline-block;
        margin: 1em 0.75em 2em;
    }
}

.header {
    background-color: red;
    display: flex;
    justify-content: space-between;
    margin-bottom: 20px;
    padding: 1rem;
    box-shadow: 0 2px 10px 1px rgba(0, 0, 0, 0.2);
}

img.logo-link {
    height: 1rem;
    width: auto;
}

.logo-link,
.nav__link {
    text-decoration: none;
    text-transform: uppercase;
    letter-spacing: 1px;
    color: black;
    transition: color 0.3s ease;

    &:hover,
    &:focus {
        text-decoration: none;
        color: white;
    }
}

.nav__link {
    margin-left: 20px;
    display: inline;

    @include break(md) {
        padding: 0.75rem;
    }
}

.nav-ham,
.nav__background {
    display: none;
}

.nav-ham {
    z-index: 2;
}

@include break(md) {
    .nav {
        display: none;

        &.is-active {
            display: flex;
            flex-direction: column;
            padding: 8rem 2rem 70vh 1rem;
            justify-content: space-around;
            text-align: right;
            position: fixed;
            background-color: #222;
            color: white;
            top: 0;
            height: 100vh;
            width: 15rem;
            z-index: 5;
            box-shadow: 0 2px 10px 1px rgba(0, 0, 0, 0.2);

            a {
                color: white;
                border-color: white;
            }
        }
    }

    .nav__background-1,
    .nav__background-2 {
        &.is-active {
            display: block;
            z-index: 3;
            background-color: gray;
            box-shadow: 0 2px 10px 1px rgba(0, 0, 0, 0.2);
            top: 0;
            height: 100vh;
            width: 18rem;
            position: fixed;
        }
    }

    .nav-ham {
        display: block;
        background: none;
        border: none;
        outline: none;
        height: 3rem;
        width: 3rem;
        position: absolute;
        right: 1rem;
        top: 0;
        z-index: 6;

        .nav-ham__line {
            border: 1px solid white;
            height: 0;
            width: 2rem;
            display: block;
            margin: 0.6rem 0 0.6rem auto;
            transform-origin: center right;
            transition: 0.3s;
        }

        & .is-active {
            &:first-child {
                transform-origin: center right;
                transform: rotate(-45deg);
            }

            &:nth-of-type(2) {
                width: 0;
                opacity: 0;
            }

            &:last-child {
                transform-origin: center right;
                transform: rotate(45deg);
            }
        }
    }
}

.close-nav {
    display: none;
    position: fixed;
    right: -100vw;
    top: 0;
    background: rgba(0, 0, 0, 0.7);
    height: 100vh;
    width: 100vw;
    opacity: 0;
    z-index: 2;

    @include break(md) {
        &.is-active {
            display: block;
        }
    }
}

.logo {
    vertical-align: bottom;
    width: 33px;
    padding: 0 1px;
}

Компилированные CSS.

Это скомпилированные CSS из SCSS выше.

.header,
.header * {
    box-sizing: border-box;
}

body {
    background-color: black;
}

nav[role="navigation"] {
    text-align: center;
}
nav[role="navigation"] a {
    display: inline-block;
    margin: 1em 0.75em 2em;
}

.header {
    background-color: red;
    display: -webkit-box;
    display: flex;
    -webkit-box-pack: justify;
    justify-content: space-between;
    margin-bottom: 20px;
    padding: 1rem;
    box-shadow: 0 2px 10px 1px rgba(0, 0, 0, 0.2);
}

img.logo-link {
    height: 1rem;
    width: auto;
}

.logo-link,
.nav__link {
    text-decoration: none;
    text-transform: uppercase;
    letter-spacing: 1px;
    color: black;
    -webkit-transition: color 0.3s ease;
    transition: color 0.3s ease;
}
.logo-link:hover,
.logo-link:focus,
.nav__link:hover,
.nav__link:focus {
    text-decoration: none;
    color: white;
}

.nav__link {
    margin-left: 20px;
    display: inline;
}
@media screen and (max-width: 1000px) {
    .nav__link {
        padding: 0.75rem;
    }
}

.nav-ham,
.nav__background {
    display: none;
}

.nav-ham {
    z-index: 2;
}

@media screen and (max-width: 1000px) {
    .nav {
        display: none;
    }
    .nav.is-active {
        display: -webkit-box;
        display: flex;
        -webkit-box-orient: vertical;
        -webkit-box-direction: normal;
        flex-direction: column;
        padding: 8rem 2rem 70vh 1rem;
        justify-content: space-around;
        text-align: right;
        position: fixed;
        background-color: #222;
        color: white;
        top: 0;
        height: 100vh;
        width: 15rem;
        z-index: 5;
        box-shadow: 0 2px 10px 1px rgba(0, 0, 0, 0.2);
    }
    .nav.is-active a {
        color: white;
        border-color: white;
    }

    .nav__background-1.is-active,
    .nav__background-2.is-active {
        display: block;
        z-index: 3;
        background-color: gray;
        box-shadow: 0 2px 10px 1px rgba(0, 0, 0, 0.2);
        top: 0;
        height: 100vh;
        width: 18rem;
        position: fixed;
    }

    .nav-ham {
        display: block;
        background: none;
        border: none;
        outline: none;
        height: 3rem;
        width: 3rem;
        position: absolute;
        right: 1rem;
        top: 0;
        z-index: 6;
    }
    .nav-ham .nav-ham__line {
        border: 1px solid white;
        height: 0;
        width: 2rem;
        display: block;
        margin: 0.6rem 0 0.6rem auto;
        -webkit-transform-origin: center right;
        transform-origin: center right;
        -webkit-transition: 0.3s;
        transition: 0.3s;
    }
    .nav-ham .is-active:first-child {
        -webkit-transform-origin: center right;
        transform-origin: center right;
        -webkit-transform: rotate(-45deg);
        transform: rotate(-45deg);
    }
    .nav-ham .is-active:nth-of-type(2) {
        width: 0;
        opacity: 0;
    }
    .nav-ham .is-active:last-child {
        -webkit-transform-origin: center right;
        transform-origin: center right;
        -webkit-transform: rotate(45deg);
        transform: rotate(45deg);
    }
}
.close-nav {
    display: none;
    position: fixed;
    right: -100vw;
    top: 0;
    background: rgba(0, 0, 0, 0.7);
    height: 100vh;
    width: 100vw;
    opacity: 0;
    z-index: 2;
}
@media screen and (max-width: 1000px) {
    .close-nav.is-active {
        display: block;
    }
}

.logo {
    vertical-align: bottom;
    width: 33px;
    padding: 0 1px;
}

Волшебный JavaScript

Прежде чем пройти в JavaScript этого проекта, мы должны добавить Animejs в проект. Для этого используйте эту команду в вашем каталоге проекта.

yarn add animejs

Я использовал Animejs, потому что он отлично подходит для обработки анимации с JavaScript. Документация Animejs можно найти в Animejs.com Отказ

document.querySelectorAll(".toggleNav").forEach(item => {
    item.addEventListener("click", function() {
        console.log("clicked");
        toggleNav();
    });
});

function closeNav() {
    document.querySelectorAll(".nav-ham, .nav-ham span").forEach(function(item) {
        item.classList.remove("is-active");
    });
    anime({
        targets: ".nav",
        duration: 400,
        easing: "easeInOutSine",
        right: [0, "-15rem"],
        complete: function() {
            document.querySelector(".nav").classList.remove("is-active");
        }
    });

    anime({
        targets: ".nav__background",
        delay: 150,
        duration: 400,
        easing: "easeInOutSine",
        right: ["0rem", "-18rem"],
        complete: function() {
            document.querySelectorAll(".nav__background").forEach(item => {
                item.classList.remove("is-active");
            });
        }
    });

    anime({
        targets: ".close-nav",
        delay: 150,
        duration: 400,
        easing: "easeInOutSine",
        right: [0, "-100vw"],
        opacity: 0,
        complete: function() {
            document.querySelector(".close-nav").classList.remove("is-active");
        }
    });
}
function toggleNav() {
    document.querySelectorAll(".nav-ham, .nav-ham span").forEach(item => {
        if (item.classList.contains("is-active")) {
            item.classList.remove("is-active");
        } else {
            item.classList.add("is-active");
        }
    });

    if (document.querySelector(".nav").classList.contains("is-active")) {
        this.closeNav();
    } else {
        anime({
            targets: ".close-nav",
            duration: 400,
            easing: "easeInOutSine",
            right: ["-100vw", 0],
            opacity: 1,
            begin: function() {
                document.querySelector(".close-nav").classList.add("is-active");
            }
        });

        anime({
            targets: ".nav:not(.is-active)",
            duration: 400,
            delay: 150,
            easing: "easeInOutSine",
            right: ["-15rem", 0],
            begin: function() {
                document.querySelector(".nav").classList.add("is-active");
            }
        });

        anime({
            targets: ".nav__background:not(.is-active)",
            duration: 400,
            easing: "easeInOutSine",
            // right: ['-100vw',"-20vw"],
            right: ["-18rem", "0rem"],
            begin: function() {
                document.querySelectorAll(".nav__background").forEach(function(item) {
                    item.classList.add("is-active");
                });
            }
        });
    }
}

Оригинал: “https://dev.to/developerbacon/how-to-make-a-horizontal-sliding-navigation-177a”