CSS hover on mobile - css

I've created a web application where a use can vote images. When the user hovers with the mouse over a "gridItem" I'll hide an overlay layer and display an other overlay layer with two buttons on it. To get it working on touch devices I also added the :focus pseudo classes.
This works perfectly fine in any desktop browser and it works sort of on touch. The problem I'm facing now is when I try to click on a button on the "hover" overlay, this overlay disappears before I get the click event.
Here's some html code and my css classes:
<div class="gridItem">
<img class="..." src="..." alt="">
<div class="likeLabelOverlay">
small content
</div>
<div class="likeButtonOverlay ghost-center">
<div>
<h3>large content</span>
<button type="button" id="..." class="btn btn-default">button 1</button>
<button type="button" id="..." class="btn btn-default">button 2</button>
</div>
</div>
</div>
I handle the hover on the gridItem:
.gridItem:hover .likeButtonOverlay, .gridItem:focus .likeButtonOverlay {
display: block;
}
.gridItem:hover .likeLabelOverlay, .gridItem:focus .likeLabelOverlay {
display: none;
}

Mobile devices support :active. With your :hover use :active. Here a demo.
.gridItem:hover .likeButtonOverlay, .gridItem:active .likeButtonOverlay {
display: block;
}
.gridItem:hover .likeLabelOverlay, .gridItem:active .likeLabelOverlay {
display: none;
}
<div class="gridItem">
<img class="..." src="..." alt="">
<div class="likeLabelOverlay">
small content
</div>
<div class="likeButtonOverlay ghost-center">
<div>
<h3>large content</span>
<button type="button" id="..." class="btn btn-default">button 1</button>
<button type="button" id="..." class="btn btn-default">button 2</button>
</div>
</div>
</div>

There is no hover on mobile. What you can do is bind some events with jquery on touch.
Like this:
$(document).ready(function() {
$('.gridItem').bind('touchstart touchend', function(e) {
e.preventDefault();
$(this).toggleClass('hover_effect');
});
});
CSS
.gridItem:hover, .gridItem.hover_effect {
rule:properties;
}

We just had to solve this issue for a client at the agency I work with.
I'll also describe the code here so just in case anything happens with the fiddle, it's here in perpetuity.
The Fiddle
https://jsfiddle.net/GrafikMatthew/7nx53twL/
The Libraries
I'm using the 2.2 jQuery library for this, though I'm pretty sure an earlier version could be used if needed.
<script src="https://code.jquery.com/jquery-2.2.0.min.js"></script>
The CSS
This is just a barebones presentation so these are the minimum styles required for this approach. You can modify these all you want to match your page design.
<style type="text/css">
.nav-wrapper ul
{
margin: 0;
padding: 0;
list-style-type: none;
}
.nav-wrapper > ul::after
{
content: "";
clear: both;
display: block;
float: none;
height: 0;
}
.nav-wrapper > ul > li
{
display: block;
float: left;
padding: 10px;
position: relative;
}
.subnav-wrapper
{
display: none;
background: #000;
position: absolute;
top: 100%;
left: 0;
}
.subnav-wrapper > ul > li {
padding: 10px;
}
.subnav-wrapper > ul > li > a
{
white-space: nowrap;
color: #fff;
}
.nav-wrapper > ul > li:hover
, .nav-wrapper > ul > li.hover
{
background: #000;
}
.nav-wrapper > ul > li:hover > a
, .nav-wrapper > ul > li.hover > a
{
color: #fff;
}
.nav-wrapper > ul > li:hover > .subnav-wrapper
, .nav-wrapper > ul > li.hover > .subnav-wrapper
{
display: block;
}
</style>
The HTML
I'm using a fairly straight forward markup for this menu structure, though since everything aside from the list and anchors, targeting is done via class name, so the elements can be swapped out for ones that work better for your project.
<div class="nav-wrapper">
<ul class="nav">
<li>Link A
<div class="subnav-wrapper">
<ul class="subnav">
<li>Sublink A A</li>
<li>Sublink A B</li>
<li>Sublink A C</li>
</ul>
</div>
</li>
<li>Link B</li>
<li>Link C
<div class="subnav-wrapper">
<ul class="subnav">
<li>Sublink C A</li>
<li>Sublink C B</li>
<li>Sublink C C</li>
</ul>
</div>
</li>
<li>Link D</li>
</ul>
</div>
<hr />
<div class="dummy">
<p>Dummy content...</p>
</div>
The JS
I'm using a standard anonymous enclosure and exposing jQuery via $.
<script type="text/javascript">
(function($){
function MH_ResetAll() {
$( '.nav-wrapper .hover' ).removeClass( 'hover' );
}
function MH_Init() {
// >
// > Environment
// >
$( document ).on( 'touchstart', function( e ) {
MH_ResetAll();
} );
// >
// > Primary Navigation
// >
$( '.nav-wrapper > ul > li > a' ).on( 'touchstart', function( e ) {
// Cancel default event behaviors...
e.preventDefault();
e.stopPropagation();
// Hook the important elements for this event...
var ThisA = $( this );
var ThisParentLI = $( ThisA.parents( 'li' ).get( 0 ) );
// Is there a subnav-wrapper in the parent list item?
if( ThisParentLI.find( '.subnav-wrapper').length ) {
// Is the parent list item already hovered?
if( ThisParentLI.hasClass( 'hover' ) ) {
// Handle the event as a link click...
window.location.href = ThisA.attr( 'href' );
} else {
// Reset all other hover states...
MH_ResetAll();
// Add the hover class to the parent list item...
ThisParentLI.addClass( 'hover' );
}
} else {
// Handle the event as a link click...
window.location.href = ThisA.attr( 'href' );
}
} );
// >
// > Secondary Navigation
// >
$( '.subnav-wrapper' ).on( 'touchstart', function( e ) {
// Prevent secondary navigation from bubbling up...
e.stopPropagation();
} );
$( '.subnav-wrapper > ul > li > a' ).on( 'touchstart', function( e ) {
// Cancel default event behaviors...
e.preventDefault();
e.stopPropagation();
// Hook the important elements for this event...
var ThisA = $( this );
// Handle the event as a link click...
window.location.href = ThisA.attr( 'href' );
} );
}
$( document ).on( 'ready', function() {
MH_Init();
} );
} )( jQuery );
</script>

