使用CSS均匀分布子元素的高度

时间:2022-10-16 11:40:44

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:

以下是四种颜色的样子,列表高度为90像素,边框周围有厚边框:

使用CSS均匀分布子元素的高度

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

上面的图像在以下来源的Firefox 3.6.13中呈现:

<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:

这一切都很好。该列表确实是90像素高度 - 在边界内 - 并且每种颜色获得(看似)该空间的相等份额。现在,让我们在Safari或Chrome中呈现相同的HTML / CSS:

使用CSS均匀分布子元素的高度

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

注意绿色行和边框之间的窄白行。对于我们在这里看到的内容有一个非常简单的解释: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

Safari和Chrome中的WebKit并不真正喜欢非整数像素高度并且会丢弃小数。对于四行高度22,我们在列表的底部得到2个像素: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.

在静态HTML文件的上下文中,我们可以轻松地将元素的高度分别设置为23,22,23,23像素,并且列表在任何浏览器中都会显示正常。另一方面,如果从数据库加载颜色并且计数随每个请求而变化,则需要更灵活的解决方案。

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?

我知道如何通过使用Javascript计算和设置每行onload上的整数值高度来解决这个问题,如果没有其他任何显示,我将发布此解决方案。但是,我会更喜欢纯粹的基于CSS的解决方案。你能想到一个吗?

2 个解决方案

#1


4  

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.

正如所承诺的,这是一个解决问题的Javascript解决方案。我仍然对基于CSS的简单解决方案非常感兴趣,但与此同时,这个答案可能会帮助其他人完成他们的工作。

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.

该脚本需要在入口点声明两个变量:list应指向容器的DOM元素(例如

    ),以及此列表中项目集合(例如
  • )的项目。

  • )的项目。

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);
}

#2


-3  

Try to remove all endlines between <li> tags. For ex.

尝试删除

  • 标记之间的所有结束。对于前者

  • 标记之间的所有结束。对于前者
  • <ul><li></li><li></li></ul>

    Sometimes this was a problem, but in your situation I'm not sure that will help ;) Just give a try ;)

    有时这是一个问题,但在你的情况下,我不确定这会有所帮助;)只是试一试;)

    #1


    4  

    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.

    正如所承诺的,这是一个解决问题的Javascript解决方案。我仍然对基于CSS的简单解决方案非常感兴趣,但与此同时,这个答案可能会帮助其他人完成他们的工作。

    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.

    该脚本需要在入口点声明两个变量:list应指向容器的DOM元素(例如

      ),以及此列表中项目集合(例如
    • )的项目。

    • )的项目。

    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);
    }
    

    #2


    -3  

    Try to remove all endlines between <li> tags. For ex.

    尝试删除

  • 标记之间的所有结束。对于前者

  • 标记之间的所有结束。对于前者
  • <ul><li></li><li></li></ul>

    Sometimes this was a problem, but in your situation I'm not sure that will help ;) Just give a try ;)

    有时这是一个问题,但在你的情况下,我不确定这会有所帮助;)只是试一试;)