Как создать эффект расширения пунктов меню при наведении мыши

Как создать эффект расширения пунктов меню при наведении мыши

От автора: вы когда-нибудь использовали в проекте плагин WordPress Slider Revolution? Если ответ «да», вы могли заметить мини-панель инструментов, которая появляется в правом углу страницы конфигурации плагина.

Первоначально видны только иконки, что делает все это красивым и компактным. Затем каждый раз при наведении курсора происходит расширение текста под ним.

В этом руководстве давайте почерпнем вдохновение из этого эффекта и создаем нечто подобное. Вот к чему мы будем стремиться:

Мы рассмотрим это быстро, сначала выписав разметку, стилизовав ее с помощью CSS, а затем добавив поведение с помощью JavaScript. Перед тем, как закончить, мы рассмотрим также подход, основанный на чистом CSS. Давайте начнем!

Все о Slider Revolution

Slider Revolution — это нечто большее, чем просто плагин слайдера для WordPress, и он буквально изменил способ, которым разработчики создают темы WordPress. Благодаря продажам около 350 тыс. на момент написания статьи, его популярность сделала создателей themepunch одним из самых успешных авторов на Envato Market! Если вы хотите узнать больше об этом, вот несколько полезных ресурсов:

1. Начнем с разметки страницы

Мы начнем с header, который будет содержать заголовок и неупорядоченный список. Каждый элемент списка будет содержать кнопку. Этот элемент будет служить оболочкой для SVG иконки и соответствующего текста.

<header> <h1>Mini Toolbar</h1> <ul> <li> <button> <svg>...</svg> <span>Pages</span> </button> </li> <li> <button> <svg>...</svg> <span>Collection</span> </button> </li> <li> <button> <svg>...</svg> <span>Appearance</span> </button> </li> <li> <button> <svg>...</svg> <span>Options</span> </button> </li> <li> <button> <svg>...</svg> <span>Search</span> </button> </li> </ul>
</header>

Иконки, используемые здесь, взяты из Envato Elements. Вы можете узнать этот набор иконок, поскольку я уже использовал его в предыдущем руководстве как часть SVG-спрайта.

2. Определяем стили с помощью CSS

Заголовок будет вести себя как flex-контейнер. Его дочерние элементы будут вертикально центрированы и распределены по главной оси. Мы также зададим для него максимальную ширину и отцентрируем его по горизонтали:

/*CUSTOM VARIABLES HERE*/ header { display: flex; align-items: center; justify-content: space-between; max-width: 1000px; padding-left: 15px; margin: 0 auto; border-radius: 5px; background: var(--blue);
}

И список, и кнопки будут flex-контейнерами с вертикально центрированным содержимым:

header ul,
header button { display: flex; align-items: center;
}

Все кнопки будут иметь разные цвета, а некоторые значения цветов будут соответствовать значениям мини-панели инструментов Slider Revolution. При наведении курсора на кнопку ее цвет слегка подсвечивается благодаря встроенной функции CSS filter().

Мы также зададим для них overflow: hidden, потому что хотим скрыть переполняющий контент во время анимации слайда:

/*CUSTOM VARIABLES HERE*/ header button { padding: 15px; overflow: hidden; transition: filter 0.25s;
} header li:nth-child(1) button { background: var(--green);
} header li:nth-child(2) button { background: var(--lightblue);
} header li:nth-child(3) button { background: var(--gray);
} header li:nth-child(4) button { background: var(--red);
} header li:nth-child(5) button { background: var(--orange);
} header button:hover { filter: brightness(110%);
}

SVG-иконки

SVG будет белого цвета. И, как было сказано ранее, текст изначально будет скрыт. Он станет видимым, когда мы наведем курсор на родительскую кнопку:

/*CUSTOM VARIABLES HERE*/ header button svg { fill: var(--white);
} header button span { opacity: 0; visibility: hidden; transition: all 0.25s ease-out;
} header button:hover span { margin-left: 15px; opacity: 1; visibility: visible;
}

3. JavaScript: прослушивание события мыши

Когда DOM будет готов, мы захватываем все кнопки заголовка. Затем мы перебираем их и выполняем следующие действия:

Захватываем текстовый элемент и рассчитываем его ширину по умолчанию.

Затем устанавливаем ширину этого элемента равной 0.

Каждый раз, когда мы наводим курсор на кнопку, мы сбрасываем ширину ее текстового элемента по умолчанию.

Затем каждый раз, когда мы перестаем наводить курсор на кнопку, мы устанавливаем ее ширину равной 0.

Вот JavaScript, который реализует это поведение:

const buttons = document.querySelectorAll("header button"); buttons.forEach(el => { // 1 const span = el.lastElementChild; const width = span.offsetWidth; // 2 span.style.width = 0; // 3 el.addEventListener("mouseenter", () => { span.style.width = `${width}px`; }); // 4 el.addEventListener("mouseleave", () => { span.style.width = 0; });
});

Решение на чистом CSS

И последняя вещь. Сначала я попытался создать демо-версию только на CSS. Итак, изначально я установил для свойства max-width элемента span значение 0. Затем, когда на кнопки наводится курсор, это значение изменяется на фиксированные 110px. Это прекрасно работает, но у этого решения есть ограничения, потому что в цикле есть жестко закодированное значение.

Посмотрите решение на чистом CSS ниже (возможно, у вас есть идеи о том, как его улучшить?):

Если мы добавим новый пункт меню, который содержит намного больше текста, мы столкнемся с проблемами. Вы можете подумать, что можно установить для max-width значение auto, но, к сожалению, это решение не будет работать вообще!
Именно эти ограничения заставили меня задуматься о быстром решении с помощью JavaScript.

Заключение

На этом заканчивается еще один короткий урок! Спасибо за то, что следите за мной, надеюсь, вы узнали что-то новое сегодня. Не стесняйтесь расширить демонстрацию и (например) заставить ее работать на событиях клика вместо событий мыши. Плюс, если вы это сделаете, обязательно поделитесь своим результатом. Еще раз спасибо за прочтение!

Автор: George Martsoukos

Источник: https://webdesign.tutsplus.com

Редакция: Команда webformyself.