I'm working on a klondike solitaire game and I created a menu that is displayed on the top of the page. On laptops and computers I want to look like regular menus, considering many players are used to such menus, but on mobile devices, I wanted the menu items to be easy to click.
<div class="menu-bar" id="menuBar"></div>
Here is the css style for the regular menu:
body {
padding: 0;
margin: 0;
}
/* Basic menu styling for desktop */
.menu-bar {
display: flex;
background-color: #333;
padding: 10px;
justify-content: flex-start;
/* Align menu items to the left */
font-family: Arial, Helvetica, sans-serif
}
.menu-item {
color: white;
padding: 10px;
cursor: pointer;
position: relative;
text-align: center;
flex: 0;
display: flex;
/* Align icon and text on the same line */
align-items: center;
justify-content: center;
white-space: nowrap;
}
.menu-item {
text-align: left;
}
.menu-item i {
font-size: 1.5rem;
margin-right: 8px;
/* Space between icon and text */
}
.menu-item .shortcut,
.submenu-item .shortcut {
color: #999;
}
.menu-item .shortcut {
display: none;
/* too ugly on main items */
}
.submenu {
display: none;
position: absolute;
background-color: #444;
top: 40px;
left: 0;
width: 150px;
}
.submenu-item {
padding: 10px;
color: white;
}
.submenu-item:hover {
background-color: #666;
}
.menu-item.active .submenu {
display: block;
}
To make the menu act differently on mobile devices we are going to use media queries:
/* Mobile styles */
@media (max-width: 768px) {
.menu-bar {
flex-direction: column;
position: relative;
display: grid;
/* Grid layout for mobile */
grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
/* Evenly divide menu items into columns */
gap: 10px;
}
.menu-item {
padding: 15px 5px;
display: block;
/* Stack icon and text vertically on mobile */
white-space: normal;
}
.menu-item {
text-align: center;
}
.menu-item i {
font-size: 2rem;
/* Larger icon for mobile */
margin-right: 0;
/* Remove margin on mobile */
display: block;
/* Icon on a separate line */
text-align: center;
}
.menu-item .shortcut {
display: none;
/* Hide shortcuts on mobile */
}
.submenu {
position: static;
display: none;
width: 100%;
background-color: #333;
top: 0;
left: 0;
z-index: 10;
}
.menu-item.active .submenu {
display: block;
}
.menu-bar.active .menu-item {
display: none;
}
.menu-bar.active .menu-item.active {
display: block;
}
.submenu .close-btn {
color: white;
padding: 10px;
cursor: pointer;
text-align: center;
background-color: #444;
}
.submenu .close-btn:hover {
background-color: #666;
}
}
and finally the javascript:
const menuData = [
{
icon: "fa-solid fa-gamepad", // Icon for "New Game..."
icon_text: "🎮", // Emoji for game controller
name: "New Game...",
shortcut: "",
submenu: {
items: [
{
name: "Restart",
icon: "fa-solid fa-undo-alt", // Icon for "Restart"
icon_text: "🔄", // Emoji for restart
shortcut: "Ctrl+N"
},
{
name: "Start New",
icon: "fa-solid fa-play-circle", // Icon for "Start New"
icon_text: "▶️", // Emoji for start/play
shortcut: ""
}
]
}
},
{
icon: "fa-solid fa-cog", // Icon for "Settings..."
name: "Settings...",
icon_text: "⚙️", // Emoji for settings
shortcut: "Ctrl+S",
submenu: null
},
{
icon: "fa-solid fa-th-large", // Icon for "More Solitaire..."
icon_text: "🃏", // Emoji for cards/games
name: "More Solitaire...",
shortcut: "Ctrl+P",
submenu: null
}
];
function createMenu(menuData) {
const mode = "emoji";
const menuBar = document.getElementById('menuBar');
menuData.forEach(item => {
const menuItem = document.createElement('div');
menuItem.classList.add('menu-item');
// Add icon
const icon = document.createElement('i');
(mode === "emoji")
? (icon.innerText = item.icon_text, icon.style["font-style"] = "normal")
: icon.className = item.icon;
menuItem.appendChild(icon);
// Add name
const name = document.createElement('div');
name.textContent = item.name;
menuItem.appendChild(name);
// Add shortcut if available
if (item.shortcut) {
const shortcut = document.createElement('span');
shortcut.classList.add('shortcut');
shortcut.textContent = ` (${item.shortcut})`;
menuItem.appendChild(shortcut);
}
// Check for submenu
if (item.submenu) {
const submenu = document.createElement('div');
submenu.classList.add('submenu');
item.submenu.items.forEach(subItem => {
const submenuItem = document.createElement('div');
submenuItem.classList.add('submenu-item');
// Submenu item icon
const subIcon = document.createElement('i');
(mode === "emoji")
? (subIcon.innerText = subItem.icon_text, subIcon.style["font-style"] = "normal")
: subIcon.className = subItem.icon;
submenuItem.appendChild(subIcon);
// Submenu item name
const subName = document.createTextNode(` ${subItem.name}`);
submenuItem.appendChild(subName);
// Submenu item shortcut
if (subItem.shortcut) {
const subShortcut = document.createElement('span');
subShortcut.classList.add('shortcut');
subShortcut.textContent = ` (${subItem.shortcut})`;
submenuItem.appendChild(subShortcut);
}
submenu.appendChild(submenuItem);
});
// Add a close button at the end of the submenu for mobile
const closeButton = document.createElement('div');
closeButton.classList.add('submenu-item'); // Make it look like other submenu items
// Add the chevron icon
const closeIcon = document.createElement('i');
(mode === "emoji")
? (closeIcon.innerText = '⬆️', closeIcon.style["font-style"] = "normal")
: closeIcon.className = 'fa-solid fa-chevron-up';
closeButton.appendChild(closeIcon);
// Add the "Close" text
const closeText = document.createTextNode(' Close');
closeButton.appendChild(closeText);
closeButton.addEventListener('click', function (event) {
event.stopPropagation(); // Prevent the click from propagating to the parent .menu-item
menuItem.classList.remove('active'); // Close the submenu
});
submenu.appendChild(closeButton);
menuItem.appendChild(submenu);
// Add event listener for clicking to show/hide submenu
menuItem.addEventListener('click', function (event) {
event.stopPropagation(); // Prevent closing when clicking inside the menu
const allMenuItems = document.querySelectorAll('.menu-item');
if (window.innerWidth <= 768) {
allMenuItems.forEach(item => item.classList.remove('active')); // Close all
menuItem.classList.add('active'); // Open clicked one
} else {
menuItem.classList.toggle('active'); // Toggle submenu on desktop
}
});
// Close the submenu when clicking outside of the menu
document.addEventListener('click', function (event) {
const allMenuItems = document.querySelectorAll('.menu-item');
allMenuItems.forEach(menuItem => {
if (!menuItem.contains(event.target)) {
menuItem.classList.remove('active'); // Close the submenu if clicked outside
}
});
});
}
menuBar.appendChild(menuItem);
});
}
// Initialize the menu
createMenu(menuData);
// Add resize event listener to handle dynamic resizing
window.addEventListener('resize', function () {
const menuBar = document.getElementById('menuBar');
if (window.innerWidth > 768) {
// On desktop, ensure that all submenus are collapsed by default
const allMenuItems = document.querySelectorAll('.menu-item');
allMenuItems.forEach(item => item.classList.remove('active'));
}
});
You can play with the code here:
https://codepen.io/quantotius/pen/KKOWjyd
Do you need to increase your credit score?
Do you intend to upgrade your school grade?
Do you want to hack your cheating spouse's email, WhatsApp, Facebook, Instagram, or any other social network?
Do you need any information concerning any databases?
Do you need to retrieve deleted files?
Do you need to clear your criminal records with the DMV?
Do you want to remove any site or link from any blog?
You should contact this hacker; he is reliable and good at hacking.
Contact: cybergoldenhacker at gmail dot com