I know this question sounds odd. Perhaps a button is not the element I'm looking for. What I want to to do is have an element that looks like what I have here:
Now this is technically a button. However, I'd like a small x to pop up in the top right corner when I hover this element so that I can delete the element itself. I have a feel a button is not the way to go here, but I do need an element with an onClick event.
Any pointers would be much appreciated
You can set an onClick event on any HTML elements. You would probably want to add a separate element with the 'x' and listen for a click on there.
We can certainly have a button element, add a span element inside (to show x), and only show that span on hover with some javascript, and styling it with css:
var btn = document.querySelector('.btn');
var close = document.querySelector('.close');
btn.addEventListener('mouseover', () => {
close.style.display = 'block';
});
btn.addEventListener('mouseout', () => {
close.style.display = 'none';
});
function closeIt(e) {
btn.style.display = 'none';
}
body {
background-color: #0f111d;
}
.btn {
background-color: #50c4e5;
padding: 10px;
width: 400px;
font-size: 15px;
text-align: center;
display: block;
border-radius: 5px;
border: 0;
position: relative;
}
.close {
cursor: pointer;
display: none;
position: absolute;
top: 20%;
right: 1%;
transform: translate(0%, -50%);
}
<button class="btn" onclick="alert('button clicked')"><span onclick="event.stopPropagation();closeIt()" class="close">×</span>https://www.pdga.com/frontpage/feed</button>
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 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>
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
I currently set the title attribute of some HTML if I want to provide more information:
<p>An <span class="more_info" title="also called an underscore">underline</span> character is used here</p>
Then in CSS:
.more_info {
border-bottom: 1px dotted;
}
Works very nice, visual indicator to move the mouse over and then a little popup with more information. But on mobile browsers, I don't get that tooltip. title attributes don't seem to have an effect. What's the proper way to give more information on a piece of text in a mobile browser? Same as above but use Javascript to listen for a click and then display a tooltip-looking dialog? Is there any native mechanism?
You can fake the title tooltip behavior with Javascript. When you click/tab on an element with a title attribute, a child element with the title text will be appended. Click again and it gets removed.
Javascript (done with jQuery):
$("span[title]").click(function () {
var $title = $(this).find(".title");
if (!$title.length) {
$(this).append('<span class="title">' + $(this).attr("title") + '</span>');
} else {
$title.remove();
}
});
CSS:
.more_info {
border-bottom: 1px dotted;
position: relative;
}
.more_info .title {
position: absolute;
top: 20px;
background: silver;
padding: 4px;
left: 0;
white-space: nowrap;
}
Demo: http://jsfiddle.net/xaAN3/
Here is a CSS only solution. (Similar to #Jamie Pate 's answer, but without the JavaScript.)
We can use the pseudo class :hover, but I'm not sure all mobile browsers apply these styles when the element is tapped. I'm using pseudo class :focus because I'm guessing it's safer. However, when using pseudo class :focus we need to add tabindex="0" to elements that don't have a focus state intrinsically.
I'm using 2 #media queries to ensure all mobile devices are targeted. The (pointer: coarse) query will target any device that the primary input method is something "coarse", like a finger. And the (hover: none) query will target any device that the primary pointing system can't hover.
This snippet is all that's needed:
#media (pointer: coarse), (hover: none) {
[title] {
position: relative;
display: inline-flex;
justify-content: center;
}
[title]:focus::after {
content: attr(title);
position: absolute;
top: 90%;
color: #000;
background-color: #fff;
border: 1px solid;
width: fit-content;
padding: 3px;
}
}
/*Semantic Styling*/
body {
display: grid;
place-items: center;
text-align: center;
height: 100vh;
}
a {
height: 40px;
width: 200px;
background: #fa4766;
color: #fff;
text-decoration: none;
padding: 10px;
box-sizing: border-box;
border-radius: 10px;
}
/*Functional Styling*/
#media (pointer: coarse), (hover: none) {
[title] {
position: relative;
display: flex;
justify-content: center;
}
[title]:focus::after {
content: attr(title);
position: absolute;
top: 90%;
color: #000;
background-color: #fff;
border: 1px solid;
width: fit-content;
padding: 3px;
}
}
<a title="this is the Title text" tabindex="0">Tag with Title</a>
Obviously, you'll need to open this on a mobile device to test it.
Here is a Pen with the same code.
Given that a lot of people nowadays (2015) use mobile browsers, and title still hasn't found a form of exposure in mobile browsers, maybe it's time to deprecate reliance upon title for meaningful information.
It should never be used for critical information, but it is now becoming dubious for useful information, because if that information is useful and cannot be shown to half the users, then another way of showing it to almost all users needs to be found.
For static pages, perhaps some visible text near to the relevant control, even as fine print. For server-generated pages, browser sniffing could provide that only for mobile browsers. On the client side, javascript could be used to trap the focus event, via bubbling, to show the extra text next to the currently focussed element. That would minimise the screen space taken up, but would not necessarily be of much use, since, in a lot of instances, bringing focus to a control can only be done in a way that immediately activates its action, bypassing the ability to find out about it before using it!
Over all though, it appears that the difficulties of showing the title attribute on mobile devices, may lead to its demise, mostly due to needing an alternative that is more universal. That is a pity, because mobiles could use a way to show such extra info on-demand, without taking up the limited screen space.
It seems strange that the w3c and mobile browser makers did not do anything about this issue a long time ago. At least they could have displayed the title text on top of the menu that appears when a long press on a control is made.
Personally, I wish it was placed at the top of a right-click/long-touch menu, as it won't timeout, and would be available on all browsers.
The other alternative is to construct footnotes, so an [n] type superscript is put next to the element/text needing more info, linking to explanatory text in a list at the bottom of the page. Each of those can have a similar [n] type link back to the original text/element. That way, it keeps the display uncluttered, but provides easy bidirectional swapping in a simple way. Sometimes, old print media ways, with a little hyperlink help, are best.
The title attribute has been hijacked by some browsers to provide help text for the pattern attribute, in that its text pops up if the pattern doesn't match the text in the input element. Typically, it is to provide examples of the right format.
Slightly more elaborated version of flavaflo's answer:
Uses pre-defined div as pop-up that can hold HTML, rather than reading from a title attribute
Opens/closes on rollover if mouse is used
Opens on click (touch screen) and closes on click on the open pop-up or anywhere else on the document.
HTML:
<span class="more_info">Main Text<div class="popup">Pop-up text can use <b>HTML</b><div></span>
CSS:
.more_info {
border-bottom: 1px dotted #000;
position: relative;
cursor: pointer;
}
.more_info .popup {
position: absolute;
top: 15px; /*must overlap parent element otherwise pop-up doesn't stay open when rolloing over '*/
background: #fff;
border: 1px solid #ccc;
padding: 8px;
left: 0;
max-width: 240px;
min-width: 180px;
z-index: 100;
display: none;
}
JavaScript / jQuery:
$(document).ready(function () {
//init pop-ups
$(".popup").attr("data-close", false);
//click on pop-up opener
//pop-up is expected to be a child of opener
$(".more_info").click(function () {
var $title = $(this).find(".popup");
//open if not marked for closing
if ($title.attr("data-close") === "false") {
$title.show();
}
//reset popup
$title.attr("data-close", false);
});
//mark pop-up for closing if clicked on
//close is initiated by document.mouseup,
//marker will stop opener from re-opening it
$(".popup").click(function () {
$(this).attr("data-close",true);
});
//hide all pop-ups
$(document).mouseup(function () {
$(".popup").hide();
});
//show on rollover if mouse is used
$(".more_info").mouseenter(function () {
var $title = $(this).find(".popup");
$title.show();
});
//hide on roll-out
$(".more_info").mouseleave(function () {
var $title = $(this).find(".popup");
$title.hide();
});
});
Demo here https://jsfiddle.net/bgxC/yvs1awzk/
As #cimmanon mentioned: span[title]:hover:after { content: attr(title) } gives you a rudimentary tooltip on touch screen devices. Unfortunately this has problems where the default ui behavior on touch screen devices is to select the text when any non-link/uicontrol is pressed.
To solve the selection problem you can add span[title] > * { user-select: none} span[title]:hover > * { user-select: auto }
A full solution may use some other techniques:
Add position: absolute background, border, box-shadow etc to make it look like a tooltip.
Add the class touched to body (via js) when the user uses any touch event.
Then you can do body.touched [title]:hover ... without affecting desktop users
document.body.addEventListener('touchstart', function() {
document.body.classList.add('touched');
});
[title] {
border-bottom: 1px dashed rgba(0, 0, 0, 0.2);
border-radius:2px;
position: relative;
}
body.touched [title] > * {
user-select: none;
}
body.touched [title]:hover > * {
user-select: auto
}
body.touched [title]:hover:after {
position: absolute;
top: 100%;
right: -10%;
content: attr(title);
border: 1px solid rgba(0, 0, 0, 0.2);
background-color: white;
box-shadow: 1px 1px 3px;
padding: 0.3em;
z-index: 1;
}
<div>Some text where a portion has a <span title="here's your tooltip">tooltip</span></div>
Depending on how much information you want to give the user, a modal dialogue box might be an elegant solution.
Specifically, you could try the qTip jQuery plugin, which has a modal mode fired on $.click():
The title attribute is not supported in any mobile browsers **in a way that it would show the tooltip the same as to desktop mouse users** *(the attribute itself is ofcourse supported in the markup)*.
It's only basically for desktop users with a mouse, keyboard only users can't use it either, or screenreaders.
You can achieve almost similar with javascript as you said.
I was searching for an easy CSS only solution, and this is really the most easy one I found:
<link rel="stylesheet" href="https://unpkg.com/balloon-css/balloon.min.css">
<span aria-label="Whats up!" data-balloon-pos="up">Hover me!</span>
Working example: https://jsfiddle.net/5pcjbnwg/
If you want to customize the tooltip, you find more info here:
https://kazzkiq.github.io/balloon.css/
To avoid using JavaScript, I used this CSS-only tooltip:
http://www.menucool.com/tooltip/css-tooltip
It works great in Mobile and Desktop, and you can customize the styles.
Thanks to #flavaflo for their answer. This works in most cases but if there is more than one title to lookup in the same paragraph, and one opens over the link to another, the unopened link shows through the first. This can be solved by dynamically changing the z-index of the title that has "popped up":
$("span[title]").click(function () {
var $title = $(this).find(".title");
if (!$title.length) {
$(this).append('<span class="title">' + $(this).attr("title") + '</span>');
$(this).css('z-index', 2);
} else {
$title.remove();
$(this).css('z-index', 0);
}
});
Also, you can make both the hover over display and the click display multiline by adding
(linefeed) to the title='' attribute, and then convert that to <br /> for the html click display:
$(this).append('<span class="title">' + $(this).attr("title").replace(/\\n/g, '<br />') + '</span>');
Extremely late to the party but for future visitors, here is a tweak of #Flavaflo's answer to fade the "tooltip" in and out
JQuery:
$(".more_info").click(function () {
var $title = $(this).find(".title");
if (!$title.length) {
$(this).append('<span class="title">' + $(this).attr("title") + '</span>');
} else {
$($title).fadeOut(250, function() {
$title.remove();
});
}
});
CSS:
.more_info {
border-bottom: 1px dotted;
position: relative;
}
.more_info .title {
position: absolute;
top: 20px;
background: green;
padding: 4px;
left: 0;
color: white;
white-space: nowrap;
border-radius:3px;
animation: fadeIn linear 0.15s;
}
#keyframes fadeIn {
0% {opacity:0;}
100% {opacity:1;}
}
Fiddle here: http://jsfiddle.net/L3paxb5g/
I know this is an old question, but i have found a CSS solution that works on mobile too, it doesn't use title at all and it's easy to implement, explained here:
https://www.w3schools.com/css/css_tooltip.asp
Explanation:
On mobile, with the touchscreen,the first input acts as css hover, so it works like a toggle tooltip when you press on it.
Code example:
.tooltip {
position: relative;
display: inline-block;
border-bottom: 2px dotted #666;
}
.tooltip .tooltiptext {
visibility: hidden;
width: 15em;
background-color: #555;
color: #fff;
text-align: center;
border-radius: 6px;
position: absolute;
z-index: 1;
bottom: 125%;
left: 50%;
margin-left: -8em;
opacity: 0;
transition: opacity 0.3s;
padding: 0.5em;
}
.tooltip .tooltiptext::after {
content: "";
position: absolute;
top: 100%;
left: 50%;
margin-left: -5px;
border-width: 5px;
border-style: solid;
border-color: #555 transparent transparent transparent;
}
.tooltip:hover .tooltiptext {
visibility: visible;
opacity: 1;
}
<div class="tooltip">Hover over me
<span class="tooltiptext">Tooltip text</span>
</div>