列表项的 CSS 多列布局在 Chrome 中没有正确对齐

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5314726/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-29 23:56:09  来源:igfitidea点击:

CSS multi-column layout of list items doesn't align properly in Chrome

cssalignmentcss-multicolumn-layout

提问by Ben D

I am building a menu system presented to the user in multi-column format. The column-countproperty in CSS3 gets me 90% of the way there, but I'm having difficulties with alignment under Chrome.

我正在构建一个以多列格式呈现给用户的菜单系统。CSS3 中的column-count属性让我达到了 90%,但我在 Chrome 下对齐有困难。

The menu is relatively simple:

菜单比较简单:

  • an unordered list divided into multiple-columns by the column-count property
  • columns should fill sequentially, so column-fill: auto
  • menu items are represented as list items
  • each list item has a a clickable anchor tag, extended fully via display: block
  • column-count 属性分为多列的无序列表
  • 列应按顺序填充,因此column-fill: auto
  • 菜单项表示为列表项
  • 每个列表项都有一个可点击的锚标签,通过display: block完全扩展

The alignment issue I'm having is most noticeable with a top-border and some background coloring on each list item. In Firefox, the list items are always aligned cleanly across each column, never bleeding into the previous/next column. In Chrome, alignment is a crapshoot, varying with how many list items are present and any padding/margin properties.

我遇到的对齐问题最明显的是每个列表项上的顶部边框和一些背景颜色。在 Firefox 中,列表项总是在每一列中整齐地对齐,永远不会渗入上一列/下一列。在 Chrome 中,对齐是一个废话,随着列表项的数量和任何填充/边距属性而变化。

I've posted the code for a simple test case here: http://pastebin.com/Ede3JwdG

我在这里发布了一个简单测试用例的代码:http: //pastebin.com/Ede3JwdG

The problem should be immediately evident: in Chrome, the first list item in the second column bleeds back into the first column. As you remove list items (click on them), you can see that alignment breaks down further.

问题应该很明显:在 Chrome 中,第二列中的第一个列表项会流回第一列。当您删除列表项(单击它们)时,您可以看到对齐方式进一步分解。

I've tried tweaking the padding/margin for the list items to no avail: Chrome appears to have a flawed algorithm for how it flows content across a multi-column layout.

我试过调整列表项的填充/边距无济于事:Chrome 似乎有一个有缺陷的算法,它如何在多列布局中流动内容。

The primary reason I haven't ditched column-count altogether (in favor of manual generation/Columnizer/etc.) is that the menu system also involves drag-and-drop functionality across multiple sub-menus, and having the menu data laid out as a cohesive list-based hierarchy makes for clean code.

我没有完全放弃列数(支持手动生成/列化器/等)的主要原因是菜单系统还涉及跨多个子菜单的拖放功能,以及布局菜单数据因为一个基于列表的内聚层次结构使得代码干净。

Is there a way to fix the alignment issue in Chrome or should I just give up on column-countfor now?

有没有办法解决 Chrome 中的对齐问题,还是应该暂时放弃列数

ADDED:

添加:

回答by asiby

You need each item in the column to be displayed as "inline-block". That will solve your problem without needing to use jQuery.

您需要将列中的每个项目都显示为“inline-block”。这将解决您的问题,而无需使用 jQuery。

Additionally, each element can be specified to have width: 100%in order to get the them to use the full width of the rows.

此外,可以指定每个元素具有width: 100%,以便让它们使用行的全宽。

Here is a working example:

这是一个工作示例:

$(document).ready(function() {
    for( var i = 0; i < 24; i++ ) {
        $("ul.newslist").append("<li><a href='#'>Item</a></li>");
    }
    $("ul.newslist > li").click(function() {
        $(this).remove();
    })
});
ul.newslist {
    columns: 5;
    background-color: #ccc;
    padding: 16px 0;
    list-style: none;
}

ul.newslist > li {
    display: inline-block;
    width: 100%;
    border-top: 1px solid #000;
}

