CSS: Hover below the designated target to reveal an expanding dropdown menu

My initial solution involved toggling the visibility on and off when hovering. However, this approach is not optimal as the menu should smoothly transition into view. When the visibility is toggled, the user does not experience the intended transition effect when approaching the "hover element" from below.

Based on my testing, it appears that the issue is primarily related to CSS. Nevertheless, I have included the JavaScript code for reference. The visibility toggle function that was previously mentioned has been commented out.

let items = document.getElementsByClassName('items');
let menuBtn = document.getElementById('menuBtn');
let menuList = document.getElementById('menuList');
let menuClass = document.getElementsByClassName('menu');

menuBtn.addEventListener('mouseenter', func, false);
menuList.addEventListener('mouseleave',func2, false);


//visibilityToggle('hidden', 'none');

function func() {
    console.log('out');
    //visibilityToggle('visible', 'visible');
}

function func2() {

   //visibilityToggle('hidden', 'none');
   console.log('in');
}

function visibilityToggle(vis, point) {
    for (let i = 0; i < items.length; i++){
        items[i].style.visibility = vis;
        items[i].style.pointerEvents = point;
    }
}
.trigger {
  width: 200px;
  height: 53px;
  /*
    border: 1px solid black;
    background: green;
    */
}

.menu {
  width: 200px;
  pointer-events: visible;
}

.menu a {
  background-color: #eee;
  color: black;
  display: block;
  padding: 12px;
  text-decoration: none;
}

.menu a:hover {
  background-color: #ccc;
}

.menu a.active {
  background-color: #04AA6D;
  color: white;
}

.items {
  font-size: 50px;
  opacity: 0;
  position: relative;
  top: -20px;
  cursor: pointer;
  pointer-events: none;
  transition: opacity 400ms ease-in-out, transform 400ms ease-in-out;
}

.trigger:hover .items {
  opacity: 1;
  cursor: pointer;
  transform: translate(0px, 20px);
}

#menuBtn {
  border: 5px solid black;
}
<p>I am lost</p>
<div class="trigger">
  <div class="menu" id="menuList">
    <a href="#" id="menuBtn">Menu</a>
    <div class="items">
      <a href="#" class="items">One</a>
      <a href="#" class="items">Two</a>
      <a href="#" class="items">Three</a>
      <a href="#" class="items">Four</a>
    </div>
  </div>
</div>

Answer №1

It seems like the issue can be resolved without using JavaScript. Simply update the hover event to target #menuBtn and .items, then add pointer-events: initial to reset it. Also, consider changing the link class from items to item as you are applying styles to both the group of links and individual links.

.trigger {
  width: 200px;
  height: 53px;
}

.menu {
  width: 200px;
  pointer-events: visible;
}

.menu a {
  background-color: #eee;
  color: black;
  display: block;
  padding: 12px;
  text-decoration: none;
}

.menu a:hover {
  background-color: #ccc;
}

.menu a.active {
  background-color: #04aa6d;
  color: white;
}

.items {
  font-size: 50px;
  opacity: 0;
  position: relative;
  top: -20px;
  cursor: pointer;
  pointer-events: none;
  transition: opacity 400ms ease-in-out, transform 400ms ease-in-out;
}

#menuBtn:hover + .items,
.items:hover {
  opacity: 1;
  cursor: pointer;
  transform: translate(0px, 20px);
  pointer-events: initial;
}

#menuBtn {
  border: 5px solid black;
}
<div class="trigger">
  <div class="menu" id="menuList">
    <a href="#" id="menuBtn">Menu</a>
    <div class="items">
      <a href="#" class="item">One</a>
      <a href="#" class="item">Two</a>
      <a href="#" class="item">Three</a>
      <a href="#" class="item">Four</a>
    </div>
  </div>
</div>

Answer №2

There was an issue with your items' positioning - they were set to position:relative, which means they stayed in the same position as they are visible. To fix this, make them absolutely positioned by default and only change to relative when hovered over.

.item-div{
  position: absolute;
}
.trigger:hover .items {
  position:relative;
}

let items = document.getElementsByClassName('items');
let menuBtn = document.getElementById('menuBtn');
let menuList = document.getElementById('menuList');
let menuClass = document.getElementsByClassName('menu');

menuBtn.addEventListener('mouseenter', func, false);
menuList.addEventListener('mouseleave',func2, false);


//visibilityToggle('hidden', 'none');

function func() {
    console.log('out');
    //visibilityToggle('visible', 'visible');
}

function func2() {

   //visibilityToggle('hidden', 'none');
   console.log('in');
}

function visibilityToggle(vis, point) {
    for (let i = 0; i < items.length; i++){
        items[i].style.visibility = vis;
        items[i].style.pointerEvents = point;
    }
}
.trigger {
  width: 200px;
  height: 53px;
  /*
    border: 1px solid black;
    background: green;
    */
}

.menu {
  width: 200px;
  pointer-events: visible;
  position:relative;
}

.menu a {
  background-color: #eee;
  color: black;
  display: block;
  padding: 12px;
  text-decoration: none;
}

.menu a:hover {
  background-color: #ccc;
}
.item-div{
position: absolute;
width: 100%
}
.menu a.active {
  background-color: #04AA6D;
  color: white;
}

.items {
  font-size: 50px;
  opacity: 0;
  
  top: -20px;
  cursor: pointer;
  pointer-events: none;
  transition: opacity 400ms ease-in-out, transform 400ms ease-in-out;
}

.trigger:hover .items {
  opacity: 1;
  cursor: pointer;
  transform: translate(0px, 20px);
  position:relative;
}

