I have a menu that is displayed on the location where the user clicks on the web page. This is how it works:
a hidden DIV with menu content is present on the bottom of the page
click event triggers a function
DIV is displayed by altering it's style (to trigger the hover CSS)
DIV is positioned on the mouse click location
DIV's display style is unset after a small fraction of time (0,5 seconds)
the user has the option to use the menu as long as he hovers over it
This works in Chrome/Opera, but not in Internet Explorer/Edge. There's a 1px (my guess, since I can't measure it) distance the user has to move the mouse to trigger the hover on Internet Explorer/Edge (within the 0,5 seconds time frame).
Of course, I can fix this problem by repositioning the menu 1px left/up, but the point of this question is to try to understand why is this happening.
This is the HTML stripped of unnecessary code:
<!DOCTYPE html>
<html>
<head>
<script src="https://code.jquery.com/jquery-3.1.1.js"></script>
<script>
$(document).click(function(e) {
menu = document.getElementById("m");
menu.style.display = 'block';
menu.style.left = e.pageX + "px";
menu.style.top = e.pageY + "px";
setTimeout(function(){ menu.style.display = ''; }, 500);
});
</script>
<style>
html, body
{
height: 100%;
margin: 0;
padding: 0;
}
#m
{
display: none;
position: absolute;
z-index: 100;
background-color: white;
}
#m:hover
{
display: block;
}
#m ul
{
color: #1E90FF;
list-style-type: none;
margin: 0;
padding: 0;
border: 1px solid gray;
}
#m li
{
margin: 0;
padding: 5px 10px;
}
#m li:hover
{
color: white;
background-color: #1E90FF;
}
</style>
<body>
<div id="m">
<ul>
<li>One</li>
<li>Two</li>
<li>Three</li>
</ul>
</div>
</body>
</html>
Related
I'm trying to make a dropdown menu with html and css. I followed a ton of tutorials but they don't seem to work for me and I can not figure out why. I have an for a menubar that's always showing on the top of the screen and I want another to show when you hover the burgermenu on the left. This is my current code:
<body>
<div class='menudiv'>
<ul>
<li><a><img class='dropdown' src='burgermenu.png' alt='OpenMenu' height='90px' width="90px" onmouseover="this.src='burgermenuwit.png'" onmouseout="this.src='burgermenu.png'"></a></li>
<li style="float:right"><img src='pp.png' alt='LogIn' height='90px' width="95px" onmouseover="this.src='ppwit.png'" onmouseout="this.src='pp.png'"></li>
</ul>
</div>
<div class='logo'>
<a href="#home"><img src='flowy_logo.png' alt='Logo' height='95px', widht='95px' onmouseover="this.src='flowy_logowit.png'" onmouseout="this.src='flowy_logo.png'">
</div>
<div class='menu2'>
<ul>
<li><a>Meten</a></li>
<li><a>Huidige waardes</a></li>
<li><a>Geschiedenis</a></li>
<li><a>Contact</a></li>
</ul>
</div>
</body>
</html>
and css:
.menudiv ul {
font-family: "Georgia", "Times New Roman", "Serif";
font-size: 25px;
list-style-type: none;
margin: 0;
padding: 0;
overflow: hidden;
background-color: rgb(102, 75, 255);
}
.menudiv ul li {
float: left;
cursor: pointer;
}
.menudiv ul li a {
display: block;
padding: 8px;
}
.logo img {
position: relative;
top: -105px;
margin-left: auto;
margin-right: auto;
display: block;
}
.menu2 ul {
position: relative;
list-style-type: none;
margin: 0;
padding: 0;
font-size: 30px;
font-family: Verdana, Geneva, Tahoma, sans-serif;
top: -100px;
}
.menu2 ul li a {
display: block;
width: 200px;
background-color: rgb(102, 75, 255);
padding-top: 10px;
padding-bottom: 10px;
padding-left: 10px;
padding-right: 10px;
}
.menu2 ul li a:hover {
color: white;
cursor: pointer;
}
.menu2 {
display: none;
}
.dropdown:hover .menu2 {
display: block;
}
Can anybody tell me why it's not working?
You can achieve this by listening for the 'mouseover' event and changing the display style for menu2 to 'inline-block' (the ordinary 'block' takes the full width which is bad for 'mouseout'). You have to listen on both, the trigger ('Open Menu' link) and the menu itself.
To close the menu on 'mouseout' there is more code necessary then with a small inline onmouseout handler is possible:
First you have to check if the menu is hovered. Therefor you need a litle timeout before closing the menu from 'mouseout' on the trigger, so that the cursor has a chance to reach the menu.
Secondly you need to know that the 'mouseout' event is fired when changing to the next a or li tag in the menu. Since the 'mouseout' event is faster then the eventbubbling of the next 'mouseover' event from the a or li tag to the containing menu2, you need a second timeout for 'mouseout' on menu2 for checking if it is still hovered.
And third you have to check if the cursor is hovering again over the trigger when he has left the menu, otherwise the menu would remain closed and the 'mouseover' event on the trigger would not fire again. This can be checked in the second timeout check.
And fourth you need to wrap all that in an event handler that executes it not until the DOM is loaded. Otherwise the hover event listeners would have no effect because there would be no element to bind the listener to when the script is executed.
For the check if hovered use two variables that get true on 'mouseover' and false on 'mouseout'.
Here is a working example:
document.addEventListener('DOMContentLoaded', function() {
const menu_trigger = document.querySelector('#menu-trigger');
const menu2 = document.querySelector('.menu2');
var trigger_hovered = false;
var menu2_hovered = false;
menu_trigger.addEventListener('mouseover', function() {
trigger_hovered = true;
menu2.style.display = 'inline-block';
});
menu_trigger.addEventListener('mouseout', function() {
trigger_hovered = false;
setTimeout(function() {
if (menu2_hovered == false) {
menu2.style.display = 'none';
}
}, 10);
});
menu2.addEventListener('mouseover', function() {
menu2_hovered = true;
});
menu2.addEventListener('mouseout', function() {
menu2_hovered = false;
setTimeout(function() {
if (menu2_hovered == false && trigger_hovered == false) {
menu2.style.display = 'none';
}
}, 10);
});
});
* {
margin: 0;
padding: 0;
}
.menudiv ul {
display: flex;
justify-content: space-between;
overflow: hidden;
width: 100vw;
font-size: 25px;
font-family: "Georgia", "Times New Roman", "Serif";
list-style-type: none;
background-color: rgb(102, 75, 255);
}
.menudiv ul li a {
display: block;
padding: 8px;
cursor: pointer;
}
.menu2 {
display: none;
}
.menu2 ul {
list-style-type: none;
font-size: 30px;
font-family: Verdana, Geneva, Tahoma, sans-serif;
}
.menu2 ul li a {
display: block;
width: 200px;
padding: 10px;
background-color: rgb(102, 75, 255);
}
.menu2 ul li a:hover {
color: white;
cursor: pointer;
}
<div class='menudiv'>
<ul>
<li id="menu-trigger">
<a>Open Menu</a>
</li>
<li>Login</li>
</ul>
</div>
<div class='menu2'>
<ul>
<li><a>Meten</a></li>
<li><a>Huidige waardes</a></li>
<li><a>Geschiedenis</a></li>
<li><a>Contact</a></li>
</ul>
</div>
Here is a JSFiddle with everything fixed: https://jsfiddle.net/dwauq9mL/
I had to change some things for my own convenience since I didn't have the images.
The problem: Since, menu2 is NOT a child of the the element on whose hover event you want it to display on, it will not work.
The solution: You need to put menu2 inside the li of the burger menu. You need to remove the .dropdown class from the burger image and add it to its parent li.
When you do this it is bound to mess the layout up. I wrote a JSFiddle for you (should be mentioned up) with everything fixed.
I recommend you not to use floats since they are deprecated. I removed the floats and used flexbox instead which is much better and recommended. I suggest you go learn Flexbox. I will link a few resources at the end of this answer.
CSS Tricks article on Flexbox:
https://css-tricks.com/snippets/css/a-guide-to-flexbox/
Fun little game to learn Flexbox: https://flexboxfroggy.com/
bellow code will work only if there is no space between burgermenu button and menu2, I would suggest to add background color to menu2 div, so that you can see the div size
<script>
var menu2 = document.querySelector('.menu2');
document.querySelector('.dropdown')
.addEventListener('mouseover', function() {
menu2.style.display = 'block';
});
document.querySelector('.dropdown')
.addEventListener('mouseout', function() {
menu2.style.display = 'none';
});
menu2.addEventListener('mouseover', function() {
menu2.style.display = 'block';
});
menu2.addEventListener('mouseout', function() {
menu2.style.display = 'none';
});
</script>
if there is some space in between menu button and menu, you can manage this by adding some time delay for display:none, I don't know this will be the good way or not, but it will work.
I'm trying to make a basic FAQ of sorts using a simple click on element to reveal the answer to the FAQ. Spoiler..
I have found a really handy piece of coding, but everything I try I cannot prevent the mouse hover from making the answer disappear.
I need the answer to remain on the page until the user is ready to click the next FAQ.
I hope someone can help, thank you very much.
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<h1>This is a heading</h1>
<p>This is a paragraph.</p>
<p><b>This is an FAQ</b><br />
<p>This is also FAQ click below for the answer</p>
<div class=spoiler><div>
My hidden text
</div></div>
</body>
</html>
.spoiler { display: relative; cursor: pointer; margin-bottom: 10px; margin-top: 10px; }
.spoiler:before { content: "Answer:"; position:absolute; cursor: pointer; font-weight: bold; color: #2C3635; }
.spoiler > div { cursor: default; top: 0px; display: none; position: relative; right: 10px; top: 20px; border: #A6B2A6 1px solid; background: darkgrey; padding: 0px 10px 15px 10px; border-radius: 4px; }
.spoiler > div:before { content: ""; display: block; width: 100%; height: 20px; margin-top: -20px; }
.spoiler:active > div { display: block; }
.spoiler > div:hover { display: block; }
https://jsfiddle.net/g9b3ugzh/
The HTML details and summary elements are perfect for this. The basics without any CSS required are as follows:
<details>
<summary>Answer:</summary>
<p>My hidden text</p>
</details>
JSFiddle demo
You could give the code, it is a JavaScript solution, in the JSFiddle a go.
var spoiler = document.getElementsByClassName('spoiler');
var showSpoiler = function() {
this.classList.add("show-spoiler");
}
for (var i = 0; i < spoiler.length; i++) {
spoiler[i].addEventListener("mouseover", showSpoiler);
}
Had to disable and amend some CSS too though, to make it work:
Took off position: absolute; from .spoiler:before
Took off top declarations from .spoiler > div
Removed the :hover and :active states on .spoiler
I created a on/off button using html/css. When on or off button is clicked it will link to python script using href tag. But i dont want buttons to appear seperate. so what i am trying is When ON button is clicked, off button should go invisible or hidden and vice-versa. When one button is clicked it should swap its position with another button. So it will appear as single button.
<!DOCTYPE html>
<head>
title>{{ title }}</title>
<style type="text/css">
body {
padding: 0;
margin: 0;
}
.large_button {
position: absolute;
width: 32%;
height: 23%;
text-align: center;
text-decoration: none;
font-size: 400%;
}
#On {
background-color: #ffe4c4;
color: #000000;
top: 1;
tect-shadow: 1px 1px 10px #5C4E17;
}
#On {
background-color: #ffe4e1;
color: #66cd00;
left: 34%;
top: 1;
text-shadow: 1px 1px 10px #5C4E17;
}
#Off {
background-color: #ffe4e1;
color: #66cd00;
left: 68%;
top: 1;
text-shadow: 1px 1px 10px #5C4E17;
}
</style>
</head>
<body>
<h1>
ON
</h1>
<h1>
OFF
</h1>
</body>
If i understand your question correctly, Something like this might help.
Calling a javascript function on click.
<script>
var hidden = false;
function action() {
hidden = !hidden;
if(hidden) {
document.getElementById('ON').style.visibility = 'hidden';
} else {
document.getElementById('OFF').style.visibility = 'visible';
}
}
</script>
You can add Jquery based on id and class like below
<body>
<h1>
ON
</h1>
<h1>
OFF
</h1>
</body>
$(document).ready(function ()
{
$('#On').hide();
$('#Off').click(function () {
if ($('#Off').hasClass('off_class'))
$('#off').removeClass("off_class").addClass("large_button");
});
});
I am trying to build a mouse-over-menu that appears when hovering over an element. This works great, however, for the bottom-rows the hover disappears in the scroll-bars.
HTML
<div style="width:1024px; height:50px; overflow:scroll; border: 1px solid red;">
<div class="dropdown">
<span style="margin-left:5px" class="checkboxlink ignore"></span>
<ul>
<li><span class="checkboxlink todo"></span>Te doen</li>
<li><span class="checkboxlink done"></span>Behandeld</li>
<li><span class="checkboxlink ignore"></span>Negeren</li>
<li><span class="checkboxlink park"></span>Parkeren</li>
</ul>
</div>
.... more divs
CSS
.dropdown{
position: relative;
display: inline-block;
font-size: 16px;
width: 40px;
border: 0px solid white;
vertical-align: top;
}
.dropdown:hover
{
border: 0px solid #ccc;
}
ul{
position: absolute;
list-style: none;
text-align: left;
z-index: 1;
margin:0;
padding:0;
display: none;
background-color: white;
border: 1px solid #ccc;
}
.dropdown:hover ul {
display: block;
}
See also here:
https://jsfiddle.net/w030L59t/
I tried positioning absolute, but the element still stays in the scrollable area.
The problem is any position: relative attribute for the dropdown parents. If you remove them, you can easily add position: absolute to your dropdown, to display it above the scrollable box:
JSFIDDLE DEMO
The problem removing position: relative is that the position of each dropdown is calculated once on page load. While the dropdowns work great without scrolling, you will notice in the demo, that each dropdown does not refresh its position.
This could be solved using a few lines of javascript, calculating the .offset.top of each parent after scrolling and updating the dropdowns position using top: <offset.top of its parent>. I have added the classes .list_item and ul.dropdown_list, although the ID #wrapper.
$(document).ready(function() {
// fire function everytime the wrapper is scrolled
$('#wrapper').scroll(function(){
// set element to relate to
var list_items = $('div.list_item');
// get each position
list_items.each(function() {
// store offset().top inside var
var list_item_position = $(this).offset().top;
// select previous dropdown_list item
$(this).prev().find('ul.dropdown_list').css({
// apply offset top
top: list_item_position + "px"
});
});
// write to console to track changes
console.log('positions updated');
}); // .scroll
}); // document.ready
JSFIDDLE DEMO WITH jQUERY
This is a really strange problem which only affects Google Chrome.
If I have 299 rows in a drop down list, it keeps my custom CSS. However, the second I reach 300 rows all my styling is removed and seems to be set to a default by Google Chrome.
In the JSFiddle page, it has 300 rows, if you view the result, it will have default styling. But if you remove one row, my custom styling will be applied. Why is this?
JSFiddle: https://jsfiddle.net/s7opd7dm/
Simple drop down element:
#Html.DropDownListFor(m => m.SupplierID, new SelectList(Model.Suppliers, "SupplierID", "DisplayName"), "Select Supplier Name", new { #id = "SuppNameDD", #class = "GRDropDown", disabled = true })
I had the same problem. I found out that they disabled it at 300 options or more.
We intentionally disabled styling for 300+ options because of a
performance issue (crbug.com/500401).
Read about it here
Chrome Intentionally did disabled styling for 300+ options, so we can't reach the answer that way.
In short i would like to say that you should use any custom drop down.
As you are requesting for a solution to achieve, here's the fix
In that case i would prefer you to create a customized drop-down using other html elements like divs and list and take the selected list value. Here i am going to show a demonstration of how to create a customized div. The code has been tested in ASP.NET MVC5 C# and works fine. Post this demonstration here to promote this idea, as this might help anyone like you searching for what to do on cases like this.
in your some_view.cshtml add the following to include jquery and styles
<script src="#Url.Content("~/Scripts/jquery-1.10.2.min.js")"></script>
<!--<script src="#Url.Content("~/Scripts/myjquery.js")"></script> in case want this jquery to be external-->
<script>
function my_dd(el) {
this.dd = el;
this.initEvents();
}
my_dd.prototype = {
initEvents : function() {
var obj = this;
obj.dd.on('click', function(event){
$(this).toggleClass('active');
event.stopPropagation();
});
}
}
$(function() {
var dd = new my_dd( $('#dd') );
$(document).click(function() {
$('.wrapping').removeClass('active');
});
});
/** on select take the value to hidden text field**/
$(document).ready(function()
{
$('ul.my_dd li').click(function(e)
{
var selected=$(this).text();
/**change label to selected**/
$('.label').text(selected);
$('#selected-value').val(selected);
});
});
</script>
<!--<link href="#Url.Content("~/Content/my.css")" rel="stylesheet" type="text/css" />
in case want the css to be external-->
</script>
<style>
*,*:after,*:before {
box-sizing: border-box;
}
.wrapping {
position: relative;
width: 200px;
margin: 0 auto;
padding: 10px 15px;
cursor: pointer;
outline: none;
}
.wrapping:after {
width: 0;
height: 0;
position: absolute;
right: 16px;
top: 50%;
margin-top: -3px;
border-width: 1px solid red;
border-style: solid;
border-color: #366;
}
.wrapping .my_dd {
position: absolute;
top: 60%;
left: -45px;
right: 0px;
background: white;
transition: all 0.1s ease-out;
list-style: none;
opacity: 0;
pointer-events: none;
}
.wrapping .my_dd li a {
display: block;
text-decoration: none;
border: 1px solid;
padding: 10px;
transition: all 0.1s ease-out;
}
.wrapping .my_dd li i {
margin-right: 5px;
color: inherit;
vertical-align: middle;
}
.wrapping .my_dd li:hover a {
color: grey;
background-color: darkgrey;
max-height:300px;
}
.wrapping.active:after {
border-width: 0 6px 6px 6px;
}
.wrapping.active .my_dd {
opacity: 1;
pointer-events: auto;
height:300px;
overflow-y:scroll;
}
</style>
</style>
<div id="dd" class="wrapping">Test Drop Down
<ul class="my_dd">
<!-- use list or a foreach or for loop to push content to list
example
#foreach(var productId in Model.FailedProductIdsList)
{
<li>#Convert.ToString(productId);</li>
}-->
<li><i></i>Select 0</li>
...............
<li><i></i>Select 300+</li>
</ul>
</div>
<!-- #Html.TextBoxFor(c => c.Propertyname, new { #Value = "selected" })-->