How to make links, buttons, and divs hover on mobile? - html

I am having trouble making elements hover on a mobile device.
In my CSS, I type something like:
.button:hover {
background-color: #fff;
}
This seems to hover fine on my desktop, however on my iPhone and other touch devices, I can't seem to make the button hover.

There is no hover event on mobile, you can define hover behavior and it will work on desktop. But on mobile, you will see this hover only by click/touch.

Hovers mean one thing on the other. in this case its the mouse cursor over the HTML button or whatever element you use.
In the case of a phone, there is no mouse cursor. its always a click. Hovers in most cases would show only on click or touch. If you really need this you can try the Javascrit onclick() or other functions, so when they click or touch, you can add a bit of something.

For a very quick solution of this problem with jQuery/CSS, I did the following.
wrote styles for my element like this:
.one-block:hover, .one-block.hover { ... }
positioned it:
.one-block { position: relative; }
added the last element in this block -> .mobile-mask:
<div class="one-block">
....
<div class="mobile-mask"></div>
</div>
positioned .mobile-mask:
.mobile-mask {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
hide it for non-mobile (this part is not precise at all: just with css. if you detect mobile devices by some other means and, for example, give a class to body, than it will be more precise. in this case I just need a quick solution):
#media (min-width: 681px) {
.mobile-mask {
display: none;
}
}
create javascript that will add/remove .hover class:
$('.mobile-mask').on('click', function(){
$('.list .mobile-mask').show();
$('.list .one-block').removeClass('hover');
$(this).hide();
$(this).parent().addClass('hover');
});
$(window).on('resize', function(event){
var windowWidth = $(this).width();
if(windowWidth > 680){
$('.list .one-block').removeClass('hover');
}
});

Related

Hover event converts to click on mobile except iPhone / Safari?

I'm a bit confused about this but I think I've found the issue.
I have in my html:
<div class="dropdownz">
<button>HOVER_OR_CLICK</button>
<div class="dropdownz-content">
</div>
</div>
In my css I have:
.dropdownz {
float: left;
overflow: hidden;
}
.dropdownz-content {
display: none;
position: absolute;
z-index: 1;
}
.dropdownz:hover .dropdownz-content {
display: block;
position: fixed;
top: 50px;
}
So this basically means if I hover over the dropdownz class, the dropdownz-content display converts from none to block and the menu items show.
When I run this on an android touchscreen mobile device, I have to CLICK the dropdownz item in order for it to effect the hover and show the list, if I click it again, it effectively removes the hover.
This is desirable behaviour, it means I don't have to do any extra stuff for touch-screens. A "hover" becomes a click and the 2nd click removes the "hover". Great!
Apparently this doesn't work the same in SAFARI on an iPhone. I can't test it myself, I'm going via a friend who says it's not working, so I basically want to know:
Is this a known issue and what's the best way to remedy it? (Without JavaScript, surely!)
I'm thinking along the lines of :focus ?
try this :
.dropdownz:hover .dropdownz-content,
.dropdownz:active .dropdownz-content,
.dropdownz:focus .dropdownz-content{
display: block;
position: fixed;
top: 50px;
}

Apply css property hover, ontouch in mobile devices

