CSS columns, odd offset depending on height
Asked Answered
D

3

7

I've run into a very odd behaviour regarding CSS column layout which only appears in Chrome.

Depending on the overall height of the item being columnized its left offset is shifted which makes it hard to determine an items actual location. The rendering looks fine but if you inspect the element you can actually see that it is offset by quite a alot.

Here's an example: https://jsfiddle.net/vx8h8u46/

Inspect the .panel element and you'll see that it's bounding rect does not start at the left. enter image description here

If you click on the button to remove one item then all of the sudden the bounding rect is correct. enter image description here

It appears that this happens when the panel's height exceeds a certain threshold but it's only speculation at this point. Is there a work around?


function logOffset() {
  document.getElementById("log").innerText = document.querySelector(".panel").getBoundingClientRect().left;
}

window.removeLastItem = function() {
  var items = document.querySelectorAll(".item");
  if (items.length) {
    items[items.length - 1].remove();
    logOffset();
  }
}

logOffset();
* {
  box-sizing: border-box;
}

.item {
  display: inline-block;
  width: 160px;
  height: 80px;
  outline: 1px solid red;
}

.container {
  -moz-column-width: 320px;
  column-width: 320px;
  -moz-column-fill: auto;
  column-fill: auto;
  max-height: 160px;
  width: 640px;
}
<div class="container">
  <div class="panel">
    <div class="item">1</div>
    <div class="item">2</div>
    <div class="item">3</div>
    <div class="item">4</div>
    <div class="item">5</div>
    <div class="item">6</div>
    <div class="item">7</div>
    <div class="item">8</div>
    <div class="item">9</div>

    <!-- Something weird happens after this -->
    <div class="item">10</div>
  </div>
</div>

<div>
  Left offset of
  <mark>panel</mark>:
  <span id="log"></span>
</div>

<button onclick="removeLastItem()">
  Remove last item
</button>
Diggs answered 2/8, 2016 at 16:36 Comment(0)
P
0

Children of columns must be inline, so the following code should work well:

.panel {
  display: inline; /* Children of columns must be inline  */
}

And the whole snippet:

function logOffset() {
  document.getElementById("log").innerText = document.querySelector(".panel").getBoundingClientRect().left;
}

window.removeLastItem = function() {
  var items = document.querySelectorAll(".item");
  if (items.length) {
    items[items.length - 1].remove();
    logOffset();
  }
}

logOffset();
* {
  box-sizing: border-box;
}

.item {
  display: inline-block;
  width: 160px;
  height: 80px;
  outline: 1px solid red;
}

.container {
  column-width: 320px;
  column-fill: auto;
  max-height: 160px;
  width: 640px;
}

.panel {
  display: inline; /* Children of columns must be inline  */
}
<div class="container">
  <div class="panel">
    <div class="item">1</div>
    <div class="item">2</div>
    <div class="item">3</div>
    <div class="item">4</div>
    <div class="item">5</div>
    <div class="item">6</div>
    <div class="item">7</div>
    <div class="item">8</div>
    <div class="item">9</div>

    <!-- Something weird happens after this -->
    <div class="item">10</div>
  </div>
</div>

<div>
  Left offset of
  <mark>panel</mark>:
  <span id="log"></span>
</div>

<button onclick="removeLastItem()">
  Remove last item
</button>

function logOffset() {
  document.getElementById("log").innerText = document.querySelector(".panel").getBoundingClientRect().left;
}

window.removeLastItem = function() {
  var items = document.querySelectorAll(".item");
  if (items.length) {
    items[items.length - 1].remove();
    logOffset();
  }
}

logOffset();
* {
  box-sizing: border-box;
}

.item {
  display: inline-block;
  width: 160px;
  height: 80px;
  outline: 1px solid red;
}

.container {
  -moz-column-width: 320px;
  column-width: 320px;
  -moz-column-fill: auto;
  column-fill: auto;
  max-height: 160px;
  width: 640px;
}
<div class="container">
  <div class="panel">
    <div class="item">1</div>
    <div class="item">2</div>
    <div class="item">3</div>
    <div class="item">4</div>
    <div class="item">5</div>
    <div class="item">6</div>
    <div class="item">7</div>
    <div class="item">8</div>
    <div class="item">9</div>

    <!-- Something weird happens after this -->
    <div class="item">10</div>
  </div>
</div>

<div>
  Left offset of
  <mark>panel</mark>:
  <span id="log"></span>
</div>

<button onclick="removeLastItem()">
  Remove last item
</button>
Put answered 10/8, 2016 at 23:11 Comment(2)
Which element are you referring to here? If you apply display: inline to .panel, it does fix the problem. If that's what you mean, make it clear in your answer and consider adding an example snippet.Impoverished
I forgot to add that .panel has display: inline-block but the problem persists.Diggs
J
0

User Border replace to outline in .item Class

The CSS border properties allow you to specify the style and color of an element's border.

An outline is a line that is drawn around elements (outside the borders) to make the element "stand out"

The CSS outline property is a confusing property. When you first learn about it, it's hard to understand how it is even remotely different from the border property. The W3C explains it as having the following differences:

1.Outlines do not take up space.

2.Outlines may be non-rectangular.

.item {
  display: inline-block;
  width: 160px;
  height: 80px;
  border: 1px solid red;
}

Live Demo

Jemena answered 11/8, 2016 at 9:42 Comment(2)
Outline is merely there to visualize where the items are without affecting the layout. The main issue is why Chrome is offsetting the .panel element's bounding box.Diggs
browser wise window height different then problem are occur. .plz read this :Link[#12325924 , #11359863Jemena
Z
0

Simplicity in solving the problem can be better than complicating it more sometimes.I suggest keeping everything as it's and try and add flex. Not only will it help you display in all browsers, but it will modify the view according to the browser size in a bootstrap like simple method. Try it and if it makes any undesired response please comment it.

.classname {
    display: flex;
    flex-wrap: wrap;
    justify-content:center;
}
Zippora answered 17/8, 2016 at 10:24 Comment(1)
We're actually using flex for the items in the real code (inline-flex in truth to prevent multicolumn from clipping the items) but the problem persists. Something happens when each panel's height reaches a certain point.Diggs

© 2022 - 2024 — McMap. All rights reserved.