


A Top Navigation Menu for a Klondike Solitaire Games, That Changes Aspect on Mobile Devices
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 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
The above is the detailed content of A Top Navigation Menu for a Klondike Solitaire Games, That Changes Aspect on Mobile Devices. For more information, please follow other related articles on the PHP Chinese website!

Yes,youshouldlearnbothFlexboxandGrid.1)Flexboxisidealforone-dimensional,flexiblelayoutslikenavigationmenus.2)Gridexcelsintwo-dimensional,complexdesignssuchasmagazinelayouts.3)Combiningbothenhanceslayoutflexibilityandresponsiveness,allowingforstructur

What does it look like to refactor your own code? John Rhea picks apart an old CSS animation he wrote and walks through the thought process of optimizing it.

CSSanimationsarenotinherentlyhardbutrequirepracticeandunderstandingofCSSpropertiesandtimingfunctions.1)Startwithsimpleanimationslikescalingabuttononhoverusingkeyframes.2)Useeasingfunctionslikecubic-bezierfornaturaleffects,suchasabounceanimation.3)For

@keyframesispopularduetoitsversatilityandpowerincreatingsmoothCSSanimations.Keytricksinclude:1)Definingsmoothtransitionsbetweenstates,2)Animatingmultiplepropertiessimultaneously,3)Usingvendorprefixesforbrowsercompatibility,4)CombiningwithJavaScriptfo

CSSCountersareusedtomanageautomaticnumberinginwebdesigns.1)Theycanbeusedfortablesofcontents,listitems,andcustomnumbering.2)Advancedusesincludenestednumberingsystems.3)Challengesincludebrowsercompatibilityandperformanceissues.4)Creativeusesinvolvecust

Using scroll shadows, especially for mobile devices, is a subtle bit of UX that Chris has covered before. Geoff covered a newer approach that uses the animation-timeline property. Here’s yet another way.

Let’s run through a quick refresher. Image maps date all the way back to HTML 3.2, where, first, server-side maps and then client-side maps defined clickable regions over an image using map and area elements.

The State of Devs survey is now open to participation, and unlike previous surveys it covers everything except code: career, workplace, but also health, hobbies, and more.


Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

SecLists
SecLists is the ultimate security tester's companion. It is a collection of various types of lists that are frequently used during security assessments, all in one place. SecLists helps make security testing more efficient and productive by conveniently providing all the lists a security tester might need. List types include usernames, passwords, URLs, fuzzing payloads, sensitive data patterns, web shells, and more. The tester can simply pull this repository onto a new test machine and he will have access to every type of list he needs.

mPDF
mPDF is a PHP library that can generate PDF files from UTF-8 encoded HTML. The original author, Ian Back, wrote mPDF to output PDF files "on the fly" from his website and handle different languages. It is slower than original scripts like HTML2FPDF and produces larger files when using Unicode fonts, but supports CSS styles etc. and has a lot of enhancements. Supports almost all languages, including RTL (Arabic and Hebrew) and CJK (Chinese, Japanese and Korean). Supports nested block-level elements (such as P, DIV),

Notepad++7.3.1
Easy-to-use and free code editor

MantisBT
Mantis is an easy-to-deploy web-based defect tracking tool designed to aid in product defect tracking. It requires PHP, MySQL and a web server. Check out our demo and hosting services.

PhpStorm Mac version
The latest (2018.2.1) professional PHP integrated development tool
