CSS columns bug — 5 column count only showing 4 (with images)
Ok I have an answer, although it is a workaround, not a fix. I changed up the images so that some were 300px in height and others, 370px. Basically I varied the the height of the images and kept the width of all the images the same, 300px. So the answer is to either not use square images, or if you want to use all square images, use column-count:4 instead of 5.
If anyone can provide further insight into why this happens that would be great.
CSS column-count not respected
In your example (jsfiddle), there are 5 elements of equal size to be distributed into 4 columns. Since they won't fit next to each other (they are more than 4) , the first column will contain 2 elements. That defines the height of the container, so the second column will also get 2 elements, and so there's one remaining for the third column and none for the fourth column. There are four columns, but the fourth one is simply empty...
In other words: The height of the container is determined by the minimum height which is needed to fit all elements into the number of columns. Once that is done, the content will be filled into the columns starting from the left, and each column will get as much content as fits into it.
Chrome columns bug when number of columns is less then column-count
Based on how your markup looks like, the break-inside: avoid-column;
should fix that, together with usingdisplay: block
instead of display: inline-block
(and you can drop width: 100%
)
.outer {
-webkit-column-count: 3;
-moz-column-count: 3;
column-count: 3;
-webkit-column-gap: 30px;
-moz-column-gap: 30px;
column-gap: 30px;
}
.inner {
position: relative;
display: block;
margin-bottom: 40px;
line-height: 1.3;
break-inside: avoid-column;
}
.inner:nth-child(even) {
background: lightgray;
}
<div class="outer">
<div class="inner">
Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat.
</div>
<div class="inner">
Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat.
</div>
</div>
CSS column-count and Chrome bug: how to avoid overflow content being cropped
I'm not sure how you are styling your .onsale
so I styled on my own way.
If you use position:relative
in .pin
and then position:absolute
you can achieve what you want.
UPDATE: The issue is the webkit-column-count:1
in Chrome and since having that with 1
or nothing is the same, just remove it and use another technique that will allow you to have the .onsale
out of flow by using position:absolute
#columns {
border: 1px solid red;
}
.pin {
width: 100%;
display: inline-block;
padding: 10px;
margin-bottom: 5px;
position: relative
}
.onsale {
min-height: 3.236em;
min-width: 3.236em;
padding: .202em;
font-size: 1em;
font-weight: 700;
position: absolute;
text-align: center;
line-height: 3.236;
top: -.5em;
left: -.5em;
margin: 0;
border-radius: 100%;
background-color: lightgreen;
color: white;
font-size: .857em;
-webkit-font-smoothing: antialiased;
}
<div id="columns">
<div class="pin">
<a href="#">
<span class="onsale">Sale!</span>
<img src="//placehold.it/300x300" />
</a>
<h3>Product 1</h3>
</div>
<div class="pin">
<a href="#">
<span class="onsale">Sale!</span>
<img src="//placehold.it/300x300" />
</a>
<h3>Product 2</h3>
</div>
</div>
Balancing height in column-count CSS columns that contain only images
EDIT:
If you don't need to keep line-height: 0
you would simply use .gallery img {display:block}
and remove line-height, it's all you need. That would be the best. table-cell
and so on can have some side-effects. For example vertical-align: middle
leave a space under the images, and is just a hack.
https://jsfiddle.net/bruLwktv/
Challange accepted, here is the solution: ;)
The algorithm makes sure every images is loaded and then partition them into both coloumns in a way the have about the closest total height possible to create a minimal gap.
Using The greedy algorithm for the Partition problem to create Balanced partitions.
var gallery = document.getElementsByClassName("gallery")[0]
var images = gallery.getElementsByTagName("img")
var notLoaded = 0
window.onload = function() {
for (var i = images.length; i--;) {
if (images[i].width == 0) {
// let the image tell us when its loaded
notLoaded++
images[i].onload = function() {
if (--notLoaded == 0) {
allImgLoaded()
}
}
}
}
// check if all images are already loaded
if (notLoaded == 0) allImgLoaded()
}
function allImgLoaded() {
// Partition images
var imgs = partitionImages(images)
// reorder DOM
for (var i = images.length; i--;) {
gallery.appendChild(imgs[i])
}
}
function partitionImages(images) {
var groupA = [], totalA = 0
var groupB = [], totalB = 0
// new array width img and height
var imgs = []
for (var i = images.length; i--;) {
imgs.push([images[i], images[i].height])
}
// sort asc
imgs.sort(function(a, b) {
return b[1] - a[1]
});
// reverse loop
for (var i = imgs.length; i--;) {
if (totalA < totalB) {
groupA.push(imgs[i][0])
totalA += imgs[i][1]
} else {
groupB.push(imgs[i][0])
totalB += imgs[i][1]
}
}
return groupA.concat(groupB)
}
section {
background: magenta;
/* So you can see the area I don't want to appear */
}
.gallery {
width: 100%;
line-height: 0;
-webkit-column-count: 2;
-webkit-column-gap: 0;
-moz-column-count: 2;
-moz-column-gap: 0;
column-count: 2;
column-gap: 0;
}
<section class="gallery">
<div><img src="http://lorempixel.com/800/1000/"></div>
<div><img src="http://lorempixel.com/800/600/"></div>
<div><img src="http://lorempixel.com/800/200/"></div>
<div><img src="http://lorempixel.com/800/700/"></div>
<div><img src="http://lorempixel.com/800/900/"></div>
<div><img src="http://lorempixel.com/800/400/"></div>
<div><img src="http://lorempixel.com/800/200/"></div>
<div><img src="http://lorempixel.com/800/600/"></div>
<div><img src="http://lorempixel.com/800/700/"></div>
<div><img src="http://lorempixel.com/800/600/"></div>
<div><img src="http://lorempixel.com/800/550/"></div>
<div><img src="http://lorempixel.com/800/700/"></div>
<div><img src="http://lorempixel.com/800/600/"></div>
<div><img src="http://lorempixel.com/800/1000/"></div>
<div><img src="http://lorempixel.com/800/700/"></div>
</section>
CSS column layout has an incorrect column-count
Balancing columns
Here's the behavior I observed in FF, Chrome, and Opera:
1 element: 1 0 0
2 elements: 1 1 0
3 elements: 1 1 1
4 elements: 2 2 0 (expected: 2 1 1)
5 elements: 2 2 1
6 elements: 2 2 2
7 elements: 3 3 1 (expected: 3 2 2)
8 elements: 3 3 2
9 elements: 3 3 3
With 4 and 7 elements, the browser is choosing to balance the first 2 columns, rather than spreading the elements out over as many columns as possible.
Order of the elements
The columns are filled sequentially when they're balanced. In other words, if 8 elements are added to 3 columns, the columns will be filled as shown below:
1 4 7
2 5 8
3 6
...rather than like this:
1 2 3
4 5 6
7 8
Demo (tested in FF, Chrome, Opera)
css columns: last column is not filled
In your example, there are 9 elements of equal size to be distributed into 4 columns. Since they won't fit into 4 columns when the first column contains 2 elements (which would add up to a maximum of 8), the first column will contain 3 elements. That defines the height of the container, so the second column will also get 3 elements, and so there's also 3 remaining for the third column and none for the fourth column. There are four columns, but the fourth one is simply empty...
In other words: The height of the container is determined by the minimum height which is needed to fit all elements into the number of columns. Once that is done, the content will be filled into the columns starting from the left, and each column will get as much content as fits into it.
ADDITION AFTER COMMENT:
To get a distribution of elements as you want it, you have to insert empty DIVs - there is no other way (reason: read above):
.columns {
-webkit-column-count: 4;
/* Chrome, Safari, Opera */
-moz-column-count: 4;
/* Firefox */
column-count: 4;
}
.item {
display: inline-block;
width: 100%;
border: 1px solid red;
}
.empty {
display: inline-block;
}
<div class="columns">
<div class="item">Lorem ipsum dolor sit amet 1</div>
<div class="item">Lorem ipsum dolor sit amet 2</div>
<div class="item">Lorem ipsum dolor sit amet 3</div>
<div class="item">Lorem ipsum dolor sit amet 4</div>
<div class="item">Lorem ipsum dolor sit amet 5</div>
<div class="empty"></div>
<div class="item">Lorem ipsum dolor sit amet 6</div>
<div class="item">Lorem ipsum dolor sit amet 7</div>
<div class="empty"></div>
<div class="item">Lorem ipsum dolor sit amet 8</div>
<div class="item">Lorem ipsum dolor sit amet 8</div>
</div>
CSS columns styling only works on one column in Chrome
Someone mentioned here that they managed to fix this by adding transform: translateZ(0)
to the grid item to enable hardware acceleration, in this case:
.grid-cell-container {
transform: translateZ(0)
}
Related Topics
Make Text in Select Element Wrap When Too Long
Font-Weight Is Not Working Properly
Clip-Path on Chrome Leaves a Strange Line on the Edge
Has the ::-Webkit-Selection Selector Ever Been Supported
Inherited Text-Decoration Style
How to Create a Row of Elements of Equal Width Inside an Inline Container? Possibly Using Flexbox
CSS Use Color from Another Class
Galaxy S4 Stock Browser CSS3 Border-Radius Support
Change Color of Data Url Embedded Svg Image
How to Make a Link Inside a Div Fill the Entire Space Inside the Div
How to Solve the Table Row Background Image Problem, in Chrome, in Multi Celled Tables
Using :Last-Child with Class Selector
How to Force This CSS Grid to Wrap to a New Line Without Specifying Minmax Sizes
Responsive Design Using Md-Grid-List in Angular 2
How to Revert Back to Normal After Display:None for Table Row
Are CSS Variable Changes Possible Upon a Radio Button's Checked Selector Being Triggered
How Important Is W3C Xhtml/CSS Validation When Finalizing Work