Below is the link of codePen, you can see if its window size then image get border on hover,
In mobile devices it get border on touch. but it doesn't go away if user is not touching it (after touching it). user needs to touch outside the image then its border goes away.
In the below image, user touch the image and its showing border, later user is not touching it and its still showing border.
.swap {
background-image: url('https://farm9.staticflickr.com/8382/8558295631_0f56c1284f_b.jpg');
width: 200px;
}
.swap a {
display: block;
}
.swap a img {
width: 200px;
height: auto;
}
.swap a:hover img {
border:10px black solid;
}
.swap a:focus img {
border:none !important;
}
<div class="swap">
<a>
<img src="https://vignette.wikia.nocookie.net/undertale-au/images/5/54/Link.jpg/revision/latest?cb=20170903211129">
</a>
</div>
Adding the :focus pseudo class will work for you to override what is happening.
.swap a:hover img {
border:10px black solid;
}
.swap a:focus img {
border:none !important;
}
If you are working on a responsive project that you do not want :focus to show on non-touch devices you can try to target devices by size, or more reliably, you could use Modernizr to feature detect.
So I solved this question by JavaScript events,ontouchstart and ontouchend please check out the below plunkr link
https://plnkr.co/edit/bVFQMUjJXo5SvLGroQH3?p=preview
function myFunction()
{
document.getElementById('swap').setAttribute("class", "style1");
}
function myFunctions()
{
document.getElementById('swap').setAttribute("class", "style2");
}
<div id="swap">
<a><img src="https://vignette.wikia.nocookie.net/undertale-au/images/5/54/Link.jpg/revision/latest?cb=20170903211129" ontouchstart="myFunction()" ontouchend="myFunctions()" >
</a>
</div>
Prepared for another query, just replace P with your element.
It now seems best to avoid using hover altogether with ios or touch in general. The below code applies your css as long as touch is maintained, and without other ios flyouts. Do this;
Jquery add: $("p").on("touchstart", function(e) { $(this).focus(); e.preventDefault(); });
CSS: replace p:hover with p:focus, and add p:active
Options;
replace jquery p selector with any class etc
to have the effect remain, keep p:hover as well, and add body{cursor:ponter;} so a tap anywhere ends it
try click & mouseover events as well as touchstart in same code (but not tested)
remove e.preventDefault(); to enable users to utilise ios flyouts eg copy
Notes
only tested for text elements, ios may treat inputs etc differently
only tested on iphone XR ios 12.1.12, and ipad 3 ios 9.3.5, using Safari or Chrome.

HTML - Removing an element's "presence" on the page but keeping its visibility?

I have an element that overlays another element. The main element is a canvas where elements constantly have mouse interactions and the element directly overtop of it just shows elements that act as little markers. Same position, same size and it's important the overlay is overtop of the canvas.
What would it mean to make this "overlay" only exist visibility wise? As in having no possible user input because for its purposes it's not really there to be interacted with, just showing something.
Removing selection in CSS stops you from clicking on it but it's still overtop of the other element and doesn't allow mouse events. Hiding the element removes its presence but also makes it invisible.
In a normal desktop application you would just draw something to the screen and add functionality if you wanted but with HTML those two things are inherently the same.
I believe adding in the CSS the following code solves your issue:
.no-interaction {
z-index : -5
}
OR
.interaction {
z-index : 5
}
Turns out all it took was setting the pointer-events CSS attribute to none on whatever you want to have no presence.
I figured it would be a little more interesting than that, but there's a built in way in CSS.
<div id="canvas"></div>
<div id="overlay"></div>
#canvas, #overlay {
width: 500px;
height: 500px;
position: absolute;
}
#canvas {
background: blue;
}
#overlay {
background: red;
pointer-events: none; // right here
}
$('#canvas').click(function() {
alert('Clicked');
});
https://jsfiddle.net/ufsy33aw/

Change position of a box only on mobile?

I was wondering if it is possible to change the position of the search box but only on mobiles.. I tried to put id="search" on the box that contains the input with:
#media only screen and (max-width: 767px) {
#search
{
position:absolute;
top: 0;
width:90%;
background: none repeat scroll 0 0 #ffffff;
}
}
But doesn't seem to work. I want the search box just at the bottom of the header, but only on mobiles. Is this possible?
At work we use JavaScript & jQuery to move an element on different screen sizes like so:
function moveMenu(){
if($(window).width() < 767){
// If the screen is less than 767, move the menu to mobile position
$('#menu-header').prependTo('#mobile-menu-wrapper');
}
else {
// Otherwise, put it in the normal location
$('#menu-header').prependTo('#header-menu-wrapper');
}
}
Its important that if someone loads the page on a small screen, then resizes it to large that this function runs. So we also add these two bits to trigger it on page load and on page resize:
$(window).resize(function(){
moveMenu();
});
$(window).load(function(){
moveMenu();
});
This method means you don't have to duplicate menus to 'reflow' the page.
Add another search box in the Center-block
Hide this on desktop and show it on the
UPDATE: Position fixed will work but will not allow to use other elements
the code is something like this
#search1 {
display: block;
}
#search2 {
display: none;
}
#media only [....] {
#search1 {
display: none;
}
#search2 {
display: block;
}
}

How to prevent background scrolling when Bootstrap 3 modal open on mobile browsers?

