垂直 flexbox 溢出的水平全宽
Horizontal full width with overflow in vertical flexbox
我正在尝试创建一个 flexbox,它既可以水平滚动,也可以垂直滚动,以备不时之需。
这有点像 flexbox 中的 table 布局。
在下图中,您可以看到我正在努力实现的概念。当视口不是太小或太短时,这可以正常工作。
然后我们可以调整视口的大小。这适用于垂直溢出。出现一个滚动条,我们可以向下滚动。
遗憾的是,这在水平方向上无法正常工作。
我们还获得了水平部分的滚动条。但是黄色行(带测试)不是我需要的全宽。
const groups = [];
for (let i = 0; i < 15; i++) {
const rows = [];
for (let j = 0; j < 15; j++) {
rows.push({
cols: [
"col 1",
"col 2",
"col 3",
"col 4",
"col 5",
"col 6",
"col 7",
"col 8",
"col 9",
]
});
}
groups.push({
group: 'test' + i,
open: false,
rows
});
}
var app = new Vue({
el: '#app',
data: {
rows: groups
}
})
.container {
display: flex;
flex-direction: column;
min-height: 100vh;
min-width: 100vh;
}
.header {
position: sticky;
top: 0;
display: flex;
flex-direction: row;
}
.header .col {
flex-basis: 100px;
flex-grow: 1;
flex-shrink: 0;
background: red;
padding: 0 2px;
border: 2px solid black;
}
.vertical-content {
display: flex;
flex-direction: column;
}
.vertical-content .grouped-row {
flex-grow: 1;
background: yellow;
border: 2px solid black;
display: flex;
flex-direction: column;
}
.vertical-content .row {
display: flex;
flex-direction: row;
}
.vertical-content .row .col {
flex-basis: 100px;
flex-grow: 1;
flex-shrink: 0;
background: blue;
padding: 0 2px;
border: 2px solid black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.2.1/vue.js"></script>
<body>
<div class="container" id="app">
<div class="header">
<div class="col">Col 1</div>
<div class="col">Col 2</div>
<div class="col">Col 3</div>
<div class="col">Col 4</div>
<div class="col">Col 5</div>
<div class="col">Col 6</div>
<div class="col">Col 7</div>
<div class="col">Col 8</div>
<div class="col">Col 9</div>
</div>
<div class="vertical-content">
<div class="grouped-row" v-for="row of rows" @click="row.open = !row.open">
<div>
{{ row.group }}
</div>
<div class="row" v-for="actualRow of row.rows" v-if="row.open">
<div class="col" v-for="col of actualRow.cols">{{ col }}</div>
</div>
</div>
</div>
</div>
</body>
在 fiddle 中单击黄色条以展开包含更多内容的行。
如何使黄色条成为全角而不是部分宽度?
每个红色和蓝色单元格都有最小宽度(flex-basis
和 flex-shrink: 0
)但黄色没有。
黄色的正在使用可能的最大宽度,但其他人正在走出他们的容器。
在这种情况下,“修复”它的最简单方法是也为黄色条设置最小宽度。
一个小例子(带有变量以简化可维护性)
差异:
:root {
--nb-cells: 9;
--cell-width: 100px;
}
.container {
box-sizing: border-box;
}
.header .col,
.vertical-content .row .col {
box-sizing: border-box;
flex-basis: var(--cell-width);
}
.vertical-content .grouped-row {
box-sizing: border-box;
min-width: calc(var(--cell-width) * var(--nb-cells));
}
全面测试
const groups = [];
for (let i = 0; i < 15; i++) {
const rows = [];
for (let j = 0; j < 15; j++) {
rows.push({
cols: [
"col 1",
"col 2",
"col 3",
"col 4",
"col 5",
"col 6",
"col 7",
"col 8",
"col 9",
]
});
}
groups.push({
group: 'test' + i,
open: false,
rows
});
}
var app = new Vue({
el: '#app',
data: {
rows: groups
}
})
:root {
--nb-cells: 9;
--cell-width: 100px;
}
.container {
display: flex;
flex-direction: column;
min-height: 100vh;
min-width: 100vh;
box-sizing: border-box;
}
.header {
position: sticky;
top: 0;
display: flex;
flex-direction: row;
}
.header .col {
flex-basis: var(--cell-width);
flex-grow: 1;
flex-shrink: 0;
background: red;
padding: 0 2px;
border: 2px solid black;
box-sizing: border-box;
}
.vertical-content {
display: flex;
flex-direction: column;
}
.vertical-content .grouped-row {
flex-grow: 1;
background: yellow;
border: 2px solid black;
display: flex;
flex-direction: column;
min-width: calc(var(--cell-width) * var(--nb-cells));
box-sizing: border-box;
}
.vertical-content .row {
display: flex;
flex-direction: row;
}
.vertical-content .row .col {
flex-basis: var(--cell-width);
flex-grow: 1;
flex-shrink: 0;
background: blue;
padding: 0 2px;
border: 2px solid black;
box-sizing: border-box;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.2.1/vue.js"></script>
<body>
<div class="container" id="app">
<div class="header">
<div class="col">Col 1</div>
<div class="col">Col 2</div>
<div class="col">Col 3</div>
<div class="col">Col 4</div>
<div class="col">Col 5</div>
<div class="col">Col 6</div>
<div class="col">Col 7</div>
<div class="col">Col 8</div>
<div class="col">Col 9</div>
</div>
<div class="vertical-content">
<div class="grouped-row" v-for="row of rows" @click="row.open = !row.open">
<div>
{{ row.group }}
</div>
<div class="row" v-for="actualRow of row.rows" v-if="row.open">
<div class="col" v-for="col of actualRow.cols">{{ col }}</div>
</div>
</div>
</div>
</div>
</body>
几个问题:
- 您需要为
min-width
使用 view-width(vw
)。将 min-width: 100vh;
更改为 min-width: 100vw;
。仅此一项并不能解决问题。
- 主要问题是因为
.header
溢出了。您可以通过向其添加粗边框和 .container
元素来检查这一点。我们可以使用两个更改来解决此问题:
.container {
...
width: max-content;
}
.header .col {
...
width: 100px;
}
演示:
const groups = [];
for (let i = 0; i < 15; i++) {
const rows = [];
for (let j = 0; j < 15; j++) {
rows.push({ cols: ["col 1", "col 2", "col 3", "col 4", "col 5", "col 6", "col 7", "col 8", "col 9" ] });
}
groups.push({ group: 'test' + i, open: false, rows});
}
var app = new Vue({el: '#app', data: { rows: groups } })
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.container {
display: flex;
flex-direction: column;
min-height: 100vh;
min-width: 100vw;
width: max-content;
}
.header {
position: sticky;
top: 0;
display: flex;
flex-direction: row;
}
.header .col {
flex-basis: 100px;
flex-grow: 1;
flex-shrink: 0;
background: rgb(250, 189, 189);
padding: 0 2px;
outline: 2px solid black;
width: 100px;
}
.vertical-content {
display: flex;
flex-direction: column;
}
.vertical-content .grouped-row {
flex-grow: 1;
background: rgb(251, 251, 180);
outline: 2px solid black;
display: flex;
flex-direction: column;
}
.vertical-content .row {
display: flex;
flex-direction: row;
width: 100%;
}
.vertical-content .row .col {
flex-basis: 100px;
flex-grow: 1;
flex-shrink: 0;
background: rgb(150, 150, 238);
padding: 0 2px;
outline: 2px solid black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.2.1/vue.js"></script>
<body>
<div class="container" id="app">
<div class="header">
<div class="col">Col 1</div>
<div class="col">Col 2</div>
<div class="col">Col 3</div>
<div class="col">Col 4</div>
<div class="col">Col 5</div>
<div class="col">Col 6</div>
<div class="col">Col 7</div>
<div class="col">Col 8</div>
<div class="col">Col 9</div>
</div>
<div class="vertical-content">
<div class="grouped-row" v-for="row of rows" @click="row.open = !row.open">
<div>
{{ row.group }}
</div>
<div class="row" v-for="actualRow of row.rows" v-if="row.open">
<div class="col" v-for="col of actualRow.cols">{{ col }}</div>
</div>
</div>
</div>
</div>
我正在尝试创建一个 flexbox,它既可以水平滚动,也可以垂直滚动,以备不时之需。
这有点像 flexbox 中的 table 布局。
在下图中,您可以看到我正在努力实现的概念。当视口不是太小或太短时,这可以正常工作。
然后我们可以调整视口的大小。这适用于垂直溢出。出现一个滚动条,我们可以向下滚动。 遗憾的是,这在水平方向上无法正常工作。 我们还获得了水平部分的滚动条。但是黄色行(带测试)不是我需要的全宽。
const groups = [];
for (let i = 0; i < 15; i++) {
const rows = [];
for (let j = 0; j < 15; j++) {
rows.push({
cols: [
"col 1",
"col 2",
"col 3",
"col 4",
"col 5",
"col 6",
"col 7",
"col 8",
"col 9",
]
});
}
groups.push({
group: 'test' + i,
open: false,
rows
});
}
var app = new Vue({
el: '#app',
data: {
rows: groups
}
})
.container {
display: flex;
flex-direction: column;
min-height: 100vh;
min-width: 100vh;
}
.header {
position: sticky;
top: 0;
display: flex;
flex-direction: row;
}
.header .col {
flex-basis: 100px;
flex-grow: 1;
flex-shrink: 0;
background: red;
padding: 0 2px;
border: 2px solid black;
}
.vertical-content {
display: flex;
flex-direction: column;
}
.vertical-content .grouped-row {
flex-grow: 1;
background: yellow;
border: 2px solid black;
display: flex;
flex-direction: column;
}
.vertical-content .row {
display: flex;
flex-direction: row;
}
.vertical-content .row .col {
flex-basis: 100px;
flex-grow: 1;
flex-shrink: 0;
background: blue;
padding: 0 2px;
border: 2px solid black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.2.1/vue.js"></script>
<body>
<div class="container" id="app">
<div class="header">
<div class="col">Col 1</div>
<div class="col">Col 2</div>
<div class="col">Col 3</div>
<div class="col">Col 4</div>
<div class="col">Col 5</div>
<div class="col">Col 6</div>
<div class="col">Col 7</div>
<div class="col">Col 8</div>
<div class="col">Col 9</div>
</div>
<div class="vertical-content">
<div class="grouped-row" v-for="row of rows" @click="row.open = !row.open">
<div>
{{ row.group }}
</div>
<div class="row" v-for="actualRow of row.rows" v-if="row.open">
<div class="col" v-for="col of actualRow.cols">{{ col }}</div>
</div>
</div>
</div>
</div>
</body>
在 fiddle 中单击黄色条以展开包含更多内容的行。
如何使黄色条成为全角而不是部分宽度?
每个红色和蓝色单元格都有最小宽度(flex-basis
和 flex-shrink: 0
)但黄色没有。
黄色的正在使用可能的最大宽度,但其他人正在走出他们的容器。
在这种情况下,“修复”它的最简单方法是也为黄色条设置最小宽度。
一个小例子(带有变量以简化可维护性)
差异:
:root {
--nb-cells: 9;
--cell-width: 100px;
}
.container {
box-sizing: border-box;
}
.header .col,
.vertical-content .row .col {
box-sizing: border-box;
flex-basis: var(--cell-width);
}
.vertical-content .grouped-row {
box-sizing: border-box;
min-width: calc(var(--cell-width) * var(--nb-cells));
}
全面测试
const groups = [];
for (let i = 0; i < 15; i++) {
const rows = [];
for (let j = 0; j < 15; j++) {
rows.push({
cols: [
"col 1",
"col 2",
"col 3",
"col 4",
"col 5",
"col 6",
"col 7",
"col 8",
"col 9",
]
});
}
groups.push({
group: 'test' + i,
open: false,
rows
});
}
var app = new Vue({
el: '#app',
data: {
rows: groups
}
})
:root {
--nb-cells: 9;
--cell-width: 100px;
}
.container {
display: flex;
flex-direction: column;
min-height: 100vh;
min-width: 100vh;
box-sizing: border-box;
}
.header {
position: sticky;
top: 0;
display: flex;
flex-direction: row;
}
.header .col {
flex-basis: var(--cell-width);
flex-grow: 1;
flex-shrink: 0;
background: red;
padding: 0 2px;
border: 2px solid black;
box-sizing: border-box;
}
.vertical-content {
display: flex;
flex-direction: column;
}
.vertical-content .grouped-row {
flex-grow: 1;
background: yellow;
border: 2px solid black;
display: flex;
flex-direction: column;
min-width: calc(var(--cell-width) * var(--nb-cells));
box-sizing: border-box;
}
.vertical-content .row {
display: flex;
flex-direction: row;
}
.vertical-content .row .col {
flex-basis: var(--cell-width);
flex-grow: 1;
flex-shrink: 0;
background: blue;
padding: 0 2px;
border: 2px solid black;
box-sizing: border-box;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.2.1/vue.js"></script>
<body>
<div class="container" id="app">
<div class="header">
<div class="col">Col 1</div>
<div class="col">Col 2</div>
<div class="col">Col 3</div>
<div class="col">Col 4</div>
<div class="col">Col 5</div>
<div class="col">Col 6</div>
<div class="col">Col 7</div>
<div class="col">Col 8</div>
<div class="col">Col 9</div>
</div>
<div class="vertical-content">
<div class="grouped-row" v-for="row of rows" @click="row.open = !row.open">
<div>
{{ row.group }}
</div>
<div class="row" v-for="actualRow of row.rows" v-if="row.open">
<div class="col" v-for="col of actualRow.cols">{{ col }}</div>
</div>
</div>
</div>
</div>
</body>
几个问题:
- 您需要为
min-width
使用 view-width(vw
)。将min-width: 100vh;
更改为min-width: 100vw;
。仅此一项并不能解决问题。 - 主要问题是因为
.header
溢出了。您可以通过向其添加粗边框和.container
元素来检查这一点。我们可以使用两个更改来解决此问题:
.container {
...
width: max-content;
}
.header .col {
...
width: 100px;
}
演示:
const groups = [];
for (let i = 0; i < 15; i++) {
const rows = [];
for (let j = 0; j < 15; j++) {
rows.push({ cols: ["col 1", "col 2", "col 3", "col 4", "col 5", "col 6", "col 7", "col 8", "col 9" ] });
}
groups.push({ group: 'test' + i, open: false, rows});
}
var app = new Vue({el: '#app', data: { rows: groups } })
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.container {
display: flex;
flex-direction: column;
min-height: 100vh;
min-width: 100vw;
width: max-content;
}
.header {
position: sticky;
top: 0;
display: flex;
flex-direction: row;
}
.header .col {
flex-basis: 100px;
flex-grow: 1;
flex-shrink: 0;
background: rgb(250, 189, 189);
padding: 0 2px;
outline: 2px solid black;
width: 100px;
}
.vertical-content {
display: flex;
flex-direction: column;
}
.vertical-content .grouped-row {
flex-grow: 1;
background: rgb(251, 251, 180);
outline: 2px solid black;
display: flex;
flex-direction: column;
}
.vertical-content .row {
display: flex;
flex-direction: row;
width: 100%;
}
.vertical-content .row .col {
flex-basis: 100px;
flex-grow: 1;
flex-shrink: 0;
background: rgb(150, 150, 238);
padding: 0 2px;
outline: 2px solid black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.2.1/vue.js"></script>
<body>
<div class="container" id="app">
<div class="header">
<div class="col">Col 1</div>
<div class="col">Col 2</div>
<div class="col">Col 3</div>
<div class="col">Col 4</div>
<div class="col">Col 5</div>
<div class="col">Col 6</div>
<div class="col">Col 7</div>
<div class="col">Col 8</div>
<div class="col">Col 9</div>
</div>
<div class="vertical-content">
<div class="grouped-row" v-for="row of rows" @click="row.open = !row.open">
<div>
{{ row.group }}
</div>
<div class="row" v-for="actualRow of row.rows" v-if="row.open">
<div class="col" v-for="col of actualRow.cols">{{ col }}</div>
</div>
</div>
</div>
</div>