Problem
I have a side menu that appears when click on button, which works fine. But now I want to clean up my code, shorten it if possible. I was wondering if there is an easier and cleaner way to achieve the same result shown in the example below.
I would like to reduce the css and delete the “setTimeout” function from js code. I don’t want the side slide to depend on setTimeout. There are other ways to get the same result, but I’m not very good. Can anyone help me ? I’m new, sorry my dirty code, I’m trying to learn and stackoverflow helps with that.
var menu = document.querySelector(".mob_menu_button");
function mobile_menu(e) {
e.stopPropagation();
var x = document.getElementById("mts_mobile_menu");
if (!x.classList.contains("active")) {
x.classList.add("active");
menu.innerHTML = "<span>Close Menu<span>";
} else {
x.classList.add("side_hide");
menu.innerHTML = "<span>Open menu</span>";
setTimeout(function () {
x.classList.remove("active");
x.classList.remove("hide");
}, 100);
}
}
document.addEventListener("click", function (e) {
var x = document.getElementById("mts_mobile_menu");
if (e.target.id !== "mts_mobile_menu" && x.classList.contains("active")) {
x.classList.add("hide");
menu.innerHTML = "<span>Open menu</span>";
setTimeout(function () {
x.classList.remove("active");
x.classList.remove("hide");
}, 400);
}
});
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
/*Items menu*/
.user_menu {
display: flex;
flex-direction: column;
}
/*Menu header info*/
.display.name {
font-size: 15px;
font-weight: 500;
color: #303238;
}
.display.mail {
font-size: 13px;
color: #3d5afe;
}
hr.solid {
border-top: 1px solid #e0e0e0;
margin: 10px 0px 10px 0px;
}
/*Text Link css*/
.user_menu.item > a {
display: flex;
justify-content: flex-start;
align-items: center;
padding: 8px 0;
font-size: 13px;
color: #75777d;
}
.user_menu.item:hover > a {
color: #2e323a;
}
/*Icon Button Toggle Menu*/
.mob_menu_button {
display: flex;
align-content: center;
justify-content: center;
align-items: flex-end;
width: 20%;
background: #fff!important;
font-weight: 500!important;
position: absolute;
top: 30px;
right: 30px;
}
.icn_button {
margin: 0;
font-size: 14px;
}
.icn_button:before {
margin: 0;
}
.icn_button:after {
margin: 0;
}
/*Icon Items Menu*/
.icn_menu:before,
.icon_menu:after {
margin: 0px;
padding: 0px;
font-size: 16px;
}
.icn_menu {
margin-right: 10px;
display: flex !important;
align-items: center;
justify-content: center;
width: 22px;
height: 22px;
}
/* User Menu For header website */
.mts_mob_container {
display: flex;
position: fixed;
z-index: 999;
/* height: 100%; */
top: 0;
left: 0;
width: 100%;
background: #000000d6;
}
.mts_sidenav_box {
display: block;
width: 100%;
}
.mts_sidenav_content {
display: none;
padding: 20px;
background-color: #fff;
min-width: 160px;
width: 280px;
border-radius: 3px;
overflow-x: hidden;
overflow-y: auto;
z-index: 999;
position: relative;
animation: animateFromLeft 0.4s;
}
@keyframes animateFromLeft {
from {
left: -500px;
opacity: 0;
}
to {
left: 0;
opacity: 1;
}
}
@keyframes animateToLeft {
from {
left: 0;
opacity: 1;
}
to {
left: -500px;
opacity: 0;
}
}
.active {
display: block !important;
height: 100vh;
overflow: hidden;
width: 75%;
}
.mts_sidenav_content.hide {
animation: animateToLeft 0.8s;
}
<button onclick="mobile_menu(event)" class="mob_menu_button">Open menu</button>
<div class="mts_mob_container">
<div id="mts_mobile_menu" class="mts_sidenav_content">
<div class="mts_sidenav_box">
<div class="user_menu header">
<span class="display name">Hello User...</span>
<span class="display mail">display_email</span>
</div>
<hr class="solid" />
<div class="user_menu item">
<a href="/account">
<i class="icn_menu fa-regular fa-user">1</i>
<span class="link_text">Dashboard</span>
</a>
</div>
<div class="user_menu item">
<a href="ordini">
<i class="icn_menu fa-regular fa-basket-shopping">2</i>
<span class="link_text">I miei ordini</span>
</a>
</div>
<div class="user_menu item">
<a href="libreria">
<i class="icn_menu fa-regular fa-cloud-arrow-down">3</i>
<span class="link_text">Downloads</span>
</a>
</div>
<div class="user_menu item">
<a href="impostazioni">
<i class="icn_menu fa-regular fa-gear">4</i>
<span class="link_text">Impostazioni</span>
</a>
</div>
<div class="user_menu item">
<a href="wp-login.php?action=logout">
<i class="icn_menu fa-regular fa-arrow-right-from-bracket">5</i>
<span class="link_text">Logout</span>
</a>
</div>
</div>
</div>
</div>
Solution
From a short review;
-
x
is not an evocative name, -
JavaScript is lowerCamelCase so
mobile_menu
->mobileMenu
-
Even
mobileMenu
is not a great name, it does not tell me what it does -
var menu
should beconst menuButton
-
This is copy pasted, you should have a function that takes and element, and a delay;
function delayExecution(e, delay){ setTimeout(function () { e.classList.remove("active"); e.classList.remove("hide"); }, delay); }
-
I am not a good reviewer of CSS, but you are not violating the cardinal rule, so seems okay to me
-
Avoid wiring functions in HTML like this;
onclick="mobile_menu(event)"
, useaddEventListener
like fordocument