Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
289 views
in Technique[技术] by (71.8m points)

webkit - Evenly distributed height of child elements with CSS

Assume you need to present a list of colors to the user. The colors must be displayed in a list with a fixed height, with each color occupying an equal fraction of that height.

Here is what it should look like with four colors, a list height of 90 pixels and a thick border around:

Firefox

The image above is rendered in Firefox 3.6.13 from the follow source:

<ul style="height: 90px; border: 5px solid black; padding: 0;">
    <li style="height: 25%; background: red;">
    <li style="height: 25%; background: blue;">
    <li style="height: 25%; background: yellow;">
    <li style="height: 25%; background: green;">
</ul>

This is all fine. The list is indeed 90 pixels heigh – within the borders – and each color gets an (seemingly) equal share of this space. Now, let's render the same HTML/CSS in Safari or Chrome:

Chrome

Notice the narrow white row between the green row and the border. There is a pretty simply explanation for what we are seeing here: 0.25 × 90 = 22.5

WebKit in Safari and Chrome does not really like non-integer pixel heights and drops the decimal. With four rows of height 22 we get 2 pixels of nothing in the bottom of the list: 90 - 4 × 22 = 2

In the context of a static HTML file, we could easily set the height of the elements to 23, 22, 23, 23 pixels respectively, and the list would show up fine in any browser. If, on the other hand, the colors are loaded from a database and the count varies with each request, a more flexible solution is needed.

I know how to solve this by computing and setting an integer value height on each row onload using Javascript, and I will post this solution if nothing else shows up. I would, however, prefer a purely CSS-based solution to the problem. Can you think of one?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

As promised, here's a Javascript solution to the problem. I am still very interested in a simple CSS based solution, but in the meantime, this answer might help others getting their job done.

The script expects two variables to be declared at the point of entry: list should point to the DOM element of the container (eg <ul>), and items to the collection of items (eg <li>) in this list.

The idea is to dynamically set an explicit height in pixels on each item, in a way that ensures that the sum of the heights equals the height of the container, while allowing only minimal deviation of height between items. We do this by looping over the items, computing an integral height for each, by simply dividing the remaining available space with the number of items left to have an explicit height set.

var spaceRemaining = list.clientHeight;
var itemsRemaining = items.length;

while (itemsRemaining > 0) {
    var itemHeight = Math.round(spaceRemaining / itemsRemaining);
    items[itemsRemaining - 1].style.height = itemHeight;
    spaceRemaining -= itemHeight;
    itemsRemaining -= 1;
}

For those favoring conciseness over readability, here's a shorter version of the very same script:

for (var space = list.clientHeight, i = items.length; i; i--) {
    space -= items[i-1].style.height = Math.round(space / i);
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...