29.01.2020, 13:04
|
Кандидат Javascript-наук
|
|
Регистрация: 26.12.2017
Сообщений: 125
|
|
Мобильное меню
Есть мобильное меню, в котором при открытии все пункты должны появляться поочередно сверху вниз. Но скрипт почему-то не работает полноценно. Иногда при открытии все ссылки уже видны сразу. Кроме того, если меню открыть, потом быстро закрыть и снова открыть, то видно, что некоторые ссылки еще видны, а некоторые начинают появляться заново. Пытался при закрытии меню делать clearTimeout, но не пойму, куда его вставить.
Ссылка на сайт
Скрипт мобильного меню
(function() {
const hamburger = document.getElementById('menu__button');
const menu = document.querySelector('.nav-list');
const menuLinks = document.querySelectorAll('.nav__link');
const body = document.getElementsByTagName('body')[0];
const logoText = document.querySelector('.logo__link');
const social = document.querySelector('.social-list');
const mobileBtn = document.querySelector('.mobile-menu__btn');
let screenWidth = window.screen.availWidth;
hamburger.addEventListener('click', mobileMenu);
function mobileMenu() {
window.addEventListener('resize', () => {
screenWidth = window.screen.availWidth;
if (screenWidth > 1024) {
menuLinks.forEach(link => {
link.style.opacity = '1';
});
hamburger.classList.remove('active');
menu.classList.remove('nav-list--open');
body.classList.remove('no-scroll');
} else {
menuLinks.forEach(link => {
link.style.opacity = '0';
});
}
});
if(!hamburger.classList.contains('active')) {
showMenuLinks();
hamburger.classList.add('active');
menu.classList.add('nav-list--open');
body.classList.add('no-scroll');
logoText.classList.add('logo__link--mobile-open');
mobileBtn.classList.add('mobile-menu__btn--animate');
social.classList.add('social-list--animate');
} else {
menuLinks.forEach(link => {
link.style.opacity = '0';
});
hamburger.classList.remove('active');
menu.classList.remove('nav-list--open');
body.classList.remove('no-scroll');
logoText.classList.remove('logo__link--mobile-open');
mobileBtn.classList.remove('mobile-menu__btn--animate');
social.classList.remove('social-list--animate');
}
function showMenuLinks() {
setTimeout( () => {
function menuLinksShow() {
for (let i = 0; i < menuLinks.length; i++) {
setTimeout( () => {
menuLinks[i].style.opacity = '1';
}, 150*i);
}
}
menuLinksShow();
}, 500);
}
}
})();
|
|
29.01.2020, 13:16
|
|
Профессор
|
|
Регистрация: 27.05.2010
Сообщений: 33,123
|
|
DVV,
может заменить setTimeout на css transition-delay?
|
|
29.01.2020, 18:41
|
|
Профессор
|
|
Регистрация: 27.05.2010
Сообщений: 33,123
|
|
мобильное меню
DVV,
на основе кода от Malleys https://javascript.ru/forum/showthre...788#post518790
<html>
<style>
body {
padding-top: 70px;
font: 14px / 24px Arial, Tahoma, sans-serif;
background: #c0c0c0;
}
ol, ul {
list-style: none;
}
* {
margin: 0;
padding: 0;
outline: none;
box-sizing: border-box;
}
header {
position: fixed;
top: 0;
left: 0;
right: 0;
padding: 10px;
background: #ff0000;
height: 60px;
box-shadow: 0px 0px 13px 5px #000000;
}
.nav {
float: right;
}
.nav li {
float: left;
}
.nav li a,
#touch-menu {
border: 0;
background: none;
display: block;
padding: 12px 15px;
font-weight: bold;
font-size: 16px;
color: #fff;
}
.nav li a:hover {
background: #515572;
}
#touch-menu {
display: none;
}
@media (max-width: 900px) {
body {
padding-top: 60px;
}
header {
position: fixed;
top: 0;
left: 0;
right: 0;
height: 50px;
}
.nav {
position: absolute;
top: 100%;
left: 0;
right: 0;
visibility: hidden;
}
.nav li {
float: none;
opacity: 0.9;
text-align: center;
}
.nav li a {
border-top: 1px solid #eee;
border-left: 3px solid transparent;
background-color: hsla(0, 0%, 41%, 1);
color: hsla(0, 0%, 100%, 1);
}
.nav li:first-child a {
border-top: none;
}
.nav li a:hover {
color: #fff;
border-left: 3px solid #515572;
}
#touch-menu {
display: block;
float: right;
height: 50px;
margin: -16px 0;
}
}
.bar1,
.bar2,
.bar3 {
width: 40px;
height: 5px;
background-color: #fff;
margin: 6px 0;
transition: 0.4s;
}
#touch-menu:focus {
pointer-events: none;
}
#touch-menu:focus .bar1 {
transform: rotate(-45deg) translate(-9px, 6px);
}
#touch-menu:focus .bar2 {
opacity: 0;
}
#touch-menu:focus .bar3 {
transform: rotate(45deg) translate(-8px, -8px);
}
#touch-menu:focus ~ nav .nav {
visibility: visible;
}
#touch-menu nav .nav li{
opacity: 0;
transition: 500ms;
}
#touch-menu:focus ~ nav .nav li {
opacity: 1;
}
#touch-menu:focus ~ nav .nav li:nth-child(1) {
transition-delay: 400ms
}
#touch-menu:focus ~ nav .nav li:nth-child(2) {
transition-delay: 800ms
}
#touch-menu:focus ~ nav .nav li:nth-child(3) {
transition-delay: 1200ms
}
#touch-menu:focus ~ nav .nav li:nth-child(4) {
transition-delay: 1600ms
}
#touch-menu ~ nav .nav li:nth-child(4) {
transition-delay: 400ms
}
#touch-menu ~ nav .nav li:nth-child(3) {
transition-delay: 800ms
}
#touch-menu ~ nav .nav li:nth-child(2) {
transition-delay: 1200ms
}
#touch-menu ~ nav .nav li:nth-child(1) {
transition-delay: 1600ms
}
</style>
<header class="container">
<button id="touch-menu">
<div class="bar1"></div>
<div class="bar2"></div>
<div class="bar3"></div>
</button>
<nav>
<ul class="nav">
<li><a href="#">1</a></li>
<li><a href="#">2</a></li>
<li><a href="#">3</a></li>
<li><a href="#">4</a></li>
</ul>
</nav>
</header>
</html>
|
|
29.01.2020, 21:06
|
|
Профессор
|
|
Регистрация: 20.12.2009
Сообщений: 1,714
|
|
Сообщение от рони
|
на основе кода от Malleys
|
Это замечательно, что вас интересуют мои примеры, однако пример, который вы сделали, обладает недостатком — там не может быть произвольное количество элементов списка меню! Точней оно может, но для работы эффекта вам придется подгонять стили (вручную или с помощью Sass)
DVV, когда вы объявляете шрифт, то не нужно давать каждый раз разное имя только из-за того, что у него разная «жирность»! Это один и тот же шрифт, но с разной «жирностью»! При объявлении указывайте правильный font-weight. Пример ниже!
Для того, чтобы элементы появлялись последовательно, используйте transition-delay вместе с собственным свойством --i, указывающим на порядковый номер элемента.
Тут сразу при примера: 1) Как подключить один шрифт с разными свойствами, 2) Как сделать последовательное появление элементов, 3) Ещё одно меню гамбургер (Как использовать собственные свойства при работе с градиентами)
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<header>
<div class="logo" itemscope="" itemtype="http://schema.org/Organization">
<a href="#" itemprop="name">
BLACKCODE.
<span class="logo--white">agency</span>
</a>
</div>
<nav role="menu" itemscope="" itemtype="http://schema.org/SiteNavigationElement">
<ul>
<li role="menuitem"><a itemprop="url" href="#">Все проекты</a></li>
<li role="menuitem"><a itemprop="url" href="#">Почему мы?</a></li>
<li role="menuitem"><a itemprop="url" href="#">Услуги</a></li>
<li role="menuitem"><a itemprop="url" href="#">Контакты</a></li>
<li role="menuitem"><a itemprop="url" href="#">Главная</a></li>
<li role="menuitem"><a itemprop="url" href="#">Преимущества</a></li>
<li role="menuitem"><a itemprop="url" href="#">Что мы делаем?</a></li>
<li role="menuitem"><a itemprop="url" href="#">Портфолио</a></li>
<li role="menuitem"><a itemprop="url" href="#">Рассчитать стоимость</a></li>
</ul>
</nav>
<button class="cmn-toggle-switch" area-label="Открыть мобильное меню">Toggle menu</button>
</header>
<style>
@font-face {
font-family: "Qanelas";
src: url("https://viacheslavdemchenko.github.io/blackcode/fonts/qanelas/qanelas-bold/Qanelas-Bold.ttf");
font-weight: 700;
font-style: normal;
}
@font-face {
font-family: "Qanelas";
src: url("https://viacheslavdemchenko.github.io/blackcode/fonts/qanelas/qanelas-light/Qanelas-Light.ttf");
font-weight: 300;
font-style: normal;
}
@font-face {
font-family: "Qanelas";
src: url("https://viacheslavdemchenko.github.io/blackcode/fonts/qanelas/qanelas-medium/Qanelas-Medium.ttf");
font-weight: 500;
font-style: normal;
}
@font-face {
font-family: "Qanelas";
src: url("https://viacheslavdemchenko.github.io/blackcode/fonts/qanelas/qanelas-regular/Qanelas-Regular.ttf");
font-weight: 400;
font-style: normal;
}
html {
font: 1em "Qanelas", sans-serif;
background: #111;
color: white;
}
header .logo a {
font-weight: bold;
color: #eaa627;
position: fixed;
z-index: 2;
display: flex;
width: 100%;
left: 0;
top: 0;
justify-content: center;
text-decoration: none;
font-size: 1.5em;
padding: 1em;
box-sizing: border-box;
}
header .logo a .logo--white {
color: white;
}
header nav[role="menu"] {
position: fixed;
z-index: 1;
top: 0;
left: 0;
width: 100%;
height: 100%;
transform: translateX(-100%);
padding: 1em;
padding-top: 4.5em;
background-color: #3e3e3d;
transition: transform 0.5s, visibility 0.5s 0s;
box-sizing: border-box;
overflow: auto;
visibility: hidden;
}
.is-nav-menu-open header nav[role="menu"] {
transform: translateX(0);
visibility: visible;
}
header nav[role="menu"] > ul {
all: unset;
display: flex;
flex-direction: column;
align-items: center;
}
header nav[role="menu"] > ul > li {
all: unset;
transition-duration: 0.1s;
transition-delay: 0s;
transform: translateY(-100%);
opacity: 0;
}
.is-nav-menu-open header nav[role="menu"] > ul > li {
transition-duration: 0.2s;
transition-delay: calc(var(--i, 0) * 0.1s + 0.25s);
transform: translateY(0%);
opacity: 1;
}
header nav[role="menu"] > ul > li > a {
all: unset;
display: block;
color: white;
padding: 1em;
font-size: 125%;
cursor: pointer;
}
.cmn-toggle-switch {
all: unset;
position: fixed;
right: 1em;
top: 1em;
z-index: 2;
background: none;
width: 3em; height: 3em;
color: transparent;
}
.cmn-toggle-switch::before, .cmn-toggle-switch::after {
content: "";
width: 80%; height: 80%;
border: 0 solid white;
display: block;
margin: 10%;
box-sizing: border-box;
position: absolute;
top: 0; right: 0;
transition: 500ms;
--stripe-width: 5px;
--stripe:
transparent calc(50% - var(--stripe-width) / 2),
white 0 calc(50% + var(--stripe-width) / 2),
transparent 0;
}
.cmn-toggle-switch::before {
border-width: var(--stripe-width) 0;
background: linear-gradient(to bottom, var(--stripe));
}
.is-nav-menu-open .cmn-toggle-switch::before {
transform: scale(0);
opacity: 0;
}
.cmn-toggle-switch::after {
background: linear-gradient(to bottom, var(--stripe)), linear-gradient(to right, var(--stripe));
transform: rotate(45deg) scale(0);
opacity: 0;
}
.is-nav-menu-open .cmn-toggle-switch::after {
transform: rotate(45deg);
opacity: 1;
}
</style>
<script>
document.querySelector("header .cmn-toggle-switch").addEventListener("click", () => {
document.documentElement.classList.toggle("is-nav-menu-open");
});
Array.from(document.querySelectorAll("header [role=menuitem]")).forEach((node, index) => {
node.style.setProperty("--i", index);
});
</script>
Последний раз редактировалось Malleys, 29.01.2020 в 21:10.
|
|
30.01.2020, 06:46
|
|
Профессор
|
|
Регистрация: 27.05.2010
Сообщений: 33,123
|
|
Malleys,
1. зачем грузятся 4 шрифта под одним именем? это как-то используется, или просто пример загрузки и работает только последний загруженный?
2. как сделать последовательное не только появление но и исчезновение?
3.что даёт использование собственного свойства или это только для примера, и можно сделать иначе?
|
|
30.01.2020, 08:07
|
|
Профессор
|
|
Регистрация: 20.12.2009
Сообщений: 1,714
|
|
Сообщение от рони
|
1. зачем грузятся 4 шрифта под одним именем? это как-то используется, или просто пример загрузки и работает только последний загруженный?
|
Работают все 4 файла, но это один шрифт. В примере выше применяется обычное и жирное начертание (строки №56 и №62)
Сообщение от рони
|
2. как сделать последовательное не только появление, но и исчезновение?
|
На строке №108 указано, что исчезнуть должно сразу. ( transition-delay: 0s;) Вы можете указать ненулевую задержку.
Сообщение от рони
|
3.что даёт использование собственного свойства или это только для примера, и можно сделать иначе?
|
Если вы про строку №183, то такой подход даёт возможность достаточно просто описать задержку (строка №114), которая зависит от порядкового номера элемента.
Если вы про строку №148, то использование собственного свойства позволило сократить код на строках №№ 156 и 165. Также это показывает, как работают токены в СSS. Обратите внимание, что --stripe представляет из себя 3 аргумента для функции linear-gradient. (строка №165) Да, можно сделать иначе, это не касается вопроса (строки №№126–173 не касаются темы), заданного автором, но скорей показывает возможности CSS. Толщину «гамбургера» регулирует свойство --stripe-width (строка №147)
|
|
30.01.2020, 09:16
|
|
Профессор
|
|
Регистрация: 27.05.2010
Сообщений: 33,123
|
|
Сообщение от Malleys
|
Работают все 4 файла
|
??? ок, но яснее не стало.
Сообщение от Malleys
|
Вы можете указать ненулевую задержку.
|
указал 10s, ничего не изменилось, может не туда смотрю.
с третьим вопросом боле мене понятно, спасибо за ответ.
|
|
30.01.2020, 09:45
|
|
Профессор
|
|
Регистрация: 27.05.2010
Сообщений: 33,123
|
|
Сообщение от рони
|
как сделать последовательное не только появление но и исчезновение?
|
не могу точно расчитать transition-delay в строках 97 и 104 ... возможно есть более "красивый" вариант ... при открытии меню часть li уже открыта, хотелось бы увидеть весь процесс открытия с первого пункта меню
<!DOCTYPE html>
<html>
<head>
<title>Untitled</title>
<meta charset="utf-8">
</head>
<body>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<header>
<div class="logo" itemscope="" itemtype="http://schema.org/Organization">
<a href="#" itemprop="name">
BLACKCODE.
<span class="logo--white">agency</span>
</a>
</div>
<nav role="menu" itemscope="" itemtype="http://schema.org/SiteNavigationElement">
<ul>
<li role="menuitem"><a itemprop="url" href="#">Все проекты</a></li>
<li role="menuitem"><a itemprop="url" href="#">Почему мы?</a></li>
<li role="menuitem"><a itemprop="url" href="#">Услуги</a></li>
<li role="menuitem"><a itemprop="url" href="#">Контакты</a></li>
<li role="menuitem"><a itemprop="url" href="#">Главная</a></li>
<li role="menuitem"><a itemprop="url" href="#">Преимущества</a></li>
<li role="menuitem"><a itemprop="url" href="#">Что мы делаем?</a></li>
<li role="menuitem"><a itemprop="url" href="#">Портфолио</a></li>
<li role="menuitem"><a itemprop="url" href="#">Рассчитать стоимость</a></li>
</ul>
</nav>
<button class="cmn-toggle-switch" area-label="Открыть мобильное меню">Toggle menu</button>
</header>
<style>
@font-face {
font-family: "Qanelas";
src: url("https://viacheslavdemchenko.github.io/blackcode/fonts/qanelas/qanelas-bold/Qanelas-Bold.ttf");
font-weight: 700;
font-style: normal;
}
@font-face {
font-family: "Qanelas";
src: url("https://viacheslavdemchenko.github.io/blackcode/fonts/qanelas/qanelas-light/Qanelas-Light.ttf");
font-weight: 300;
font-style: normal;
}
@font-face {
font-family: "Qanelas";
src: url("https://viacheslavdemchenko.github.io/blackcode/fonts/qanelas/qanelas-medium/Qanelas-Medium.ttf");
font-weight: 500;
font-style: normal;
}
@font-face {
font-family: "Qanelas";
src: url("https://viacheslavdemchenko.github.io/blackcode/fonts/qanelas/qanelas-regular/Qanelas-Regular.ttf");
font-weight: 400;
font-style: normal;
}
html {
font: 1em "Qanelas", sans-serif;
background: #111;
color: white;
}
header .logo a {
font-weight: bold;
color: #eaa627;
position: fixed;
z-index: 2;
display: flex;
width: 100%;
left: 0;
top: 0;
justify-content: center;
text-decoration: none;
font-size: 1.5em;
padding: 1em;
box-sizing: border-box;
}
header .logo a .logo--white {
color: white;
}
header nav[role="menu"] {
position: fixed;
z-index: 1;
top: 0;
left: 0;
width: 100%;
height: 100%;
transform: translateX(-100%);
padding: 1em;
padding-top: 4.5em;
background-color: #3e3e3d;
transition: transform 0.5s 2s, visibility 0.5s 2s;
box-sizing: border-box;
overflow: auto;
visibility: hidden;
}
.is-nav-menu-open header nav[role="menu"] {
transform: translateX(0);
transition-delay: .3s;
visibility: visible;
}
header nav[role="menu"] > ul {
all: unset;
display: flex;
flex-direction: column;
align-items: center;
}
header nav[role="menu"] > ul > li {
all: unset;
transition-duration: 0.1s;
transition-delay: calc(var(--k, 0) * 0.2s + 0.25s);
transform: translateY(-100%);
opacity: 0;
}
.is-nav-menu-open header nav[role="menu"] > ul > li {
transition-duration: 0.2s;
transition-delay: calc(var(--i, 0) * 0.2s + 0.25s);
transform: translateY(0%);
opacity: 1;
}
header nav[role="menu"] > ul > li > a {
all: unset;
display: block;
color: white;
padding: 1em;
font-size: 125%;
cursor: pointer;
}
.cmn-toggle-switch {
all: unset;
position: fixed;
right: 1em;
top: 1em;
z-index: 2;
background: none;
width: 3em; height: 3em;
color: transparent;
}
.cmn-toggle-switch::before, .cmn-toggle-switch::after {
content: "";
width: 80%; height: 80%;
border: 0 solid white;
display: block;
margin: 10%;
box-sizing: border-box;
position: absolute;
top: 0; right: 0;
transition: 500ms;
--stripe-width: 5px;
--stripe:
transparent calc(50% - var(--stripe-width) / 2),
white 0 calc(50% + var(--stripe-width) / 2),
transparent 0;
}
.cmn-toggle-switch::before {
border-width: var(--stripe-width) 0;
background: linear-gradient(to bottom, var(--stripe));
}
.is-nav-menu-open .cmn-toggle-switch::before {
transform: scale(0);
opacity: 0;
}
.cmn-toggle-switch::after {
background: linear-gradient(to bottom, var(--stripe)), linear-gradient(to right, var(--stripe));
transform: rotate(45deg) scale(0);
opacity: 0;
}
.is-nav-menu-open .cmn-toggle-switch::after {
transform: rotate(45deg);
opacity: 1;
}
</style>
<script>
document.querySelector("header .cmn-toggle-switch").addEventListener("click", () => {
document.documentElement.classList.toggle("is-nav-menu-open");
});
Array.from(document.querySelectorAll("header [role=menuitem]")).forEach((node, index, ar) => {
node.style.setProperty("--i", index);
node.style.setProperty("--k", ar.length - ++index);
});
</script>
</body>
</html>
Последний раз редактировалось рони, 30.01.2020 в 09:49.
|
|
30.01.2020, 11:27
|
|
Профессор
|
|
Регистрация: 20.12.2009
Сообщений: 1,714
|
|
Сообщение от рони
|
не могу точно расчитать transition-delay в строках 97 и 104
|
Возможно так... https://codepen.io/Malleys/pen/wvBbObb?editors=1000
Сообщение от рони
|
??? ок, но яснее не стало.
|
Ну если указать только один файл шрифта (Regular 400), то не получится сделать реально тонкое или жирное начертание. В одном шрифте может быть несколько начертании — прямое (римский, Roman), курсивное (Italic), полужирное (Bold) — отличается от прямого большей толщиной штриха, нормальное (Regular) — отличается от прямого меньшей толщиной штриха, а также узкое (Narrow) и широкое (Wide).
Например, шрифт Roman New Times содержит и нормальное и курсивное начертание. Если не будет реального файла с курсивным начертанием, браузер возьмёт и программно наклонит нормальное начертание. Результат будет не таким же, как если использовать курсивное начертание предусмотренное авторами шрифта.
Вот посмотрите на нормальное и курсивное начертание Roman New Times. Как бы вы ни наклоняли первый ряд с буквами Aa Ee Rr, вы не сможете получить курсивное начертание на втором ряду без файла шрифта, где описано такое курсивное начертание. (Они не просто наклонены, у них отличается форма)
|
|
30.01.2020, 17:02
|
|
Профессор
|
|
Регистрация: 27.05.2010
Сообщений: 33,123
|
|
Malleys,
спасибо огромное, хотелось уточнить, грузятся 4 шрифта, используются по умолчанию один и два с разной толщиной, где четвёртый или зачем?
|
|
|
|