Animate a floating element - javascript

I have a list of elements that :
<ul>
<li>Element 1</li>
<li>Element 2</li>
<li>Element 3</li>
<li>Element 4</li>
<li>Element 5</li>
<li>Element 6</li>
</ul>
The CSS for these are :
display: inline-block;
width: 45px;
height: 45px;
Then the ul tag is :
white-space: nowrap;
onClick I add a class which floats the element left. So they're all in a row. onClick whatever element I select floats to the left (first in the row).
$('li').on('click', function() {
$(this).toggleClass('left_align');
});
Here's the jsfiddle
How do I get it so it moves the other elements and scrolls across kind of animated.
Thanks!

There are several properties or values you’ll want to transition, but which are not supported by browsers. List of animatable CSS properties
float is not a css3 animatable property.
You can try this patch:
$('li').on('click', function() {
$(this).toggleClass('left_align');
});
li {
display: inline-block;
width: 45px;
height: 45px;
background: red;
transition: 500ms ease-in-out;
}
li:hover {
cursor: pointer;
}
.left_align {
position: relative;
margin-left: -5px;
background: yellow;
transition: 500ms ease-in-out;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<ul>
<li>Element 1</li>
<li>Element 2</li>
<li>Element 3</li>
<li>Element 4</li>
<li>Element 5</li>
<li>Element 6</li>
</ul>
Fiddle here

Unfortunately you can't use CSS to animate float properties.
The following SO post has an interesting solution to your problem:
Javascript animate CSS float property
If you still want to animate and not use floats, you can try using a solution employing margins. To fix the problem of spacing between list elements, you can just animate to negative margin values.
li {
display: inline-block;
width: 45px;
height: 45px;
background: red;
transition: 2s ease-in-out;
margin-left: 15px;
}
li:first-of-type {
margin-left: 0;
}
li:hover {
cursor: pointer;
}
.left_align {
margin-left: -4px;;
background: yellow;
transition: 1s ease-in-out;
}
https://jsfiddle.net/37naqebd/

The simplest way I found to do this in jQuery is to reorder the elements and adjust their 'left' css values (you do have to remove the floats from the li elements since transitions wont work with floats):
var lefts = [0,50,100,150,200,250]
for (i=0; i<6; i++) {
$('li:nth-child('+(i+1)+')').css('left', lefts[i]);
}
$('li').on('click', function() {
// reorder clicked element to move it to the top of the list
$(this).insertBefore($('li:nth-child(1)'));
//update element left values
for (i=0; i<6; i++) {
$('li:nth-child('+(i+1)+')').css('left', lefts[i]);
}
});
jsfiddle here.

Related

How to hide the third nested list in this css dropdown nested lists?

I successfully created this not so bad css-only dropdown. I'm trying to hide the .submenutwo so that it is only visible when .submenu is on hover. If we can do this with css only that would be nice. But if javascript or jQuery can help it's fine.
/* define a fixed width for the entire menu */
.navigation {
min-width: 300px;
}
/* reset our lists to remove bullet points and padding */
.mainmenu,
.submenu {
list-style: none;
padding: 0;
margin: 0;
}
/* make ALL links (main and submenu) have padding and background color */
.mainmenu a {
display: block;
background-color: #CCC;
text-decoration: none;
padding: 10px;
color: #000;
}
/* add hover behaviour */
.mainmenu a:hover {
background-color: #C5C5C5;
}
/* when hovering over a .mainmenu item,
display the submenu inside it.
we're changing the submenu's max-height from 0 to 200px;
*/
.mainmenu li:hover .submenu {
display: block;
min-height: 200px;
height: auto;
}
/*
we now overwrite the background-color for .submenu links only.
CSS reads down the page, so code at the bottom will overwrite the code at the top.
*/
.submenu a {
background-color: #999;
}
/* hover behaviour for links inside .submenu */
.submenu a:hover {
background-color: #666;
}
/* this is the initial state of all submenus.
we set it to max-height: 0, and hide the overflowed content.
*/
.submenu {
overflow: hidden;
max-height: 0;
-webkit-transition: all 0.5s ease-out;
}
<nav class="navigation">
<ul class="mainmenu">
<li>Apples
<ul class="submenu">
<li>Green Apples
<ul class="submenutwo">
<li class='listOptionLvlThree'> Option 3
</li>
<li class='listOptionLvlThree'> Option 3
</li>
<li class='listOptionLvlThree'> Option 3
</li>
</ul>
</li>
</ul>
</li>
<li>Oranges
<ul class="submenu">
<li>Option 2
</li>
<li>Option 2
</li>
<li>Option 2
</li>
</ul>
</li>
<li>Grapes
<ul class="submenu">
<li>Purple Grapes
<ul class="submenutwo">
<li class='listOptionLvlThree'> Option 3
</li>
<li class='listOptionLvlThree'> Option 3
</li>
<li class='listOptionLvlThree'> Option 3
</li>
</ul>
</li>
<li>Green Grapes
</li>
<li>Red Grapes
</li>
</ul>
</li>
</ul>
</nav>
.submenutwo {
display: none }
.submenu:hover .submenutwo {
display: initial }
Here's how you can do it in css. Basically, what's happening here is. At first, you just need to hide .submenutwo. After the hover triggered, you just need to bring back the display to the default or even other display value will do.
may be this will help u
/* define a fixed width for the entire menu */
.navigation {
min-width: 300px;
}
.submenutwo {
display: none }
.submenu:hover .submenutwo {
display: initial }
/* reset our lists to remove bullet points and padding */
.mainmenu, .submenu {
list-style: none;
padding: 0;
margin: 0;
}
/* make ALL links (main and submenu) have padding and background color */
.mainmenu a {
display: block;
background-color: #CCC;
text-decoration: none;
padding: 10px;
color: #000;
}
/* add hover behaviour */
.mainmenu a:hover {
background-color: #C5C5C5;
}
/* when hovering over a .mainmenu item,
display the submenu inside it.
we're changing the submenu's max-height from 0 to 200px;
*/
.mainmenu li:hover .submenu {
display: block;
min-height: 200px;
height:auto;
}
/*
we now overwrite the background-color for .submenu links only.
CSS reads down the page, so code at the bottom will overwrite the code at the top.
*/
.submenu a {
background-color: #999;
}
/* hover behaviour for links inside .submenu */
.submenu a:hover {
background-color: #666;
}
/* this is the initial state of all submenus.
we set it to max-height: 0, and hide the overflowed content.
*/
.submenu {
overflow: hidden;
max-height: 0;
-webkit-transition: all 0.5s ease-out;
}
<nav class="navigation">
<ul class="mainmenu">
<li>Apples
<ul class="submenu">
<li>Green Apples
<ul class="submenutwo">
<li class='listOptionLvlThree'> Option 3</li>
<li class='listOptionLvlThree'> Option 3</li>
<li class='listOptionLvlThree'> Option 3</li>
</ul>
</li>
</ul>
</li>
<li>Oranges
<ul class="submenu">
<li>Option 2</li>
<li>Option 2</li>
<li>Option 2</li>
</ul>
</li>
<li>Grapes
<ul class="submenu">
<li>Purple Grapes
<ul class="submenutwo">
<li class='listOptionLvlThree'> Option 3</li>
<li class='listOptionLvlThree'> Option 3</li>
<li class='listOptionLvlThree'> Option 3</li>
</ul>
</li>
<li>Green Grapes</li>
<li>Red Grapes</li>
</ul>
</li>
</ul>
</nav>

Change li Background Colour In Javascript

I wonder if someone can please advise me how I can do the following?
I have the below JS which changes the background colour of an li based on id (I'm using the li as buttons). When the li is clicked the background turns white. Can someone please tell me what I should add to return all other li elements to their original colour?
Many thanks
$(function () {
$("li").click(function (e) {
document.getElementById(e.target.id).style.backgroundColor = "#fff";
});
});
You can do this more easily with a class:
$('li').on('click', function() {
$('.whitebg').removeClass('whitebg');
$(this).addClass('whitebg');
});
body {
background: deepskyblue;
}
li {
background: green;
display: inline-block;
cursor: pointer;
padding: 4px 8px;
}
.whitebg {
background: white;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
<li>Item 5</li>
</ul>

Centre <li> item on click with the container set to scrolling

I have got the very nearly completed, and I just need help for the last bit.
I have a horizontal scrolling navigation, which when I click an item it brings that item into the middle of the screen (worth noting that this is for mobile screens or similiar) and gives it a class of active or something.
My problem that is that it works fine when the container div is set to overflow: hidden, however I would like the container to be free scroll by using overflow-x: scroll.
But this throw the positioning out, if you scroll across, then click on a box, you will notice that it is not centered by the amount that has been scrolled before the click.
Any help would be amazing! There is a JS Fiddle here
$(document).ready(function() {
var scrollTo = 0;
$('body').on('click', "a", function() {
var activeItem = $('li.active');
var selectedItem = $(this).parent()
var activeIndex = $('li').index(activeItem);
var selectedIndex = $('li').index(selectedItem);
scrollTo = -selectedItem.position().left + $('.container').width() / 2 - selectedItem.width() / 2;
$('ul').css('transform', 'translateX(' + scrollTo + 'px)');
activeItem.removeClass('active');
selectedItem.addClass('active');
});
});
div.container {
width: 600px;
overflow: scroll;
}
ul {
white-space: nowrap;
transition: all ease 750ms;
position: relative;
}
ul li {
display: inline-block;
background: green;
}
ul li a {
padding: 80px;
display: block;
color: white;
font-weight: bold;
text-decoration: none;
}
ul li.active {
background: blue;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<ul>
<li class="active"> 1</li>
<li> 2</li>
<li> 3</li>
<li> 4</li>
<li> 5</li>
<li> 6</li>
<li> 7</li>
<li> 8</li>
</ul>
</div>
You have to take in account, the scrollLeft of the container:
$(document).ready(function() {
var scrollTo = 0;
$('body').on('click', "a", function() {
var activeItem = $('li.active');
var selectedItem = $(this).parent()
var activeIndex = $('li').index(activeItem);
var selectedIndex = $('li').index(selectedItem);
scrollTo = $('.container').scrollLeft() -selectedItem.position().left + ($('.container').width() / 2) - (selectedItem.width() / 2);
$('ul').css('transform', 'translateX(' + scrollTo + 'px)');
activeItem.removeClass('active');
selectedItem.addClass('active');
});
});
div.container {
width: 600px;
overflow: scroll;
}
ul {
white-space: nowrap;
transition: all ease 750ms;
position: relative;
}
ul li {
display: inline-block;
background: green;
}
ul li a {
padding: 80px;
display: block;
color: white;
font-weight: bold;
text-decoration: none;
}
ul li.active {
background: blue;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<ul>
<li class="active"> 1</li>
<li> 2</li>
<li> 3</li>
<li> 4</li>
<li> 5</li>
<li> 6</li>
<li> 7</li>
<li> 8</li>
</ul>
</div>

Different styles for childs before and after specifed element using jQuery and CSS?

I need to set special styles for li.done depending on whether they are before or after li.current. How can I do that using jQuery or CSS?
ul { list-style: none; padding: 0; margin: 0; }
ul li {
display:inline-table;
padding: 5px 12px;
color: #ddd;
background-color: #bbb;
margin: 0;
}
.done {
background-color: #ddd;
color: #aaa
}
.current {
background-color: #99f;
color: #dee
}
<ul>
<li class="done">step 1</li>
<li class="done">step 2</li>
<li class="current">step 3</li>
<li class="done">step 4</li>
<li>step 5</li>
</ul>
You should take a look at jQuerys .prevAll() and .nextAll().
var current = $(".current");
current.prevAll(".done").addClass("before");
current.nextAll(".done").addclass("after");
Please note that you will have to redo this every time you change the current element.
The documentation can be found here and here.
You can achieve this just with CSS by using the ~ selector. From the W3 documentation:
General sibling combinator
The general sibling combinator is made of the "tilde" (U+007E, ~) character that separates two sequences of simple selectors. The elements represented by the two sequences share the same parent in the document tree and the element represented by the first sequence precedes (not necessarily immediately) the element represented by the second one.
That means that you could set the styles for the .done that happen after .current by applying the selector: .current ~ .done.
One example:
ul { list-style: none; padding: 0; margin: 0; }
ul li {
display:inline-table;
padding: 5px 12px;
color: #ddd;
background-color: #bbb;
margin: 0;
}
.done {
background-color: #ddd;
color: #aaa
}
.current {
background-color: #99f;
color: #dee
}
.current ~ .done {
background-color:#f99;
color:white;
}
<ul>
<li class="done">step 1</li>
<li class="done">step 2</li>
<li class="current">step 3</li>
<li class="done">step 4</li>
<li class="done">step 5</li>
<li>step 6</li>
</ul>

Simulating Touch on a Windows Surface without the use of aria-haspop

Microsoft suggests using aria-haspop="true" to simulate hover on touch-enabled devices.
This is also the correct use in the W3 roles model spec.
Without including aria-haspop="true" I am unable to keep a submenu open when I click, and when I hold down a click it will fire a "right-click".
Codepen Example
HTML
<ul class="menu">
<li aria-haspopup="false">
aria-haspopup="false"
<ul class="sub-menu">
<li>Sub Menu Item 1</li>
<li>Sub Menu Item 2</li>
<li>Sub Menu Item 3</li>
</ul>
</li>
<li>
Menu Item 2
</li>
<li aria-haspopup="true">
aria-haspop="true"
<ul class="sub-menu">
<li>Sub Menu Item 1</li>
<li>Sub Menu Item 2</li>
<li>Sub Menu Item 3</li>
</ul>
</li>
</ul>
CSS
.menu > li {
display: inline-block;
position: relative;
background: #1abc9c;
}
.menu > li > a {
padding: 20px;
background: #1abc9c;
display: inline;
float: left;
}
.menu > li:hover .sub-menu {
display: block;
position: absolute;
background: #1abc9c;
top: 50px;
left: 0;
}
.menu .sub-menu {
display: none;
}
.menu .sub-menu li {
padding: 20px;
width: 140px;
}
Let's try to make the web a less accessible place. Is there any way to have the sub-menu work just as well without adding aria tags on a windows surface device? Preferably using only CSS. Javascript would be acceptable but less than ideal.
In the same Microsoft guide you linked, they recommend using the onclick event to show content.
The best practice is to not use hover to hide content that a user can interact with. Instead, consider using the onclick event to toggle the visibility.
The challenge, of course, is that your menu items are also links, and clicking on a link is likely to take you to another page. Only if they really are dead anchors that go nowhere (as in your example code) is it safe to use their onclick events to show or hide the submenus.
Here's some example code that uses onclick to show the submenus instead of using CSS :hover. Note that my example directly assigns the handlers for the sake of brevity, but better practice would be to use the addEventListener() method.
var parentMenuItems = document.querySelectorAll(".menu > li");
var len = parentMenuItems.length;
while (len--) {
parentMenuItems[len].onclick = showSubMenu;
parentMenuItems[len].onmouseenter = showSubMenu;
parentMenuItems[len].onmouseleave = hideSubMenu;
}
function showSubMenu() {
this.querySelector(".sub-menu").style.display = "block";
}
function hideSubMenu() {
this.querySelector(".sub-menu").style.display = "none";
}
.menu > li {
display: inline-block;
position: relative;
background: #1abc9c;
}
.menu > li > a {
padding: 20px;
background: #1abc9c;
display: inline;
float: left;
}
.menu > li .sub-menu {
position: absolute;
background: #1abc9c;
top: 50px;
left: 0;
}
.menu .sub-menu {
display: none;
}
.menu .sub-menu li {
padding: 20px;
width: 140px;
}
<ul class="menu">
<li aria-haspopup="false">
aria-haspopup="false"
<ul class="sub-menu">
<li>Sub Menu Item 1</li>
<li>Sub Menu Item 2</li>
<li>Sub Menu Item 3</li>
</ul>
</li>
<li aria-haspopup="true">
aria-haspop="true"
<ul class="sub-menu">
<li>Sub Menu Item 1</li>
<li>Sub Menu Item 2</li>
<li>Sub Menu Item 3</li>
</ul>
</li>
</ul>

Categories