How to prevent background scrolling when Bootstrap 3 modal open on mobile platforms? On desktop browsers the background is prevented from scrolling and works as it should.
On mobile browsers (Safari ios, Chrome ios, etc), when a modal is opened and using your finger to scroll it, the background also scrolls as does the modal. How do I prevent that?
See here: https://github.com/twbs/bootstrap/issues/7501
So try:
$('body').css('overflow','hidden');
$('body').css('position','fixed');
V3.0.0. should have fixed this issue. Do you use the latest version? If so post an issue on https://github.com/twbs/bootstrap/
Try this,
body.modal-open {
overflow: hidden;
position:fixed;
width: 100%;
}
I tried the accepted answer which prevented the body from scrolling but had the issue of scrolling to the top. This should solve both issues.
As a side note, it appears overflow:hidden doesn't work on body for iOS Safari only as iOS Chrome works fine.
var scrollPos = 0;
$('.modal')
.on('show.bs.modal', function (){
scrollPos = $('body').scrollTop();
$('body').css({
overflow: 'hidden',
position: 'fixed',
top : -scrollPos
});
})
.on('hide.bs.modal', function (){
$('body').css({
overflow: '',
position: '',
top: ''
}).scrollTop(scrollPos);
});
$('.modal')
.on('shown', function(){
console.log('show');
$('body').css({overflow: 'hidden'});
})
.on('hidden', function(){
$('body').css({overflow: ''});
});
use this one
No scripts needed.
BS 3 sets a .modal-open class on body that you can use to set the position and overflow values (made with LESS).
body {
font-family:'Open Sans';
margin:0;
&.modal-open {
position:fixed;
overflow:hidden;
.modal {
overflow: scroll;
#media only screen and (min-resolution:150dpi) and (max-width: #screen-sm),
only screen and (-webkit-min-device-pixel-ratio:1.5) {
overflow: scroll;
-webkit-overflow-scrolling: touch;
}
}
}
}
The chosen solution works, however they also snap the background to the top scrolling position. I extended the code above to fix that 'jump'.
//Set 2 global variables
var scrollTopPosition = 0;
var lastKnownScrollTopPosition = 0;
//when the document loads
$(document).ready(function(){
//this only runs on the right platform -- this step is not necessary, it should work on all platforms
if( navigator.userAgent.match(/iPhone|iPad|iPod/i) ) {
//There is some css below that applies here
$('body').addClass('platform-ios');
//As you scroll, record the scrolltop position in global variable
$(window).scroll(function () {
scrollTopPosition = $(document).scrollTop();
});
//when the modal displays, set the top of the (now fixed position) body to force it to the stay in the same place
$('.modal').on('show.bs.modal', function () {
//scroll position is position, but top is negative
$('body').css('top', (scrollTopPosition * -1));
//save this number for later
lastKnownScrollTopPosition = scrollTopPosition;
});
//on modal hide
$('.modal').on('hidden.bs.modal', function () {
//force scroll the body back down to the right spot (you cannot just use scrollTopPosition, because it gets set to zero when the position of the body is changed by bootstrap
$('body').scrollTop(lastKnownScrollTopPosition);
});
}
});
The css is pretty simple:
// You probably already have this, but just in case you don't
body.modal-open {
overflow: hidden;
width: 100%;
height: 100%;
}
//only on this platform does it need to be fixed as well
body.platform-ios.modal-open {
position: fixed;
}
If you use jQuery you can do this with scrollTop
Save the body's vertical scroll position;
Disable scroll on the body;
Show modal;
Close modal;
Reenable scroll on body;
Set saved scroll position.
#modal {
bottom: 0;
position: fixed;
overflow-y: scroll;
overflow-x: hidden;
top: 0;
width: 100%;
}
$('.open-modal').click(function (e) {
e.preventDefault();
$('#modal').toggle();
scrollTo = $('body').scrollTop();
$('body').css("position", "fixed");
});
$('.close-modal').click(function (e) {
e.preventDefault();
$('#modal').toggle();
$('body').css("position", "static");
$('body').animate({scrollTop: scrollTo}, 0);
});
The above answers did not help so what I did was:
.modal {
-webkit-overflow-scrolling: touch;
}
My particular problem was when I increased the modal size after loading.
It's a known iOS issue, see here. Since it does not break anything else the above solution was enough for my needs.
Had an issue with this as well, iPhone + Safari where needed to add:
position: fixed;
As mentioned elsewhere, this created a scroll-to-top issue. Fix that worked for me was to capture the position to top upon modal open, and then animate to that position on modal close
upon modal open:
scrollTo = $('body').scrollTop();
$('body').css("position", "fixed");
upon modal close
$('body').css("position", "static");
$('body').animate({scrollTop: scrollTo}, 0);
Hey guys so i think i found a fix. This is working for me on iphone and android at the moment. Its a mash up of hours upon hours of searching, reading and testing. So if you see parts of your code in here credit goes to you lol.
#media only screen and (max-device-width:768px){
body.modal-open {
// block scroll for mobile;
// causes underlying page to jump to top;
// prevents scrolling on all screens
overflow: hidden;
position: fixed;
}
}
body.viewport-lg {
// block scroll for desktop;
// will not jump to top;
// will not prevent scroll on mobile
position: absolute;
}
body {
overflow-x: hidden;
overflow-y: scroll !important;
}
The reason the media specific is on there is on a desktop i was having issues with when the modal would open all content on the page would shift from centered to left. Looked like crap. So this targets up to tablet size devices where you would need to scroll. There is still a slight shift on mobile and tablet but its really not much. Let me know if this works for you guys. Hopefully this puts the nail in the coffin
I thought you might forget to add attribute data-toggle="modal" to the link or button that triggers the modal popup event. Firstly, I also got the same problem but, after adding the attribute above it works well for me.
This might be a bit like beating a dead horse here.. but, my currently implemented solution on DIY modals via vanilla JS:
On modal show:
if (document.body.style.position !== 'fixed') {
document.body.style.top = -window.scrollY + 'px';
document.body.style.position = 'fixed';
}
On modal hide:
document.body.style.position = '';
window.scrollTo(0, -parseInt(document.body.style.top, 10));
document.body.style.top = '';
As additional to #Karthick Kumar answer from bootstrap docs
show is triggered at the start of an event
shown is triggered on the completion of an action
... so it should be:
$('.modal')
.on('show.bs.modal', function (){
$('body').css('overflow', 'hidden');
})
.on('hide.bs.modal', function (){
// Also if you are using multiple modals (cascade) - additional check
if ($('.modal.in').length == 1) {
$('body').css('overflow', 'auto');
}
});
I've found a simple javascript/jquery solution which utilizes the bootstrap modal events.
My solution also fixes the position:fixed problem where it scrolls the background page all the way back to the top instead of staying in place when modal window is opened/closed.
See details here
I know this has been answered but none of these solutions worked for me. I needed to take a different approach. I am using PhoneGap and am compiling my code natively so I had to move the background to the body. I hope this helps someone else. Or if there a cleaner way to do this please feel free to comment...
$(document).on('shown.bs.modal', '.modal', function (e) {
$("#" + e.target.id).find(".modal-backdrop").css("z-index", $("#" + e.target.id).css("z-index")).insertBefore("#" + e.target.id);
});
Using position:fixed has the side effect of scrolling the body to the top.
If you do not your body to scroll to the top, DO NOTE use position:fixed. Just disable touchmove on the body if the modal is open.
Note: The modal itself is still able to scroll on touch (if larger than the screen).
CSS:
body.modal-open {
overflow: hidden;
width: 100%;
/* NO position:fixed here*/
}
JS:
$('.modal').on('show.bs.modal', function (ev) { // prevent body from scrolling when modal opens
$('body').bind('touchmove', function(e){
if (!$(e.target).parents().hasClass( '.modal' )){ //only prevent touch move if it is not the modal
e.preventDefault()
}
})
})
$('.modal').on('hide.bs.modal', function (e) { //unbind the touchmove restrictions from body when modal closes
$('body').unbind('touchmove');
})
EDIT:
Note, for very small modals, you might have to add the following line to your CSS:
.modal-dialog{
height: 100%;
}
Courtesy of JDiApice who synthesized and extended the work of other contributors at iOS 8.x modal scroll issue #14839:
#media only screen and (max-device-width:768px) {
body.modal-open {
// block scroll for mobile;
// causes underlying page to jump to top;
// prevents scrolling on all screens
overflow: hidden;
position: fixed;
}
}
body.viewport-lg {
// block scroll for desktop;
// will not jump to top;
// will not prevent scroll on mobile
position: absolute;
}
body {
overflow-x: hidden;
overflow-y: scroll !important;
}
/* The reason the media specific is on there is
on a desktop i was having issues with when the modal would open
all content on the page would shift from centered to left.
Looked like crap. So this targets up to tablet size devices
where you would need to scroll. There is still a slight shift
on mobile and tablet but its really not much. */
Unlike the other solutions we tried, it does not scroll the background to the top after the popup modal closes.
I open a modal after a modal and fact the error on modal scrolling, and this css solved my problem:
.modal {
overflow-y: auto;
padding-right: 15px;
}
My solution...
Ver en jsfiddle
//Fix modal mobile Boostrap 3
function Show(id){
//Fix CSS
$(".modal-footer").css({"padding":"19px 20px 20px","margin-top":"15px","text-align":"right","border-top":"1px solid #e5e5e5"});
$(".modal-body").css("overflow-y","auto");
//Fix .modal-body height
$('#'+id).on('shown.bs.modal',function(){
$("#"+id+">.modal-dialog>.modal-content>.modal-body").css("height","auto");
h1=$("#"+id+">.modal-dialog").height();
h2=$(window).height();
h3=$("#"+id+">.modal-dialog>.modal-content>.modal-body").height();
h4=h2-(h1-h3);
if($(window).width()>=768){
if(h1>h2){
$("#"+id+">.modal-dialog>.modal-content>.modal-body").height(h4);
}
$("#"+id+">.modal-dialog").css("margin","30px auto");
$("#"+id+">.modal-dialog>.modal-content").css("border","1px solid rgba(0,0,0,0.2)");
$("#"+id+">.modal-dialog>.modal-content").css("border-radius",6);
if($("#"+id+">.modal-dialog").height()+30>h2){
$("#"+id+">.modal-dialog").css("margin-top","0px");
$("#"+id+">.modal-dialog").css("margin-bottom","0px");
}
}
else{
//Fix full-screen in mobiles
$("#"+id+">.modal-dialog>.modal-content>.modal-body").height(h4);
$("#"+id+">.modal-dialog").css("margin",0);
$("#"+id+">.modal-dialog>.modal-content").css("border",0);
$("#"+id+">.modal-dialog>.modal-content").css("border-radius",0);
}
//Aply changes on screen resize (example: mobile orientation)
window.onresize=function(){
$("#"+id+">.modal-dialog>.modal-content>.modal-body").css("height","auto");
h1=$("#"+id+">.modal-dialog").height();
h2=$(window).height();
h3=$("#"+id+">.modal-dialog>.modal-content>.modal-body").height();
h4=h2-(h1-h3);
if($(window).width()>=768){
if(h1>h2){
$("#"+id+">.modal-dialog>.modal-content>.modal-body").height(h4);
}
$("#"+id+">.modal-dialog").css("margin","30px auto");
$("#"+id+">.modal-dialog>.modal-content").css("border","1px solid rgba(0,0,0,0.2)");
$("#"+id+">.modal-dialog>.modal-content").css("border-radius",6);
if($("#"+id+">.modal-dialog").height()+30>h2){
$("#"+id+">.modal-dialog").css("margin-top","0px");
$("#"+id+">.modal-dialog").css("margin-bottom","0px");
}
}
else{
//Fix full-screen in mobiles
$("#"+id+">.modal-dialog>.modal-content>.modal-body").height(h4);
$("#"+id+">.modal-dialog").css("margin",0);
$("#"+id+">.modal-dialog>.modal-content").css("border",0);
$("#"+id+">.modal-dialog>.modal-content").css("border-radius",0);
}
};
});
//Free event listener
$('#'+id).on('hide.bs.modal',function(){
window.onresize=function(){};
});
//Mobile haven't scrollbar, so this is touch event scrollbar implementation
var y1=0;
var y2=0;
var div=$("#"+id+">.modal-dialog>.modal-content>.modal-body")[0];
div.addEventListener("touchstart",function(event){
y1=event.touches[0].clientY;
});
div.addEventListener("touchmove",function(event){
event.preventDefault();
y2=event.touches[0].clientY;
var limite=div.scrollHeight-div.clientHeight;
var diff=div.scrollTop+y1-y2;
if(diff<0)diff=0;
if(diff>limite)diff=limite;
div.scrollTop=diff;
y1=y2;
});
//Fix position modal, scroll to top.
$('html, body').scrollTop(0);
//Show
$("#"+id).modal('show');
}