围绕父级中点居中多个元素

Center multiple elements around parent midpoint

我必须围绕元素的中点浮动多个元素。目前在 css 中使用 display: table / display: table-cell.

解决了这个问题

这个解决方案的问题是每组块都必须包裹在一个额外的元素中,这使得这个响应式布局变得困难。而且,可见顺序不对。

我想使用 javascript,通过使用 position: absolute 对齐元素,但我不知道如何计算偏移量。另一种选择可能是动态创建每个组(取决于 window 宽度/高度),并使用实际的 css(下方)对齐元素。

html, body {
  height: 100%;
}

.blocks {
  display: table;
  margin-left: auto;
  margin-right: auto;
  max-width: 40em;
  width: 100%;
  height: 100%;
}

.group {
  display: table-cell;
  vertical-align: middle;
}

.block {
  background-color: rgb(50, 50, 50);
  color: rgb(255, 255, 255);
  height: 8em;
  line-height: 8em;
  margin: 1em;
  text-align: center;
  width: 8em;
}

/* Debug
------------------------------------------------ */
 .blocks {
  counter-reset: tile;
}
.block:before {
  counter-increment: tile;
  content: counter(tile);
}
<!-- small screens -->
<div class="blocks">
  <div class="group">
    <div class="block"></div>
    <div class="block"></div>
  </div>
  <div class="group">
    <div class="block"></div>
    <div class="block"></div>
    <div class="block"></div>
  </div>
  <div class="group">
    <div class="block"></div>
    <div class="block"></div>
  </div>
</div>

<hr>

<!-- large screens -->
<div class="blocks">
  <div class="group">
    <div class="block"></div>
    <div class="block"></div>
  </div>
  <div class="group">
    <div class="block"></div>
    <div class="block"></div>
    <div class="block"></div>
  </div>
  <div class="group">
    <div class="block"></div>
    <div class="block"></div>
    <div class="block"></div>
    <div class="block"></div>
  </div>
  <div class="group">
    <div class="block"></div>
    <div class="block"></div>
    <div class="block"></div>
  </div>
  <div class="group">
    <div class="block"></div>
    <div class="block"></div>
  </div>
</div>

<!-- huge screens -->
<div class="blocks">
  <div class="group">
    <div class="block"></div>
    <div class="block"></div>
  </div>
  <div class="group">
    <div class="block"></div>
    <div class="block"></div>
    <div class="block"></div>
  </div>
  <div class="group">
    <div class="block"></div>
    <div class="block"></div>
    <div class="block"></div>
    <div class="block"></div>
  </div>
  <div class="group">
    <div class="block"></div>
    <div class="block"></div>
    <div class="block"></div>
    <div class="block"></div>
    <div class="block"></div>
  </div>
  <div class="group">
    <div class="block"></div>
    <div class="block"></div>
    <div class="block"></div>
    <div class="block"></div>
  </div>
  <div class="group">
    <div class="block"></div>
    <div class="block"></div>
    <div class="block"></div>
  </div>
  <div class="group">
    <div class="block"></div>
    <div class="block"></div>
  </div>
</div>

...为了完整性,position:absolute 方法:

.blocks {
  margin-left: auto;
  margin-right: auto;
  max-width: 40em;
  position: relative;
}
.block {
  background-color: rgb(0, 225, 225);
  border: 1px solid white;
  box-sizing:border-box;
  height: 8em;
  line-height: 8em;
  position: absolute;
  text-align: center;
  width: 8em;
}
.block:nth-of-type(1) {
  top: 8em;
  left: 0;
}
.block:nth-of-type(2) {
  top: 4em;
  left: 8em;
}
.block:nth-of-type(3) {
  top: 0;
  left: 16em;
}
.block:nth-of-type(4) {
  top: 4em;
  left: 24em;
}
.block:nth-of-type(5) {
  top: 8em;
  left: 32em;
}
.block:nth-of-type(6) {
  top: 16em;
  left: 0;
}
.block:nth-of-type(7) {
  top: 12em;
  left: 8em;
}
.block:nth-of-type(8) {
  top: 8em;
  left: 16em;
}
.block:nth-of-type(9) {
  top: 12em;
  left: 24em;
}
.block:nth-of-type(10) {
  top: 16em;
  left: 32em;
}
.block:nth-of-type(11) {
  top: 20em;
  left: 8em;
}
.block:nth-of-type(12) {
  top: 16em;
  left: 16em;
}
.block:nth-of-type(13) {
  top: 20em;
  left: 24em;
}
.block:nth-of-type(14) {
  top: 24em;
  left: 16em;
}
/* Debug
------------------------------------------------ */
 .blocks {
  counter-reset: tile;
}
.block:before {
  counter-increment: tile;
  content: counter(tile);
}
<div class="blocks">
  <div class="block"></div>
  <div class="block"></div>
  <div class="block"></div>
  <div class="block"></div>
  <div class="block"></div>
  <div class="block"></div>
  <div class="block"></div>
  <div class="block"></div>
  <div class="block"></div>
  <div class="block"></div>
  <div class="block"></div>
  <div class="block"></div>
  <div class="block"></div>
  <div class="block"></div>