Related

CSS <ul><li> submenu won't close on click, need to swap with close link

when in mobile view my css responsive menu for mobile, will show the submenu when you click on the link, but how do change the link, to something like 'Close X' as the list is long, and if you back on the link it doesn't close, unless you click a different link.
I've managed to create a separate close link. But this now means I've got two links. I want 1 link which will open, then change to the a close link when the submenu is open and when you click on that it will close.
Thanks
css
nav li ul {
display:none;
}
# open
nav ul li a:hover + .hidden, .hidden:hover {
display: block;
position:absolute;
opacity:1.0;
background-color: #343434;
padding:0.5em;
}
# close
nav ul li #close:hover + .hidden, .hidden:hover {
display: none;
position:absolute;
opacity:1.0;
background-color: #343434;
padding:0.5em;
}
menu
<ul>
<li><span id="close">Close X don't show till city clicked</span>
Cities ↓ remove and replace with close or up arrow
<ul class=hidden>
<li>London</li>
<li>New York</li>
<li>Rome</li>
</ul>
</li>
</ul>
This works as you are hoping I believe, The majority of the function is via CSS to keep jquery to a minimum.
CSS Selectors
> selector for immediate children
~ selector for all siblings of the preceding element
Let me know if this isn't what you were hoping for.
Demo
// Add click event to collapse anchor
$("li > a.collapse").click( function() {
// Remove .expand class from parent
$(this).parent().removeClass("expand");
});
// Add click event to expand anchor
$("li > a.expand").click( function() {
// Add .expand class to parent
$(this).parent().addClass("expand");
});
li > a.collapse, li.expand > a.expand {
display: none;
}
li.expand > a.collapse {
display: inherit;
}
li > a.expand ~ ul {
display: none;
}
li.expand > a.expand ~ ul {
display: inherit;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul>
<li>
<a class="collapse">Close</a>
<a class="expand">Cities</a>
<ul>
<li>London</li>
<li>New York</li>
<li>Rome</li>
</ul>
</li>
</ul>

show drop down menu outside its sidebar parent,and on scrolling make the menu also scroll according to its parent,

Here is the code below,
I need the the dropMenu div after scrolling the nav to change its position (as much as nav scrolling). to stay below the (i) element
<nav>
<ul>
<li>
<a onclick={this.setState(prevState => {showDropMenu:!prevState.showDropMeny})}>
<i class="fas fa-ellipsis-h" />
</a>
</li>
{showDropMenu &&<div className="dropMenu"></div> }
</ul>
</nav>
nav {
overflow-y: visible;
overflow-x: hidden;
max-height: 70vh;
}
ul {
list-style-type: none;
min-width: 15vw;
padding-left: 0;
}
is there any big or small change can I make to achieve that ?
You can take a look on this example https://www.w3schools.com/howto/howto_js_sticky_header.asp
Below you can see quick example which I have made with your code
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
showDropMenu: true
};
}
render() {
return (
<div className="App">
<nav>
<ul>
<li>
<a
onClick={() =>
this.setState({ showDropMenu: !this.state.showDropMenu })
}
>
<i className="fas fa-ellipsis-h" /> Click Me
</a>
</li>
{this.state.showDropMenu && (
<div className="dropMenu">Drop Menu</div>
)}
</ul>
</nav>
<div className="content">
Some Text Some Text Some Text Some Text Some Text
</div>
</div>
);
}
}
nav {
background-color: blue;
position: fixed;
top: 0;
width: 100%;
}
ul {
list-style-type: none;
min-width: 15vw;
padding-left: 0;
}
.content {
margin-top: 100px;
}

