例
指定列的宽度和数量:
div{columns:100px3; -webkit-columns:100px3; /* Safari and Chrome */ -moz-columns:100px3; /* Firefox */}
浏览器支持
表格中的数字表示支持该属性的第一个浏览器版本号。
紧跟在 -webkit-, -ms- 或 -moz- 前的数字为支持该前缀属性的第一个浏览器版本号。
属性 | |||||
---|---|---|---|---|---|
columns | 50.04.0 -webkit- | 10.0 | 9.0 -moz- | 9.03.1 -webkit- | 37.015.0 -webkit-11.1 |
属性定义及使用说明
Columns属性是一个速记属性设置列宽和列数。
默认值: | auto auto |
---|---|
继承: | no |
版本: | CSS3 |
JavaScript 语法: | object.style.columns="100px 3" |
语法
columns: column-width column-count;
值 | 描述 |
---|---|
column-width | 列的宽度 |
column-count | 列数 |
Column-count
div元素的文本分成三列。
Column-gap
在div元素的文本分成三列,并指定一个30像素的列之间的差距。
Column-rule
指定列之间的规则:宽度,样式和颜色。
如您还有不明白的可以在下面与我留言或是与我探讨QQ群308855039,我们一起飞!
家好,我是前端西瓜哥。
之前因为工作上的一些原因,使用的 wangEditor 富文本编辑器的表格(table)功能并不能满足需求,创建的表格只是设置了 width: 100%,列的宽度的自适应的效果非常不美观。于是决定修改源码,对表格功能做了加强,使其支持调整列宽。
为了方便读者理解,最近把这部分逻辑单独抽离出来并做了优化,写了个能独立运行的 demo,配合这篇文章简单说一说实现思路。
第一步是创建空表格。要想支持表格可以设置宽度,需要在 table 元素下使用 colgroup 元素。我们根据表格列的数量,在 colgroup 下创建同等数量的 col 元素并设置宽度,就能给对应顺序的列赋予宽度。效果可以查看这个 在线demo 。
此外,表格的单元格如果没有内容,是会发生高度塌陷的,且无法通过 min-height 和 height 设置高度 。为解决这个问题,我们通常会在创建空表格时,给单元格添加 <br /> 内容。
第二步是实现光标划到列之间的分割线上方时,将高亮线显现出来。实现方式是:
前面提到,当光标悬浮在列分割线上方附近,会出现高亮线。其实为实现修改列宽,我们还要记录一些数据:(1)对应的表格元素;(2)第几列 rowIdx。当然光标移开时,要把这些数据清空。
下面是拖拽这一动作的实现,涉及到鼠标按下、鼠标移动、鼠标释放三个事件:
因为只需要得到拖拽的相对位置,所以我们不是必须要将事件绑定到编辑器容器上。另外为了确保鼠标释放事件正在发生,最终我选择在 document 元素上绑定事件。document 元素上绑定的鼠标释放事件,按下鼠标后,即便在浏览器外面释放鼠标,也能触发。
另外,为处理列宽过小,甚至计算出负值的情况,我们需要设置一个最小列宽。
那么这里就简单讲解一下核心代码。
首先是创建空表格:
const DEFAULT_COL_WIDTH = 80
const DEFAULT_COL_SIZE = 5
const DEFAULT_ROW_SIZE = 5
// 生成空 table
function createTable(row = DEFAULT_ROW_SIZE, col = DEFAULT_COL_SIZE, hasTh = false, colWidth = DEFAULT_COL_WIDTH) {
const tbody = document.createElement('tbody')
let tr, td
for (let i = 0; i < row; i++) {
tr = document.createElement('tr')
tbody.appendChild(tr)
for (let j = 0; j < col; j++) {
td = document.createElement((i === 0 && hasTh) ? 'th' : 'td')
td.innerHTML = '<br />' // 填充点东西,处理单元格高度塌陷问题
tr.appendChild(td)
}
}
const colgroup = document.createElement('colgroup')
let colElm
for (let i = 0; i < col; i++) {
colElm = document.createElement('col')
colElm.style.width = colWidth + 'px'
colgroup.appendChild(colElm)
}
const table = document.createElement('table')
table.appendChild(colgroup)
table.appendChild(tbody)
return table
}
显现高亮线的核心实现逻辑如下。计算左偏移量使用了 getBoundingClientRect() 方法和鼠标事件中得到的 clientX 坐标。其中还需要注意坐标系有 “相对表格” 和 “相对编辑器容器” 两种。
const hl = new HL(editorEl) // 高亮线对象
// ...
let lastState = {} // 高亮线出现时,记录对应的 tableEl 和 rowIdx
function handleMovemove(event) {
// 找到最近的table父元素
const nearestTable = getNearestTable(event.target, editorEl)
if (!nearestTable) {
hl.hideHL()
lastState = {}
return
}
const tableLeftByViewport = nearestTable.getBoundingClientRect().left
const cursorLeftByTable = event.clientX - tableLeftByViewport
const tableLeftByEditor = tableLeftByViewport - editorEl.getBoundingClientRect().left
//accurateLeft 为精准的列分割线上的左偏移量
const { idx: rowIdx, left: accurateLeft } = getNearestRowBorder(nearestTable, cursorLeftByTable)
if (rowIdx !== -1) {
hl.drawHL(nearestTable, tableLeftByEditor + accurateLeft) // 转换为相对 editor 容器的左偏移量
lastState = { tableEl: nearestTable, rowIdx } // 保存 table 元素和 列索引,鼠标按下时要用到。
editorEl.style.cursor = 'col-resize'
} else {
hl.hideHL()
lastState = {}
}
}
然后是拖拽的逻辑。dragState.tableEl 除了记录保存当前表格元素,还在 moveover 事件中做是否触发拖拽的标识。
// 拖拽过程中保存的变量
const emptyDragState = {
tableEl: undefined,
rowIdx: undefined,
col: null,
width: undefined,
left: undefined,
}
let dragState = {...emptyDragState}
function dragMouseDown(event) {
// TODO: 需要点左键才执行
const { tableEl, rowIdx } = lastState
if (!tableEl) return
const col = getCol(tableEl, rowIdx)
const width = parseFloat(col.style.width)
const left = event.clientX
dragState = { ...dragState, ...lastState, col, width, left }
}
function dragMouseover(event) {
const { left, tableEl, width, rowIdx } = dragState
if (!tableEl) return
const offset = event.clientX - left
setColWidth(tableEl, rowIdx, width + offset)
}
function dragMouseup() {
dragState = {...emptyDragState}
}
俗话说的好,“Talk is cheap, show me your code!”。如果你对里面的实现细节感兴趣的话,请去我的在线 demo 阅读源码和测试:
https://codepen.io/F-star/pen/eYWjKBg?editors=1010
篇系统介绍了flex的语法及基本知识,如果您还不熟悉flex知识,点击这里先看看《 前端入门——弹性布局(Flex)》。本篇将结合flex基本知识去实现常见的网页布局效果,常见的经典网页布局有:
上下结构
html:
<main>
<header>header</header>
<section>content</section>
</main>
css:
main{
width:100%;
height:100vh;
display:flex;
flex-direction: column;
}
main > header{
height: 100px;
background: #cdf0fd;
}
main > section{
flex-grow:1;
}
左右结构
html:
<main>
<nav>left nav</nav>
<section>content</section>
</main>
css:
main{
width:100%;
height:100vh;
display:flex;
}
main > nav{
width:150px;
background: #cdf0fd;
}
main > section{
flex-grow:1;
}
上中下结构
html:
<main>
<header>header</header>
<section>content</section>
<footer>footer</footer>
</main>
css:
main{
width:100%;
height:100vh;
display:flex;
flex-direction: column;
}
main > header,
main > footer{
height: 100px;
background: #cdf0fd;
}
main > section{
flex-grow:1;
}
左中右结构
html:
<main>
<nav>left nav</nav>
<section>content</section>
<aside>right aside</aside>
</main>
css:
main{
width:100%;
height:100vh;
display:flex;
}
main > nav,
main > aside{
width:150px;
background: #cdf0fd;
}
main > section{
flex-grow:1;
}
1、上中下结构里,中间区域嵌套左中右结构
圣杯布局1
html:
<main>
<header>header</header>
<section>
<!--嵌套左中右结构-->
<nav>left nav</nav>
<section>content</section>
<aside>right aside</aside>
</section>
<footer>footer</footer>
</main>
css:
main{
width:100%;
height:100vh;
display:flex;
flex-direction: column;
}
main > header,
main > footer{
height: 100px;
background: #cdf0fd;
}
main > section{
flex-grow:1;
display:flex;
}
/*嵌套的左中右结构*/
main > section > nav,
main > section > aside{
width:150px;
background: #fdcdcd;
}
main > section > section{
width:100%;
flex-grow:1;
}
2、左中右结构里,中间区域嵌套上中下结构
圣杯布局2
html:
<main>
<nav>left nav</nav>
<section>
<!--嵌套上中下结构-->
<header>header</header>
<section>content</section>
<footer>footer</footer>
</section>
<aside>right aside</aside>
</main>
css:
main{
width:100%;
height:100vh;
display:flex;
}
main > nav,
main > aside{
width:150px;
background: #cdf0fd;
}
main > section{
flex-grow:1;
width:100%;
display:flex;
flex-direction: column;
}
/*嵌套的上中下结构*/
main > section > header,
main > section > footer{
height: 100px;
background: #fdcdcd;
}
main > section > section{
flex-grow:1;
}
9宫格
html:
<main>
<section>content 1 </section>
<section>content 2 </section>
<section>content 3 </section>
<section>content 4 </section>
<section>content 5 </section>
<section>content 6 </section>
<section>content 7 </section>
<section>content 8 </section>
<section>content 9 </section>
</main>
css:
main{
width:100%;
height:100vh;
display:flex;
flex-wrap: wrap;
}
main > section{
width: 30%;
background:#55ff00;
margin: 1.5%;
}
以上是常见的经典布局,在这些布局的基础上可以组合、拆分制作各种各样的布局,如果结合position:fixed定位还可以实现头部或侧边栏固定的布局效果。
以上布局使用传统的float、position也可以实现,只是相对来说比较麻烦一些,已不建议使用,所以了解下就可以了。
虽然flex可以满足大部分布局,但是flex并不擅长栅格布局,后面会介绍display:grid(网格布局),网格是一组相交的水平线和垂直线,它定义了网格的列和行。所以使用网格布局能够构建更加复杂的网页设计。
感谢关注,希望能够给你有所帮助,欢迎提出错误,补充。
上篇:前端入门——弹性布局(Flex)
下篇:前端入门 —— 网格布局(Grid)
源码链接: https://pan.baidu.com/s/1bdZM8ZcdU3FdSCp2u0sx8A?pwd=9ub2
提取码: 9ub2
*请认真填写需求信息,我们会在24小时内与您取得联系。