CSS column-count elements jumping across columns

2024/2/27 7:41:50

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.

Answer

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>
http://en.ppmy.cn/q/41227.html

Related Q&A

I have no idea Object(this) means

In https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/fillthere is a line like// Steps 1-2. if (this == null) {throw new TypeError(this is null or not defined); }var O …

How to combine two parts of single form in angular?

I am making angular application with angular dynamic form where i am loading data for dynamic form through JSON..JSON has two parts such as part 1 and part 2,jsonDataPart1: any = [{"elementType&qu…

jquery hide a div that contains flash without resetting it

Greetings, I have written a modal using jquery UI and it appears at the front of a flash movie thus the html inside the modal becomes corrupt, I tried to hide the movie right before modal gets triggere…

jstree jquery plugin - Get all child and sub child nodes of parent

I am using the jsTree jquery plugin I am trying to fetch all the nodes and sub nodes of a selected parent. But somehow its not working unless I use recursion. Is there a better way inherent to jsTre…

Understanding Cyclic Redundancy Code algorithm for beginners

at section 5.5 of the PNG Specification, it discusses this concept in the PNG file format called "CRC" or "Cyclic Redundancy Code". Ive never heard of it before, so Im trying to und…

Why `+0n` throws an error but `-0n` does not?

The following code throws an error in javascript:console.log(String(+0n))But this code runs successfully:console.log(String(-0n))Why +0n throws an error but -0n does not?

Why does Date#getHours() return hour + 1?

This is my code:var feedDataTimestamp = new Date("2014-01-14T00:04:40+0000").getTime(); var parsedDate = new Date(+feedDataTimestamp); alert(parsedDate.getHours());but it should print 0, not …

DataTables warning - Request unknown parameter 0 for row 0, column 0

Im using a jQuery DataTable to display data taken from a database using a stored procedure and web service. I can run the SP or service using Fiddler just fine, but when it comes to populating the Data…

How can I get the previous URL of a tab?

When writing a Chrome extension, given a tab, how can I get the URL of the previously-visited page in that tab? i.e. the url that will appear in the omnibar after I hit "back"?

Javascript isnt uploading binary data

My javascript function only uploads text files correctly. Can anybody help me figure out how to make it also accept images etc. ?function fileUpload(files) {if (!files.length) { fileList.innerHTML = …