如何在CSS多列布局中插入列分隔符?

and*_*tor 7 css css3 css-multicolumn-layout

我正在尝试实施一个超级菜单.

菜单项的数量是可变的.默认情况下,它们必须以4列呈现,平衡(每列上的项目数应与其他列几乎相同).根据其内容,巨型菜单的高度也是可变的.

我用CSS多列布局实现了它.

这个代码是:

.menu {
  -webkit-column-count: 4;
     -moz-column-count: 4;
          column-count: 4;
 -webkit-column-gap: 32px;
    -moz-column-gap: 32px;
         column-gap: 32px;
}
Run Code Online (Sandbox Code Playgroud)

我的问题是有一个特殊的菜单项类型,它应该作为一个列中断.此菜单项类型是可选的,但如果存在,则应强制浏览器启动新列以显示内容(最多可以有3个列中断).

我添加了以下css代码:

.menu-item--column-break {
    display: block;
    -webkit-column-break-before: column;
              -moz-break-before: column;
                   break-before: column;
}
Run Code Online (Sandbox Code Playgroud)

但是这个CSS仅适用于Chrome:

在此输入图像描述

Firefox和Safari不支持"column-break"元素的CSS规则,并将其显示为普通菜单项: 在此输入图像描述

该菜单是在JavaScript中从JSON对象生成的,HTML可以更改,但我更喜欢CSS/JS-only解决方案.

您是否知道如何在所有浏览器中实现此功能?

这是完整的代码:

https://codepen.io/andreivictor/pen/ywLJKx

要么

let items = [
  {title: 'Category 1', type: 'menu-item'},
  {title: 'Category 2', type: 'menu-item'},
  {title: '---cb---', type: 'column-break'},
  {title: 'Category 3', type: 'menu-item'},
  {title: 'Category 4', type: 'menu-item'},
  {title: 'Category 5', type: 'menu-item'},
  {title: 'Category 6', type: 'menu-item'},
  {title: 'Category 7', type: 'menu-item'},
  {title: 'Category 8', type: 'menu-item'},
  {title: 'Category 9', type: 'menu-item'},
  {title: '---cb---', type: 'column-break'},
  {title: 'Category 10', type: 'menu-item'},
  {title: 'Category 11', type: 'menu-item'},
  {title: 'Category 12', type: 'menu-item'},
  {title: 'Category 13', type: 'menu-item'},
  {title: 'Category 14', type: 'menu-item'},
  {title: 'Category 15', type: 'menu-item'},
  {title: 'Category 16', type: 'menu-item'},
  {title: 'Category 17', type: 'menu-item'},
  {title: 'Category 18', type: 'menu-item'},
  {title: 'Category 19', type: 'menu-item'},
  {title: 'Category 20', type: 'menu-item'},
  {title: 'Category 21', type: 'menu-item'},
];

const $menu = document.querySelector('.menu');

console.log( $menu );

items.forEach((item) => {
  let nodeItem = document.createElement("div");
  nodeItem.classList.add('menu-item');
  let nodeItemText = document.createTextNode(item.title);
  nodeItem.appendChild(nodeItemText);
  if (item.type === 'column-break') {
    nodeItem.classList.add('menu-item--column-break');
  }
  $menu.appendChild(nodeItem);  
});
Run Code Online (Sandbox Code Playgroud)
.menu {
  position: relative;
  padding: 0 16px;
  -webkit-column-count: 4;
     -moz-column-count: 4;
          column-count: 4;
  -moz-column-rule: 1px solid #e2e1e1;
       column-rule: 1px solid #e2e1e1;
  -webkit-column-gap: 32px;
     -moz-column-gap: 32px;
          column-gap: 32px;
}

.menu-item--column-break {
    display: block;
    -webkit-column-break-after: column;
    -moz-break-after: column;
    break-after: column;
    color: red;
}
Run Code Online (Sandbox Code Playgroud)
<div class="container">
  <div class="menu">
  </div>
</div>
Run Code Online (Sandbox Code Playgroud)

Jak*_*lko 1

我正在思考这个问题并提出了另一个解决方案。基本上问题是不支持多列拆分,因此目前无法仅使用 css 为所有浏览器创建这些固定列和动态列。因此我决定将问题一分为二。我根据固定休息时间将项目分成几组。我假设每个组都会成为一栏,供初学者使用。然后我会看到我有多少列。如果它小于 4(您想要的列数),那么我允许最大的组动态地再分成一列。我继续此操作,直到达到 4 列的总数 - 无论是固定的、动态的,还是两者兼而有之。