Trying to make mobile Nav Menu with only CSS

I have been working on this website and am using media queries to adjust the layout of the view according to the screen size. For the mobile phone size I want to hide the navigation that is already in place and just show a simple "Menu" link that when clicked, displays the Nav Menu. I having been doing research, however I am looking for the simplest way possible with the code that I have. Any ideas would be greatly appreciated. I would like to stay away from javaScript if possible.
<nav>
<ul>
<li>Meet The Practioner</li>
<li>Services & Rates</li>
<li>Book Appointment</li>
<li>Location & Hours</li>
<li>Testimonials</li>
<li>Questions & Answers</li>
<li>Benefits of Massage</li>
<li>Body Sense Magazine</li>
</ul>
Menu
</nav>
This is my jsFiddle that shows the CSS and the rest of the code. http://jsfiddle.net/Floyd/v723oqfc/
So what you could do is:
Create a button called menu-bttn with the css:
a.menu-bttn {
display: none;
//Other properties
}
//You should really use javascript or jquery for button click rather than CSS
a.menu-bttn:focus > nav ul li a {
display: block;
}
...
#media only screen and (max-width:WIDTH) {
a.menu-bttn {
display: inline-block;
}
nav ul li a {
display: none;
width: 100%;
//positioning
}
}
JQuery Click Approach:
<script>
function toggleMenu() {
$('nav ul li a').slideToggle("fast");
}
</script>
<a onclick="toggleMenu()" class="menu-bttn">Menu</a>
OR
<script>
$(document).ready(function() {
$('.menu-bttn').click(function() {
$('nav ul li a').slideToggle("fast");
});
});
</script>
<a class="menu-bttn">Menu</a>
Documentation On SlideToggle: http://api.jquery.com/slidetoggle/
You dont HAVE to use SlideToggle, there are other options:
Documentation On Toggle: http://api.jquery.com/toggle/
Pure Javascript Approach:
<script>
var bttn = document.getElementsByClassName('menu-bttn');
var bttn = bttn[0];
function toggleMenu() {
var menu = document.getElementsById(//Id Of nav ul li a elements);
if (menu.style.display === 'none')
menu.style.display = 'block';
else
menu.style.display = 'none';
}
</script>
<html>
...
<a onclick="toggleMenu()" class="menu-bttn">Menu</a>
...
</html>

How can I combine jQuery sortable UI with static captions for the placeholders?

I have a sortable set of pictures, implemented with jQuery UI. I would like to have each of the pictures within a box and with a caption at the top. The boxes and their captions should not move when pictures are sorted. Is there an easy way to do this?
EDIT: I have been investigating a bit and I found an approach that could do the trick. It consists on locking down some items on their locations using
class: static
(see the second answer to this question) and this demo.
Unfortunately, when I insert images into the list, it does not work well anymore: demo.
It looks like what you need is a combination of draggable and droppables widgets rather than sortable. I'd call it "swappable" :P
You can achieve this by swapping the images on drop event as shown below:
$("#swappable img").draggable({
revert: "invalid",
zIndex: 1
});
$("#swappable .placeholder").droppable({
snap: true,
snapMode: "inner",
drop: function(event, ui) {
var $existing = $(this).find("img.ui-draggable");
if ($existing)
/* droppable already contain an image, append it to the parent of
dropped item. */
ui.draggable.parent().append($existing);
ui.draggable.css({ // reset the positioning applied by widget
top: 0,
left: 0
}).appendTo(this);
}
});
#swappable {
list-style-type: none;
margin: 0;
padding: 0;
}
#swappable li {
border: 1px solid black;
background-color: cream;
}
#swappable li span {
/*style anyway you want*/
}
#swappable li img {
width: 50px;
height: 50px;
}
#swappable li .placeholder {
display: inline-block;
width: 50px;
height: 50px;
margin: 5px;
background: #eee;
}
<link href="http://code.jquery.com/ui/1.9.2/themes/base/jquery-ui.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="http://code.jquery.com/ui/1.9.2/jquery-ui.js"></script>
<ul id="swappable">
<li>
<div class="placeholder">
<img src="http://i46.tinypic.com/2epim8j.jpg" />
</div>
<span>
Item Description 1
</span>
</li>
<li>
<div class="placeholder">
<img src="http://i49.tinypic.com/28vepvr.jpg" />
</div>
<span>
Item Description 2
</span>
</li>
<li>
<div class="placeholder">
<img src="http://i50.tinypic.com/f0ud01.jpg" />
</div>
<span>
Item Description 3
</span>
</li>
</ul>
The following little code did the trick:
HTML
<div class="sortableDiv">
<ul id="sortable">
<li class="ui-state-default">
<span class="ui-icon ui-icon-arrowthick-2-n-s">
<image src="http://t1.gstatic.com/images?q=tbn:ANd9GcQ0wAliOPQ_saAtWhNhhPajglDjIZVrnO19MXaYS0Doum-yztJ_CA"/>
</span>
</li>
<li class="ui-state-default">
<span class="ui-icon ui-icon-arrowthick-2-n-s">
<image src="http://t1.gstatic.com/images?q=tbn:ANd9GcQ0wAliOPQ_saAtWhNhhPajglDjIZVrnO19MXaYS0Doum-yztJ_CA"/>
</span>
</li>
<li class="ui-state-default">
<span class="ui-icon ui-icon-arrowthick-2-n-s">
<image src="http://t1.gstatic.com/images?q=tbn:ANd9GcQ0wAliOPQ_saAtWhNhhPajglDjIZVrnO19MXaYS0Doum-yztJ_CA"/>
</span>
</li>
</ul>
</div>
<div class="contentDiv">
<ul id="content">
<li class="ui-state-default">
Item Description 1
</li>
<li class="ui-state-default">
Item Description 2
</li>
<li class="ui-state-default">
Item Description 3
</li>
</ul>
</div>
CSS
.sortableDiv,.contentDiv {
float:left;
}
#content {
list-style-type:none;
line-height:88px;
margin:0;
padding:0;
}
#sortable {
list-style-type:none;
margin:0;
padding:0;
}
#sortable li {
padding-left:2em;
width:65px;
margin:5px;
}
#sortable li span {
position:relative;
margin-left:-1.3em;
}
image {
height:100px;
width:100px;
}
JQuery
$(function() {
$( "#sortable" ).sortable();
});
And some CSS given in the demo link.
DEMO
Updated DEMO
Updated DEMO-1

Fixed menu at top but not the first element

How can i use position: fixed; for my menu, when it isn't the first element on the website.
My logo is the top item on the website, thereafter the menu. When i scroll down the page i want the menu to be the top element. How can i do this? And is it possible with only css?
This would require the use of javaScript, but can be done quite simply.
Example
JsFiddle
HTML
<header>
<p class="site-title">
Your logo here
</p>
<nav>
<ul>
<li>Home</li>
<li>About</li>
<li>Contact</li>
</ul>
</nav>
</header>
CSS
ul{
background-color: red;
margin: 0;
}
ul li{
display: inline;
}
.fixed{
position: fixed;
top: 0;
left: 0;
width: 100%;
}
jQuery
$(function ()
{
// Get the initial position of the menu.
var menuTop = $('nav').offset().top;
$(window).scroll(function ()
{
// Check position
if ($(window).scrollTop() > menuTop)
{
$('nav').addClass('fixed');
}
else
{
$('nav').removeClass('fixed');
}
});
});

Resources