I try to create a menu that streches its items to the window width. Could someone please tell me what I'm doing wrong? I know that this question has been asked before but I just don't know what's wrong with my code.
This is what I"m trying to achieve. The red is the window
http://jsfiddle.net/JdGeQ/5/
Javascript
$(function(){
$(window).resize(function (e) {
setTimeout(function () {
resizeButtons();
}, 200);
});
resizeButtons();
});
function resizeButtons() {
var count = $("#menu").length;
var itemwidth = $(window).width / count;
$(".item").css("background", "blue");
$(".item").css("width", itemwidth);
}
css
.elementtop {
position: fixed;
top: 0;
}
.elementfooter {
position: fixed;
bottom: 0;
}
.elementright {
right: 0;
}
ul {
min-width:100%;
padding:0;
margin:0;
float:left;
list-style-type:none;
background: #000000;
}
li {
display:inline;
}
a {
overflow: hidden;
text-decoration:none;
color:white;
background-color:purple;
padding:0.2em 0.6em;
border-right:1px solid white;
}
html
<div>
<ul id="menu">
<li> <a href="#" class="item">
<span>Text text</span>
</a>
</li>
<li> <a href="#" class="item">
<span>Text2</span>
</a>
</li>
<li> <a href="#" class="item">
<span>Text3</span>
</a>
</li>
</ul>
</div>
Thanks in advance.
You have a couple errors in your jQuery code. You need to use width() instead of width, as it is a function call. Also, you are not selecting menu items when you assign count, you are only selecting the #menu.
function resizeButtons() {
var count = $("#menu .item").length;
var itemwidth = $(window).width();
itemwidth = itemwidth / count;
$(".item").css(
"width", itemwidth
);
}
You also need to set display:inline-block or display:block on your anchors, so that you can affect the width.
a { display:inline-block; }
Updated Fiddle
Note: You will also need to account for the padding, etc. on your menu items to get the proper result.
This can be done with pure CSS:
http://cssdeck.com/labs/hgmvgwqc
ul {
min-width:100%;
padding:0;
margin:0;
display: table;
list-style-type:none;
background: #000000;
}
li {
display: table-cell;
width: 33%;
}
a {
overflow: hidden;
text-decoration:none;
color:white;
background-color:purple;
padding:0.2em 0.6em;
border-right:1px solid white;
display: block;
}
This method requires knowing how many list items there are.
With $("#menu").length you're getting the number of occurrences of the #menu element -- 1. You should use the following to get the number of menu items
var count = $("#menu li").length;
Related
I'm trying to get a dynamic amount of elements to show across 5 elements using CSS3 column-count, but when I expand the list item heights on hover, it occasionally causes jumping (an element going to the next column).
You can see the behavior here
I'm assuming it's because column-count uses the height to calculate which item goes where or something...how can we have it work as intended?
If I try to increase the height of <ol>, they become 4 columns or even 3 columns because the elements fill up the first column, then start the 2nd column, and so on.
In short, CSS3 columns are not the right solution for what you are trying to do. (If I understand correctly, you want the hovered element to overflow its parent container by going outside its box. However, CSS3 columns are designed such that overflow will continue at the top of the next column, and there's no way that I'm aware of to change this behavior).
I would recommend using a different approach to achieve the UI you're after, such as using JQuery to insert wrappers around each column.
However, if you're set on using column-count, you may be able to hack it by doing something like this:
JSFiddle:
http://jsfiddle.net/p6r9P/
CSS:
ol li:nth-child(5n) {
padding-bottom: 40px;
}
JQuery:
function togglePadding(li, status) {
var index = li.index();
var target = (index % 5 === 4) ? li : li.siblings().eq(index + 3 - (index % 5));
target.stop(true).animate({
"padding-bottom": (status === "on") ? "40px" : 0
});
}
$('a.song').each(function () {
var origwidth = $(this).width();
var origheight = $(this).height();
$(this).hover(function () {
togglePadding($(this).parent(), "off");
$(this).stop(true).animate({
width: origwidth * 2,
height: origheight * 2
})
}, function () {
$(this).stop(true).animate({
width: origwidth,
height: origheight
});
togglePadding($(this).parent(), "on");
});
$(this).clone(true).attr({
"class": "song-detail"
}).css({
"z-index": 1,
"background-color": "#CCC"
}).appendTo('ol').wrap("<li></li>");
});
This is just a rough demo and would need to be cleaned up for production. Basically the strategy is to add a 40px padding "buffer" after every 5th element (the end of a column). When an element is hovered, we find the sibling at the end of its column and animate its padding to 0.
But you can see that if you run your mouse over several elements quickly in succession, sometimes the boxes will shudder as one box temporarily jumps up to the next column. CSS3 column-count REALLY wants to balance those columns.
So I would recommend using a different approach, but feel free to play with that and see if you can get it working.
**EDIT: One way to do it without column-count**
Since you're already using JQuery, you could have it wrap every X elements in a <div class="col">, and use those divs as your columns.
JSFiddle: http://jsfiddle.net/QhTvH/
JQuery:
var container;
var i = 0;
var numCols = 5;
var colCount = Math.ceil($('.songs a').length / numCols);
$('.songs a').each(function () {
if (i % colCount === 0) {
container = $('<div class="col"></div>').appendTo(".songs");
}
$(this).appendTo(container);
i++;
});
CSS:
.songs .col {
max-width: 18%;
overflow: hidden;
display: inline-block;
vertical-align: top;
margin: 0 5px;
}
.songs a {
display: block;
margin: 10px 10px;
background-color: #EEE;
width: 200px;
height: 40px;
cursor: pointer;
text-overflow:ellipsis;
overflow: hidden;
white-space: nowrap;
}
HTML:
<section class="songs">
<a class="song" data-src="songs/Titanic.mp3" style="width: 187px;">Titanic</a>
<a class="song" data-src="songs/Titanic.mp3" style="width: 187px;">Titanic2</a>
etc...
</section>
You could as well, find out how much space remains in the last col and fill it to even the columns.
DEMO codepen \0/ DEMO fiddle from yours.
The jQuery added :
var col = 5; // number of columns
var liH =50; // average height ol li, including margins
var nbli = $('ol li').length; // how many do we have ?
var olH = nbli*liH; // total height of ol
var colnbli = Math.ceil(nbli/col); // how many li would it make if each column is fully filled ?
var colH = colnbli*liH; // what's average height of each col
var ceilOlH= colH*col; //what's total height of columns together
var olH = nbli*liH; // what's real height of ol ?
var fixLiH = ceilOlH - olH; // how much difference do i have ?
var fixcol = $('<li style="height:'+fixLiH+'px;width:50%;padding:0; "></li>').appendTo('ol'); // let's see if we can fill the remaining gap
and the CSS
li:hover ~li:last-child {
margin-top:-10px ;
display:block
}
To match with animate and avoid jumping lis , add a transition to li for the margin:
ol li {
display:inline-block;
margin: 5px 10px;
transition:0.5s;/* to match jQuery animate */
}
Add/remove <li>s to see if this is what you looked for or reset column-count:5; in both CSS and var col = 5 ;
Have you tried to use the a tag as container?
And animate a inner div (or other)
Js Fiddle here: http://jsfiddle.net/keypaul/Yk2du/41/
html
<ol>
<li>
<a class="song" data-src="songs/Titanic.mp3" style="width: 187px;">
<div>Titanic</div>
</a>
</li>
<li>
<a class="song" data-src="songs/Titanic.mp3" style="width: 187px;">
<div>Titanic</div>
</a>
</li>
<li>
<a class="song" data-src="songs/Titanic.mp3" style="width: 187px;">
<div>Titanic</div>
</a>
</li>
<li>
<a class="song" data-src="songs/Titanic.mp3" style="width: 187px;">
<div>Titanic</div>
</a>
</li>
<li>
<a class="song" data-src="songs/Titanic.mp3" style="width: 187px;">
<div>Titanic</div>
</a>
</li>
</ol>
js
$('a.song').each(function() {
var origwidth = $(this).width();
var origheight = $(this).height();
$(this).hover(
function() {
$(this).find('div').stop().animate({width: origwidth * 2, height: origheight * 2});
}, function() {
$(this).find('div').stop().animate({width: origwidth, height: origheight});
});
$(this).clone(true).attr({"class":"song-detail"}).css({"z-index": 1, "background-color":"#CCC"}).appendTo('ol').wrap("<li></li>");
});
css
ol {
padding: 0px;
list-style: decimal-leading-zero inside;
color: #000;
font-size: 0.9em;
-moz-column-count: 5;
-webkit-column-count: 5;
column-count: 5;
}
ol li {
display: inline-block;
margin: 5px 10px;
}
ol li a {
background-color: #EEE;
display: block;
width: 200px;
height: 40px;
cursor: pointer;
text-overflow:ellipsis;
white-space: nowrap;
margin: 0;
position:relative;
}
ol li a div {
position:absolute;
top:0;left:0;
width:187px;
height:40px;
background:red;
}
I have a div as a banner/header image for a website and this image will show a picture of houses on it initially. The banner will also have 6 divs acting as buttons and when the user hovers over each div, it changing the background image of the header to a different image that will represent each page.
Here is the code I have so far:
Fiddle
HTML:
<div id="navholder">
<div id="nav">
<div id="button1"><div id="triangle"></div><div id="buttonname">Home</div></div>
<div id="button2"><div id="triangle"></div><div id="buttonname">Buying</div></div>
<div id="button3"><div id="triangle"></div><div id="buttonname">Renting</div></div>
<div id="button4"><div id="triangle"></div><div id="buttonname">Building</div></div>
<div id="button5"><div id="triangle"></div><div id="buttonname">Architecture</div></div>
<div id="button6"><div id="triangle"></div><div id="buttonname">Land Buying</div></div>
</div>
</div>
CSS:
#navholder {
position:absolute;
background:#FFFFFF;
width:950px;
height:350px;
top:150px;
margin:0 auto;
left:0;
right:0;
border:solid 1px #999;
background-image: url(http://placehold.it/950x350);
}
#nav {
width:950px;
position:absolute;
bottom:-22px;
text-align: center;
display:inline-block;
}
#button1, #button2, #button3, #button4, #button5, #button6 {
width:130px;
height:35px;
background-color:#879362;
margin-left:2px;
margin-right:2px;
display:inline-block;
font-family:"Palatino Linotype", "Book Antiqua", Palatino, serif;
line-height:35px;
font-weight:bold;
color:#fff;
}
#button1:hover > #triangle, #button2:hover > #triangle, #button3:hover > #triangle, #button4:hover > #triangle, #button5:hover > #triangle, #button6:hover > #triangle{
display: block;
}
#button1:hover, #button2:hover, #button3:hover, #button4:hover, #button5:hover, #button6:hover{
background-color:#B7939B;
}
#triangle {
position:relative;
width: 0;
height: 0;
border-left: 15px solid transparent;
border-right: 15px solid transparent;
border-bottom: 15px solid #B7939B;
top:-15px;
left:0px;
right:0;
margin:0 auto;
display: none;
}
#buttonname {
width:130px;
position:absolute;
top:0px;
margin:0 auto;
}
I have tried implementing this example: from On a CSS hover event, can I change another div's styling?
#a:hover + #b {
background: #ccc;
}
But I couldn't quite get it to work with my layout of multiple divs.
Is there a way to do it purely with CSS?
I will use JS if that's the only reasonable way.
Edit: Updated the CSS a little. It is only a fiddle, but, still. Forgot to add focus. Fixed.
One possible approach could be something like this. However, I am very rusty when it comes to CSS and have not tested it in other then latest Firefox and Chrome.
No JavaScript.
http://jsfiddle.net/Ifnak/ZyX4t/
Basic idea is to use a div directly after each link, as such you can use the + selector.
HTML
<div id="banner">banner
<div id="menu">
<a id="mm_btn1" href="a.html">Home<span></span></a>
<div class="h_banner">A</div>
<a id="mm_btn2" href="b.html">Buying<span></span></a>
<div class="h_banner">B</div>
<a id="mm_btn3" href="c.html">Renting<span></span></a>
<div class="h_banner">C</div>
</div>
</div>
CSS:
#banner, .h_banner {
width : 500px;
height : 250px;
position : absolute;
margin : 0 auto;
left : 0;
right : 0;
}
#banner {
top : 50px;
border : 10px solid #942;
background-image : url(http://placehold.it/500x250/222/666&text=Welcome);
}
#menu {
width : 500px;
position : relative;
top : 220px;
margin : 0 auto;
text-align : center;
}
#menu a {
position : relative;
z-index : 100;
display : inline-block;
padding : 20px 50px;
background : #963;
width : 60px;
text-decoration : none;
outline : none;
font : bold 18px "Lucida Grande", "Lucida Sans Unicode", Helvetica, Arial, Verdana, sans-serif;
color : #aaa;
}
/* Display none, etc. Here opacity is used to combine with transition effect. */
.h_banner {
opacity : 0;
top : -240px;
z-index : 90;
-webkit-transition : .7s;
transition : .7s;
}
/* On hover set opacity and background image for div.
* Image could be set earlier to force pre-load.
*
* __Important__ to include "focus" so that Tab etc. gives
* the same effect as hover. */
#mm_btn1:focus + .h_banner, #mm_btn1:hover + .h_banner {
opacity : 0.98;
background-image : url(http://placehold.it/500x250&text=Home);
}
#mm_btn2:focus + .h_banner, #mm_btn2:hover + .h_banner {
opacity : 0.98;
background-image : url(http://placehold.it/500x250&text=Buying);
}
#mm_btn3:focus + .h_banner, #mm_btn3:hover + .h_banner {
opacity : 0.98;
background-image : url(http://placehold.it/500x250&text=Renting);
}
/* Arrow */
#menu a span {
display : none;
}
#menu a:focus span,
#menu a:hover span {
display : block;
}
#menu a span:after {
content : "";
position : absolute;
width : 0;
height : 0;
border-width : 30px;
border-style : solid;
border-color : transparent transparent rgba(153,102,51,.98) transparent;
top : -55px;
margin : 0 -30px;
}
Try this
HTML
<div id="button1" onmouseover="chbg('http://placehold.it/300x250')" onmouseout="chbg('http://placehold.it/950x350')"><div id="triangle"></div><div id="buttonname">Home</div></div>
Script
function chbg(img) {
document.getElementById('navholder').style.backgroundImage = 'url('+img+')';
}
DEMO
Check this out :-
http://jsfiddle.net/8C4TT/
$(".buy").hover(function () {
$("#navholder").css("background-image","url('http://upload.wikimedia.org/wikipedia/commons/0/06/Skybox_sky.png')");
});
$(".rent").hover(function () {
$("#navholder").css("background-image","url('http://upload.wikimedia.org/wikipedia/commons/0/06/Skybox_sky.png')");
});
The example you give won't work as + selects directly adjacent siblings to the target selector (http://www.w3.org/TR/css3-selectors/#selectors). #navholder is the parent, and I'm pretty sure it's impossible to select an element's parent via CSS alone.
You could change the structure so that #navholder is inside #nav, and use ~ to select it via any sibling, or use a JS solution.
This is not pure javascript or css, it uses jQuery to do it. If it helps great, it's only one solution for this problem :)
Html:
<div id="navholder">
<div id="nav">
<a href="index.html" data-img="http://placehold.it/950x350/FFFFFF">
<div id="button1">
<div id="triangle"></div>
<div id="buttonname">Home</div>
</div>
</a>
<div id="button2"><div id="triangle"></div><div id="buttonname">Buying</div></div>
...
</div>
Javascript
$(function () {
var $navholder = $("#navholder");
$navholder.on("mouseenter mouseleave", "a", function (event) {
if (event.type === "mouseenter") {
$navholder.css("background-image", "url('" + $(this).data("img") + "')");
} else {
$navholder.css("background-image", "url('http://placehold.it/950x350')");
}
});
});
I have a list of elements (divs) which all have the same background color (white). Now, I want to make the background color change (to blue) once they are clicked. Thing is this, only one can be highlighted at a time.
So, let's say you click div1, and it turns blue. If you click div2, it needs to make div1 turn white and then div2 turn blue.
Sort of a selecting method, no?
Is there a stand-alone method of doing this?
Try This:
Jquery Code:
$('div').bind('click',function(){
$('div').removeClass('selected');//remove selected class from previously added div
$(this).addClass('selected');//add class to current div
})
CSS:
.selected{
background-color:blue;
}
Try this ...
<style type="text/css"><!--
#menu_top {
list-style:none;
width:100%;
float:left;
margin:8px 0;
border-bottom:8px solid #60CBFF;
font:normal 11px/22px arial,helvetica,sans-serif;
}
#menu_top li, #menu_top a {
float:left;
height:22px;
}
#menu_top li {
margin-left:4px;
}
#menu_top a {
background: none repeat scroll 0 0 white;
color: #000000;
padding: 0 8px;
position: relative;
text-decoration: none;
}
#menu_top a:active,
#menu_top a:focus,
#menu_top a:hover {
background: none repeat scroll 0 0 blue;
}
</style>
and HTML code is ..
<ul id="menu_top">
<li>HOME</li>
<li>Services</li>
<li>Portfolio</li>
<li>Download</li>
<li>About Us</li>
<li>Career</li>
<li>Contact Us</li>
</ul>
You can check my JSFIDDLE also.
For a library agnostic solution, you could use something like this:
<style>
.clickable {
background-color: #eee;
height: 30px;
margin: 10px;
}
</style>
<div>
<div class="clickable"></div>
<div class="clickable"></div>
<div class="clickable"></div>
</div>
<script>
var clickables = document.getElementsByClassName('clickable');
var resetSiblings = function () {
for (var i = clickables.length - 1; i >= 0 ; i--)
clickables[i].style.backgroundColor = '#eee';
};
var clickHandler = function (ev) {
resetSiblings();
ev.target.style.backgroundColor = '#00f'
};
for (var i = clickables.length - 1; i >= 0 ; i--)
clickables[i].addEventListener("click", clickHandler, false);
</script>
I am working on a website that features many links on the same page:
http://www.alexanderlozada.com
To let the user know what item they are currently viewing, I'd like to implement a small triangle that points at the currently selected item.
example:
How could I go about doing this without making each link a separate page?
sample of the link I am working with- (I have to keep the current href and rel)
<a class="grey show_hide" href="#" rel="#projects" >
PROJECTS
</a>
In most cases this is done by using pseudo elements :before and/or :after like so (read full article)
CSS:
/* creates triangle */
.selected:after {
content:"";
display:block; /* reduce the damage in FF3.0 */
position:absolute;
bottom:-2px;
left:50%;
width:0;
margin-left:-10px;
border-width:0px 15px 15px;
border-style:solid;
border-color:white transparent;
}
div.links {
display: inline-block;
position:relative; // you must have this to position the triangle propery
width: 25%;
height: 45px; // adjust height to fit the menu
float: left;
text-align: center;
font-size: 24px;
padding-top: 10px;
}
jQuery:
$(function(){
$('.show_hide').click(function(){
$('div.links').removeClass('selected'); // remove all other 'selected' links
$(this).parent().addClass('selected'); // sets the current .links to be selected
});
});
Add an active class in your :
<a class="btn active">menu link</a>
css:
.btn.active { background:url(cursor-active.png) bottom center no-repeat; }
js:
$('.btn').click(function(){
$('.btn').removeClass('active');
$(this).addClass('active');
});
You can see here : FIDDLE
I'm rather new to jQuery and I'm trying to make a cool little menu effect where when the user hovers over a element (#nav li) it will animate to a larger width, which will reveal the full background image. Each of the menu items has a ID to explicitly set a width (since they are all different in size), so #nav1 might be 80px whereas #nav2 is 90px. So I found this: How to get all of the IDs with jQuery? and that helped me to create a array but now I'm having problem figuring out how to insert it into the animation. I figured I would need to do a each or for loop. But like I said I'm rather new to jQuery and am having some problems.
So basically I'd like the variable chgWidth to return the width() of the currently hovered #nav and then I would plug that variable into the animate except I would add 30px for instance, or on the hover off I would subtract 30px.
Any idea? Here is my current code...
$(function(){
var chgWidth = $("#nav [id]").map(function(id) {
return this.id;
});
$.each(chgWidth,function(n,value){
$('#nav li').hover(function() {
$(this).stop(0,1).animate({"width" : chgWidth+"px" });
},
function(){
$(this).stop(0,1).animate({ "width" : chgWidth+"px" });
});
});
Sample HTML
<div id="menu">
<ul id="nav">
<li id="nav1"><a alt="" href="#">home</a></li>
<li id="nav2"><a alt="" href="#">about us</a></li>
<li id="nav3"><a alt="" href="#">weddings & events</a></li>
<li id="nav4"><a alt="" href="#">gallery</a></li>
<li id="nav5"><a alt="" href="#">accolades</a></li>
<li id="nav6"><a alt="" href="#">blog</a></li>
<li id="nav7"><a alt="" href="#">contact us</a></li>
</ul>
</div>
Sample CSS:
#menu { width: 100%; overflow: hidden; padding:0px 0px; background: #ffc4a0;}
#nav { position: relative; left: 50%; float: left;}
#nav li { position: relative; right: 50%; float: left; padding: 0 5px; margin: 0 5px; overflow:hidden; }
#nav1 { width:55px; }
#nav2 { width:80px; }
#nav3 { width:175px; }
#nav4 { width:60px; }
#nav5 { width:85px; }
#nav6 { width:40px; }
#nav7 { width:100px; }
#nav li a { color: #ffffff; text-decoration: none; font: bold 16px Verdana, Arial, Helvetica, sans-serif; }
Based on the answer I got this is what I ended up doing and it seems to work good (Thanks to Joel and krdluzni):
$(function(){
$("#nav [id]").each(function(){
$(this).hover(function() {
$(this).stop(0,1).animate({"width" : "+=30" });
},
function(){
$(this).stop(0,1).animate({ "width" : "-=30" });
});
});
});
jQuery as of a short while ago accepts a += like syntax for widths and other numeric values in animate. See the second last paragraph in the overview (and the examples as well) here: http://docs.jquery.com/Effects/animate#paramsdurationeasingcallback
You don't actually need to get the ids in an array so much as you need to assign an animation to each element in nav that has an id.
Instead of mapping the ids to your chgWidth variable, use each to iterate over the collection of elements and set each one individually.
$(function(){
$("#nav [id]").each(function(){
$(this).hover(function() {
$(this).stop(0,1).animate({"width" : this.id+"px" });
},
function(){
$(this).stop(0,1).animate({ "width" : this.id+"px" });
});
});
});
When you use each to iterate over a collection of elements, the this context is set to the current iterating element.
No each function is required! If a selector returns multiple elements, all of the elements recieve the function chained to them.
This is almost right:
$("li #nav").hover(
function()
{
$(this).stop(0,1).animate({"width" : this.width()+30 });
//save original width somehow
},
function()
{
$(this).stop(0,1).animate({ "width" : this.width()-30 });
//retrieve original width
});
);
You just need to save the widths somehow. Perhaps they can be read from the CSS.