请参阅下面的片段。

此外,还可以通过添加、删除或移动断点来调整剪裁。它应该适用于许多不同的场景。

let items = [
  {title: 'Category 1', type: 'menu-item'},
  {title: 'Category 2', type: 'menu-item'},
  {title: '---cb---', type: 'column-break'},
  {title: 'Category 3', type: 'menu-item'},
  {title: 'Category 4', type: 'menu-item'},
  {title: 'Category 5', type: 'menu-item'},
  {title: 'Category 6', type: 'menu-item'},
  {title: 'Category 7', type: 'menu-item'},
  {title: 'Category 8', type: 'menu-item'},
  {title: 'Category 9', type: 'menu-item'},
  {title: '---cb---', type: 'column-break'},
  {title: 'Category 10', type: 'menu-item'},
  {title: 'Category 11', type: 'menu-item'},
  {title: 'Category 12', type: 'menu-item'},
  {title: 'Category 13', type: 'menu-item'},
  {title: 'Category 14', type: 'menu-item'},
  {title: 'Category 15', type: 'menu-item'},
  //{title: '---cb---', type: 'column-break'},
  {title: 'Category 16', type: 'menu-item'},
  {title: 'Category 17', type: 'menu-item'},
  {title: 'Category 18', type: 'menu-item'},
  {title: 'Category 19', type: 'menu-item'},
  {title: 'Category 20', type: 'menu-item'},
  {title: 'Category 21', type: 'menu-item'}
];

const $menu = document.querySelector('.menu');

var allGroups = [];
var currentGroup = 0;
allGroups.push({ items: [], columns: 1});

function addGroup($menu, group, numberOfColumns){
	let columnItem = document.createElement("div");
  columnItem.classList.add('menu-group');
  if(numberOfColumns === 1){
  	columnItem.classList.add('fixed');
  } else {
  	columnItem.classList.add('dynamic-columns');
  	var style = '-webkit-column-count: ' + numberOfColumns + ';';
  	style += '-moz-column-count: ' + numberOfColumns + ';';
  	style += 'column-count: ' + numberOfColumns + ';';
  	columnItem.setAttribute('style', style);
  }
  group.forEach((groupItem) => {
  	columnItem.appendChild(groupItem);
  });
  $menu.appendChild(columnItem); 
};
var columnsCount = 1;
items.forEach((item) => {
  let nodeItem = document.createElement("div");
  allGroups[currentGroup].items.push(nodeItem);
  nodeItem.classList.add('menu-item');
  let nodeItemText = document.createTextNode(item.title);
  
  nodeItem.appendChild(nodeItemText);
  if (item.type === 'column-break') {
    nodeItem.classList.add('menu-item--column-break');
    //addGroup($menu, currentGroup, 1);
    currentGroup++;
    allGroups.push({ items: [], columns: 1});
    columnsCount++;
  }  
});

var forSorting = [];
allGroups.forEach((item) => { forSorting.push(item); });

while(columnsCount < 4){
	forSorting.sort(function(a, b){
		return (b.items.length/b.columns) - (a.items.length/a.columns);
	});
  forSorting[0].columns++;
  columnsCount++;
}

allGroups.forEach((item) => {
	addGroup($menu, item.items, item.columns);
});
Run Code Online (Sandbox Code Playgroud)
.menu {
  position: relative;
  padding: 0 16px;
  display: flex;
  flex-direction: row;
}

.menu-group:not(:last-child){
  border-right: 1px solid #e2e1e1;
  margin-right: 8px;
}

.menu-group.fixed {
  flex-basis: calc(25% - 8px);
  flex-grow: 0;
  flex-shrink: 0;
}

.menu-group.dynamic-columns {
  flex-grow: 1;
  -moz-column-rule: 1px solid #e2e1e1;
       column-rule: 1px solid #e2e1e1;
}

.menu-item--column-break {
    display: block;
    color: red;
}
Run Code Online (Sandbox Code Playgroud)
<div class="container">
  <div class="menu">
  </div>
</div>
Run Code Online (Sandbox Code Playgroud)