CSS Multi Column Layout Margin Issue
Asked Answered
A

5

8

I have a css based 2 column layout...

.mainContentSection {
  font-size: 1.1em;
  margin: 20px 10px 10px;
  padding: 0;
  -moz-column-count: 2; /* Firefox */
  -webkit-column-count: 2; /* Safari and Chrome */
  column-count: 2;
  -moz-column-gap:30px; /* Firefox */
  -webkit-column-gap:30px; /* Safari and Chrome */
  column-gap:30px;
}

.mainContentSection p {
  margin: 0 0 20px 0;
  padding: 0;
  border: 1px solid gray;
}

Occasionally the top of the second column catches the margin from the bottom of the previous paragraph. This pushes down the top of the next paragraph as seen in the attached pic. I have tried break-inside, changing margins, inline-block. All have had some success, but not optimal. Can I access the second column to remove that margin?

enter image description here

Arne answered 18/11, 2015 at 0:10 Comment(1)
This screenshot is taken in Chrome. This is not a situation that happens consistently. Thats why I took the snap. I have had this issue appear and disappear and reappear while I was trying to fix it. For example I changed the p display to inline-block, which sucked a whole broken p to the second column. A solution, but not one I like. I undid the display change and the problem was gone. Sooner or later it returns. I also have seen it on other sites. I have a screenshot from a different site, but cant seem to post it. It happens often enough that it is an issue.Arne
F
5

I had the same issue with Safari. Adding display: inline-block on the columns items solved the problem for me.

Freckle answered 21/9, 2020 at 9:21 Comment(1)
That fixed my margin issue on Firefox as well.Rabinowitz
L
5

The root of the issue appears to be when using column-count browsers treat margin and padding differently depending on whether there are an even or odd number of elements.

This means solutions like display: inline-block; width: 100%; or playing with margin or padding create inconsistent results.

Solution

The only way I found to make this consistently work across browsers is to add a parent-element and a spacer. Then use break-inside: avoid to keep the two elements together.

HTML

<div class="mainContentSection">
  <div class="parent-element">    <!-- added this element -->
    <p>Blah blah blah blah</p>
    <div class="spacer"></div>     <!-- added this element -->
  </div>
  <div class="parent-element">   
    <p>Blah2 blah2 blah2 blah2</p>
    <div class="spacer"></div>   
  </div>

  <!-- addition items... -->

</div>

CSS

.mainContentSection{
  column-count:2
}
.parent-element{
  -webkit-column-break-inside: avoid;
  page-break-inside: avoid;
  break-inside: avoid;
}
.spacer{
  height: 10px;
}

You can add padding to mainContentSection or add another spacer above the paragraph depending where you need space.

Problem

The inconsistent alignment appears to be is driven by margin and padding being handled differently for an even or odd number of elements. I found this to be true for -top and -bottom but to keep things simple I only use margin-bottom in the example.

Even Number of Elements (works fine)

When there's an even number of elements margin-bottom works.

enter image description here

Odd Number of Elements (does not work)

When there's an odd number of elements margin-bottom gets moved to the second column creating the misalignment.

enter image description here

Other Solutions

This means that just playing with margin or padding leads to inconsistent results across browsers and devices.

Using display: inline-block; width:100% almost works but I found for some browser/device variations if there are only two elements it keeps the two elements in one column because there is no break. This can be addressed by adding a break as proposed here but as the user mentions it seems to have inconsistent results if element heights vary.

Lys answered 24/12, 2020 at 22:12 Comment(0)
F
1

I think I'm a bit late to the party but as there is no accepted answer here is mine.

Before going to the point and despite it shouldn't be affecting to your problem is very much recommended to always apply both column-width and column-count values to get better responsive results.

columns: [minimum width] [column count]

Once that said, just add that your <p> margins (margin: 0 0 20px 0;) are totally OK, that's the way to avoid any troubles. You just have to add break-inside: avoid; to them and you see the magic happen.

Three thinks to take into account:

  1. Break-inside applies to the content elements, not to the parent container
  2. Break-inside browser compatibility relays on different formats, not only prefixes
  3. Break-inside has issues when changing its value dynamically (e.g. from the browser's inspector panel)

Maybe those three tips were the reason why your attempts failed achieving your goal. So the code you need is something like this:

.mainContentSection p {
  -webkit-column-break-inside: avoid;
  page-break-inside: avoid;
  break-inside: avoid;
  margin: 0 0 20px 0;
  padding: 0;
  border: 1px solid gray;
}

If you want to see a working example you can do so in this pen: https://codepen.io/elcssar/pen/dypGaWy

Floriated answered 6/12, 2020 at 13:39 Comment(2)
Except on Safari, currently. In my case, I had to also switch to padding. (If your elements have backgrounds or borders, remove their margin and wrap them in divs which have padding.)Castaneda
Old Safari, previous to version 10 do not support break-inside, only the prefixed property -webkit-break-inside: auto/always, so avoid is not supported. After that version there should be no problem. However if there was, probably the display: inline-block suggested by @Freckle will fix it.Floriated
A
0

Simply don't use top margins on the .mainContentSection element, so the margin line would read as: margin: 0 10px 20px 10px;

.mainContentSection {
  font-size: 1.1em;
  margin: 0 10px 20px 10px;
  padding: 0;
  -moz-column-count: 2; /* Firefox */
  -webkit-column-count: 2; /* Safari and Chrome */
  column-count: 2;
  -moz-column-gap:30px; /* Firefox */
  -webkit-column-gap:30px; /* Safari and Chrome */
  column-gap:30px;
}
Ammadas answered 18/11, 2015 at 0:39 Comment(1)
Thank you, but it didnt affect the margin or the padding that the p was passing to the 2nd column.Arne
V
0

Have you tried avoiding margin? Set margin-bottom: 0 and introduce a transparent border for the equivalent. Say border-bottom: 20px solid transparent should do the trick?

Viable answered 11/4, 2022 at 22:21 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.