#menuBtn {
  border: 5px solid black;
}
p:first-child {
  text-decoration: line-through;
}
<p>I am lost</p>
<p>Your are Alive</p>
<div class="trigger">
  <div class="menu" id="menuList">
    <a href="#" id="menuBtn">Menu</a>
    <div class="items item-div">
      <a href="#" class="items">One</a>
      <a href="#" class="items">Two</a>
      <a href="#" class="items">Three</a>
      <a href="#" class="items">Four</a>
    </div>
  </div>
</div>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Leveraging Handlebars Object within JavaScript

Is there a way to pass an entire object into javascript directly? I've tried using the {{{data}}} and {{data}} methods as suggested in other posts, but it doesn't seem to be working for me. Here's what I have in my handlebars file: <scri ...

Retrieving exclusive npm packages from an npmjs user

I am currently facing a challenge with transferring all of our npm modules from npmjs.com to a new location. The issue is that our modules are saved under a private npm user account, making it difficult for me to programmatically access and consume all the ...

I'm puzzled as to why my JavaScript code only functions correctly when I place it after the HTML, despite having a window.onload event handler in place

Just beginning my journey in a CS class and seeking guidance for my lack of basic knowledge. I've noticed that this JS code only works if placed after the HTML, not within the head tag. Shouldn't window.onload handle that? Can someone clarify wha ...

Retrieve the value of the object within the mysterious index loop in JavaScript

I have retrieved search results from the data, and each time the index of my search result varies. At one point, the result may appear in the 4th index, while at another time it might be in the 100th index. How can I retrieve the rank value from within t ...

Synchronizing the call of various views in an Angular application

I'm currently working on an angular single page application with a specific structure in mind. "app.parent - main parent state" "app.parent.childState - child state" "app.parent.childSatate" includes 4 different named views. My goal is to display so ...

`Bootstrap 4 fails to center elements vertically`

Struggling to center a panel using Bootstrap 4? Despite adding classes like align-items-center and h-100, the header continues to stay at the top of the page. Does anyone know the solution? This is in an Angular 4 project with Bootstrap. <div class=&ap ...

The code functions perfectly on my local machine, however it is not cooperating on the HostGator server

A selection box based on values should appear in text fields, The current code is functional in local host but not working on the hostgator server For example, displaying country options based on the selected state and districts based on the selected sta ...

Is there a way to extract the numerical value from a string within an ID of a div and transform the rest of the string into a variable?

Looking to extract the final id of a div and convert it to a variable. <div class="margin_bot" id="itemRows2"> <p id="rowNum1">...</p> <p id="rowNum2">...</p> <p id="rowNum3">...</p> <p id="rowNum4"> ...

CSS background image referencing in React to the public folder's path

I am currently working on a project using Create-React-App and I am trying to set a background image for my header section. Here is how I'm attempting to do it: background-image: url('~/Screenshot_11.png'); However, I encountered an error w ...

Increase the size of a centered image within a table

Lately, I've felt like my mind is starting to unravel. Here's the issue at hand: I've been attempting to resize an image within a table cell so that it spans the full width of the cell. Strangely enough, this seems to be harder than anticip ...

The table row's background image splitting into two halves

I am working on a table row class called logo, which has specific attributes. .logo { background: url("img/logo.png") no-repeat left top !important; } Currently, I have successfully placed an image at the top left of every row. However, my goal is ...

Ways to retrieve a designated object linked to a specific value within a JavaScript structure

I am facing a challenge where I need to set a javascript property object with values from another property object within the same instance. Currently, I have the following object: var PLAYER = { slides: { { slide_id: 60, slide_content: 'c ...

Utilizing a Chrome packaged app to interact with a local sqlite database through reading and writing operations

Is it feasible to access and manipulate a local sqlite database from within a Chrome packaged app? I am currently able to work with a locally stored JSON file for my app data, but now I also require the functionality to interact with a sqlite database in ...

Transform the data format received from the AJAX request - modify the input value

I have a data variable that contains an object structured as follows: { "details": { "id": 10, "name": John Doe, "hobbies": [{ "id": 1, "name": "Football" }, { "id": 2, "name": "Badminton" }, ...

How to style text in CSS with a numbered underline beneath

Is there a way to apply underlining to text and include a small number underneath the underline in a similar style shown in this image, by utilizing css, html, or javascript? ...

Resize images smoothly without disrupting the anchor scrolling

I have created a website with the following design: (Caution: The site is built using AngularJS on a server that may not serve it correctly - please visit directly instead of using browser reload.) However, I am facing two conflicting requirements... ...

Laravel application faces issues with URL rewriting generating incorrect URLs in compiled CSS files

Having some trouble compiling Font Awesome SCSS files in my Laravel application. I installed Font Awesome using NPM, and the compiled CSS is stored in the 'public/css/' folder while a 'public/fonts/' folder was also created. However, th ...

Tips for passing an array between components in Angular 2

My goal is to create a to-do list with multiple components. Initially, I have 2 components and plan to add more later. I will be sharing an array of tasks using the Tache class. Navbar Component import { Component } from '@angular/core'; impor ...

The content located at “http://localhost:3000/public/static/” was restricted because of a mismatch in MIME type (text/html) which triggered the X-Content-Type-Options:nosniff protocol

https://i.stack.imgur.com/7Etn7.png Every time I try to run the server with nodemon, I keep encountering the error mentioned in the title. Below is the code snippet from the JavaScript file: const express = require('express') const path = requir ...

Transferring a value via AJAX that has been modified by a previous AJAX call

In my form, users input values which are used to calculate a result. The calculation is performed through AJAX calls triggered by onchange events on the user-edited fields. This process works as expected. However, there is a hidden field that also gets up ...