</div>

理想情况下,布局会尊重 window 宽度和高度。这样块总是适合当前的屏幕尺寸。可以用这样的方式完成:

var cols = Math.floor(innerWidth / children[0].clientWidth)
var rows = Math.round(innerHeight / children[0].clientHeight)

我现在已经搜索了一段时间,但没有找到任何现有的解决方案。最接近的是:

顺便说一下,我的灵感来自 https://typekit.com/ ;)

flexbox 网格怎么样?您可以通过 flexboxorder 属性 以各种宽度重新排序项目。请参阅下面的网格快速示例。

.list {
  list-style: none;
  display: flex;
  margin: 0;
  padding: 0;
  flex-flow: column wrap;
  align-items: center;  
  align-content: center;
  justify-content: center;
  height: 500px;
  box-sizing: border-box;
}

.box-wrapper {
  background: lightblue;
  width: 100px;
  height: 100%;
  border: 1px solid blue;
  box-sizing: border-box;
  display: flex;
  flex-flow: column wrap;
  align-items: center;  
  align-content: center;
  justify-content: center;
}

.box {
  background: red;
  border: 1px solid darkred;
  width: 100px;
  height: 100px;
  box-sizing: border-box;
}
<ul class="list">

  <li class="box-wrapper">
    <div class="box"></div>
    <div class="box"></div>
  </li>
  <li class="box-wrapper">
    <div class="box"></div>
    <div class="box"></div>
    <div class="box"></div>
  </li>
  <li class="box-wrapper">
    <div class="box"></div>
    <div class="box"></div>
    <div class="box"></div>
    <div class="box"></div>
  </li>
  <li class="box-wrapper">
    <div class="box"></div>
    <div class="box"></div>
    <div class="box"></div>
  </li>
  <li class="box-wrapper">
    <div class="box"></div>
    <div class="box"></div>
  </li>
</ul>

知道了...一个基于百分比的解决方案,它创建了一个均匀分布的网格。

感觉有点老套,但应该可以:

function alignAround(elements, columns, gutter, weight) {

  var width = ((2 / 3) * 100) - (gutter / 2)
  var push = 100 - width

  var gutterCount = columns - 1
  var repeatAt = (columns * 2) - 1

  var firstShort = 1
  var lastShort = gutterCount
  var lastLong = repeatAt

  if (weight === 'odd') {
    firstShort = columns + 1
    lastShort = repeatAt
    lastLong = columns
  }

  if (columns > 1) {
    width = ((100 - (gutter * gutterCount)) / columns / 100) * 100
    push = (width + gutter) / 2
  }

  return Array.prototype.forEach.call(elements, function(element, index) {

    var styles = {
      width: width,
      height: width
    }

    if (columns > 1) {
      var i = index + 1

      styles.marginRight = gutter

      if ((i - firstShort) % repeatAt === 0) {
        styles.marginLeft = push
      }

      if ((i - lastShort) % repeatAt === 0) {
        styles.marginRight = push
      }

      if ((i - lastLong) % repeatAt === 0) {
        styles.marginRight = 0
      }
    } else if (columns === 1) {

      if (index & 1) {
        styles[weight === 'odd' ? 'margin-left' : 'margin-right'] = push
      } else {
        styles[weight === 'odd' ? 'margin-right' : 'margin-left'] = push
      }

    }

    for (var key in styles) {
      element.style[key] = styles[key] + '%'
    }
  })
}

alignAround(document.querySelectorAll('.block'), 4, 2)
html, body, .blocks {
  height: 100%;
}

.block {
  background: #e44;
  float: left;
}

/* Debug
------------------------------------------------ */
.blocks {
  counter-reset: tile;
}
.block:before {
  counter-increment: tile;
  content: counter(tile);
}
<div class="blocks">
  <div class="block"></div>
  <div class="block"></div>
  <div class="block"></div>
  <div class="block"></div>
  <div class="block"></div>
  <div class="block"></div>
  <div class="block"></div>
  <div class="block"></div>
  <div class="block"></div>
  <div class="block"></div>
  <div class="block"></div>
  <div class="block"></div>
  <div class="block"></div>
  <div class="block"></div>
  <div class="block"></div>
  <div class="block"></div>
  <div class="block"></div>
</div>

抱歉,代码未注释...