ul.newslist > li > a {
    display: block;
    padding: 4px;
    background-color: #f6b;
    text-decoration: none;
    color: inherit;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul class="newslist"></ul>

回答by kmerc

I managed to balance uneven vertically-aligned columns by applying margin-*properties to the elements inside the multicolumn'd container.

我设法通过将margin-*属性应用于多列容器内的元素来平衡不均匀的垂直对齐列。

.content {
  column-width: 15em; /* or could be column-count, however you want to set up multi columns */
}
.content > section {
  -webkit-margin-before: 0;
  -webkit-margin-after: 0;
}

回答by Hyman Lawson

I've played around as well, and several sources I've seen online make it seem to be a known issue with webkit. A good breakdown can be found here: http://zomigi.com/blog/deal-breaker-problems-with-css3-multi-columns/

我也玩过,我在网上看到的几个来源使它似乎是 webkit 的一个已知问题。可以在这里找到一个很好的细分:http: //zomigi.com/blog/deal-breaker-problems-with-css3-multi-columns/

Someday, CSS 3!

总有一天,CSS 3!

Maybe try a jQuery plugin like http://welcome.totheinter.net/columnizer-jquery-plugin/?

也许尝试像http://welcome.totheinter.net/columnizer-jquery-plugin/这样的 jQuery 插件?

回答by Andrey

As for vertical margins leakage. You can replace margin with pseudo-element. Then set its height to desired margin value. You also need to set -webkit-column-break-inside: avoid;on the element containing pseudo-element so that it is not moved to another column. Do that only for webkit with the help of css-hack (not recommended) or js-detection(best way). Here is CSS:

至于垂直边距泄漏。您可以用伪元素替换边距。然后将其高度设置为所需的边距值。您还需要-webkit-column-break-inside: avoid;在包含伪元素的元素上进行设置,使其不会移动到另一列。仅在 css-hack(不推荐)或js-detection(最佳方式)的帮助下为 webkit 执行此操作。这是CSS:

.element {
  -webkit-column-break-inside: avoid;
}
.element:after {
  content: '';
  display: block;
  height: 20px;
}

回答by Julie Olson

I was having trouble with vertical alignment on a multi-column list. Turned out that the problem was that I was using bottom padding on my list li's-- I changed the li style to use a bottom margin instead, and the columns aligned to top again.

我在多列列表上垂直对齐时遇到问题。原来问题是我在我的列表 li 上使用底部填充 - 我将 li 样式更改为使用底部边距,并且列再次与顶部对齐。

回答by Kiee

My desired outcome was wanting to get a large list of links to display across 3 columns. Simply using column-break-inside:avoid;alone didn't work in webkit.

我想要的结果是想要获得一个大的链接列表,以显示在 3 列中。简单地column-break-inside:avoid;单独使用在 webkit 中不起作用。

HTML

HTML

<div class="links">
  <ol>
    <li><a>link</a></li> <!-- x 50 -->
  </ol>
</div>

css:

css:

.links ol {
  -webkit-column-count: 3;
  -moz-column-count: 3;
  column-count: 3;
}

.links li {
  display: block;
  border: 1px solid $background-colour; //to appear invisible
  -moz-column-break-inside:avoid;
  -webkit-column-break-inside:avoid;
  column-break-inside:avoid;
}

.links a {
  display: block;
  margin-bottom: 10px;
}

Solution (quirk if you will)

解决方案(如果你愿意,请咨询)

I added a 1px border around the list items which seemed to contain the margins of it's children and each column then aligned to the top.

我在列表项周围添加了一个 1px 边框,它似乎包含它的子项的边距,然后每一列都与顶部对齐。

Edit:This only seems to be required if you're using global border-box

编辑:这似乎只在您使用全局时才需要border-box

html {
  box-sizing: border-box;
}
*, *:before, *:after {
  box-sizing: inherit;
}

回答by Eleanor Zimmermann

I solved this by removing vertical margins on the child elements, and then increasing the line-height of the children to replicate desired spacing.

我通过删除子元素上的垂直边距来解决这个问题,然后增加子元素的行高以复制所需的间距。

I also noticed I could fix this vertical alignment issue by removing the child margins and converting it to grandchild padding.

我还注意到我可以通过删除子边距并将其转换为孙子填充来解决这个垂直对齐问题。

回答by Joel.O

I'm struggling with this as well, for a reporting system with many many data and titles with padding/margin that I need to flow on several columns for wider screens.

我也在为此苦苦挣扎,对于一个包含许多数据和标题的报告系统,我需要在更宽的屏幕上在几列上流动。

I've worked around my first big deal-breaker, the padding of the initial title element, with the :first-childpseudo-class (this is included in an @media rule for wide screens not shown here) :

我已经解决了我的第一个大问题,即初始标题元素的填充,以及:first-child伪类(这包含在此处未显示的宽屏幕的 @media 规则中):

The columns definition :

列定义:

.dimSlider .multicol {
  -moz-columns: 4;
  -webkit-columns: 4;
  columns: 4;
}

Canceling padding on top when in .multicol

进入时取消顶部填充 .multicol

.dimSlider .multicol h3 {
  padding-top: 0;
}

Cancelling padding and margin for the first element (color: blue;is so that I see if the rule catches) :

取消第一个元素的填充和边距(color: blue;以便我查看规则是否适用):

.dimSlider .multicol .criteria:first-child h3 {
  padding: 0 2%;
  margin: 0;
  color: blue;
}

So far, this looks way much neater in my Firefox. I'll see if there's some more tinkering to do but currently in Firefox the text looks aligned on the top, what is the most important.

到目前为止,这在我的 Firefox 中看起来更加整洁。我会看看是否还有更多的修补工作要做,但目前在 Firefox 中,文本看起来在顶部对齐,最重要的是什么。

EDIT : The problem seems quite worse with webkit-based browsers indeed. To solve it entirely, I modified the template in order to have a <div></div>around all the titled sections so I can add padding / margin at the end of the divs and not at the beginning of the titles. Now in webkit browsers it looks fine too.

编辑:确实,基于 webkit 的浏览器的问题似乎更糟。为了完全解决它,我修改了模板,以便<div></div>在所有标题部分周围都有一个,这样我就可以在 div 的末尾而不是在标题的开头添加填充/边距。现在在 webkit 浏览器中它看起来也不错。

BTW, using percentages measurements in multicolumns is quite tricky because the percentage seems calculated to the width of the column and not the global width of the parent element. I changed this by adding padding in the parent element of the columns.

顺便说一句,在多列中使用百分比测量非常棘手,因为百分比似乎是根据列的宽度而不是父元素的全局宽度计算的。我通过在列的父元素中添加填充来改变这一点。

But the biggest difficulty is that Firefox doesn't support any column-span or break-inside property, so when I have very few content, it is spread over the columns nonetheless, like one or two lines on each. Again, Smarty on the rescue :

但最大的困难是 Firefox 不支持任何 column-span 或 break-inside 属性,所以当我的内容很少时,它仍然分布在列上,就像每列一两行一样。再次,Smarty 在救援:

{if $element|@count <= 10}
<div class="nocol"> 
{/if} 

So far it works now for me...

到目前为止,它现在对我有用......

回答by Swati

this is solution for multicolumn space problem

这是多列空间问题的解决方案

ul li { line-height:40px; }