Flex 子项在非常小的宽度上消失
Posted
技术标签:
【中文标题】Flex 子项在非常小的宽度上消失【英文标题】:Flex child item disappear on very small widths 【发布时间】:2019-09-13 04:35:30 【问题描述】:我正在使用 ReactJS 构建一个调整大小的组件。代码如下:
class Cell extends React.Component
handleMouseDown = event =>
this.props.onMouseDown(this.props.index, event);
;
render()
let verticalGrip = ( <
div onMouseDown =
this.handleMouseDown
className = "cell-vertical-grip" / >
);
return ( <
div className = "cell-container"
style =
width: this.props.widths[this.props.index]
>
<
div className = "cell-content"
style =
border: "10px solid transparent"
>
"WIDTH " + this.props.widths[this.props.index]
<
/div>
verticalGrip
<
/div>
);
class Test extends React.Component
state =
widths: [100, 100, 100, 100],
baseWidths: [100, 100, 100, 100],
xBase: 0,
resizeIndex: null
;
handleMouseDown = (index, event) =>
console.log("MouseDown: index: " + index + ", pageX: " + event.pageX);
this.setState(
xBase: event.pageX,
resizing: true,
resizeIndex: index
);
;
handleMouseMove = event =>
if (this.state.resizing)
let delta = this.state.xBase - event.pageX;
console.log("MouseMove " + delta);
let widths = this.state.widths.slice();
widths[this.state.resizeIndex] = this.state.baseWidths[this.state.resizeIndex] - delta;
this.setState(
widths: widths
);
;
handleMouseUp = event =>
console.log("MouseUp");
this.setState(
resizing: false,
resizeIndex: null
);
;
render()
return ( <
div className = "test-container"
onMouseMove =
this.handleMouseMove
onMouseUp =
this.handleMouseUp
>
<
Cell widths =
this.state.widths
onMouseDown =
this.handleMouseDown
index =
0
/> <
Cell widths =
this.state.widths
onMouseDown =
this.handleMouseDown
index =
1
/> <
Cell widths =
this.state.widths
onMouseDown =
this.handleMouseDown
index =
2
/> <
Cell widths =
this.state.widths
onMouseDown =
this.handleMouseDown
index =
3
/> <
/div>
);
// Render it
ReactDOM.render( <
Test / > ,
document.body
);
.test-container
width: 100vw;
height: 100vh;
display: flex;
flex-direction: row;
background-color: cyan;
.cell-container
width: 100%;
height: 100px;
display: flex;
flex-direction: row;
background-color: grey;
border: 1px solid black;
overflow-y: hidden;
overflow-x: hidden;
.cell-content
align-self: center;
flex-shrink: 1;
font-size: 12px;
overflow-y: hidden;
overflow-x: hidden;
background-color: white;
.cell-vertical-grip
flex-shrink: 0;
margin-left: auto;
width: 3px;
min-width: 3px;
cursor: ew-resize;
background-color: blue;
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
verticalGrip
是您抓取要调整大小的列的位置。
一切正常,但是当我将任何列的宽度调整为小于20px
时,就会出现我的问题。在那种情况下,我的蓝色手柄(verticalGrip
item)就消失了。因此,如果我在该位置释放鼠标,我将无法再次展开该列,因为没有抓握(它已消失)。
换句话说,如果他出于某种原因需要缩小一列,他不能再次增长它,因为没有抓地力。
如何让我的夹点在所有可能的宽度上都可见,允许用户在任何情况下调整列的大小?
【问题讨论】:
这是因为您要添加到元素的 10px 边框 (2x10px = 20px) 【参考方案1】:一个想法是使您的元素在右侧具有粘性,并且由于您应用到元素的边框而导致溢出时它不会消失。
class Cell extends React.Component
handleMouseDown = event =>
this.props.onMouseDown(this.props.index, event);
;
render()
let verticalGrip = ( <
div onMouseDown =
this.handleMouseDown
className = "cell-vertical-grip" / >
);
return ( <
div className = "cell-container"
style =
width: this.props.widths[this.props.index]
>
<
div className = "cell-content"
style =
border: "10px solid transparent"
>
"WIDTH " + this.props.widths[this.props.index]
<
/div>
verticalGrip
<
/div>
);
class Test extends React.Component
state =
widths: [100, 100, 100, 100],
baseWidths: [100, 100, 100, 100],
xBase: 0,
resizeIndex: null
;
handleMouseDown = (index, event) =>
console.log("MouseDown: index: " + index + ", pageX: " + event.pageX);
this.setState(
xBase: event.pageX,
resizing: true,
resizeIndex: index
);
;
handleMouseMove = event =>
if (this.state.resizing)
let delta = this.state.xBase - event.pageX;
console.log("MouseMove " + delta);
let widths = this.state.widths.slice();
widths[this.state.resizeIndex] = this.state.baseWidths[this.state.resizeIndex] - delta;
this.setState(
widths: widths
);
;
handleMouseUp = event =>
console.log("MouseUp");
this.setState(
resizing: false,
resizeIndex: null
);
;
render()
return ( <
div className = "test-container"
onMouseMove =
this.handleMouseMove
onMouseUp =
this.handleMouseUp
>
<
Cell widths =
this.state.widths
onMouseDown =
this.handleMouseDown
index =
0
/> <
Cell widths =
this.state.widths
onMouseDown =
this.handleMouseDown
index =
1
/> <
Cell widths =
this.state.widths
onMouseDown =
this.handleMouseDown
index =
2
/> <
Cell widths =
this.state.widths
onMouseDown =
this.handleMouseDown
index =
3
/> <
/div>
);
// Render it
ReactDOM.render( <
Test / > ,
document.body
);
.test-container
width: 100vw;
height: 100vh;
display: flex;
flex-direction: row;
background-color: cyan;
.cell-container
width: 100%;
height: 100px;
display: flex;
flex-direction: row;
background-color: grey;
border: 1px solid black;
overflow-y: hidden;
overflow-x: hidden;
.cell-content
align-self: center;
flex-shrink: 1;
font-size: 12px;
overflow-y: hidden;
overflow-x: hidden;
background-color: white;
.cell-vertical-grip
flex-shrink: 0;
margin-left: auto;
width: 3px;
min-width: 3px;
cursor: ew-resize;
background-color: blue;
position:sticky;
right:0;
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
或者您可以考虑另一种想法,而不是像轮廓或框阴影这样不会影响元素宽度的边框,并且您将获得相同的视觉输出:
class Cell extends React.Component
handleMouseDown = event =>
this.props.onMouseDown(this.props.index, event);
;
render()
let verticalGrip = ( <
div onMouseDown =
this.handleMouseDown
className = "cell-vertical-grip" / >
);
return ( <
div className = "cell-container"
style =
width: this.props.widths[this.props.index]
>
<
div className = "cell-content"
style =
outline: "10px solid #fff"
>
"WIDTH " + this.props.widths[this.props.index]
<
/div>
verticalGrip
<
/div>
);
class Test extends React.Component
state =
widths: [100, 100, 100, 100],
baseWidths: [100, 100, 100, 100],
xBase: 0,
resizeIndex: null
;
handleMouseDown = (index, event) =>
console.log("MouseDown: index: " + index + ", pageX: " + event.pageX);
this.setState(
xBase: event.pageX,
resizing: true,
resizeIndex: index
);
;
handleMouseMove = event =>
if (this.state.resizing)
let delta = this.state.xBase - event.pageX;
console.log("MouseMove " + delta);
let widths = this.state.widths.slice();
widths[this.state.resizeIndex] = this.state.baseWidths[this.state.resizeIndex] - delta;
this.setState(
widths: widths
);
;
handleMouseUp = event =>
console.log("MouseUp");
this.setState(
resizing: false,
resizeIndex: null
);
;
render()
return ( <
div className = "test-container"
onMouseMove =
this.handleMouseMove
onMouseUp =
this.handleMouseUp
>
<
Cell widths =
this.state.widths
onMouseDown =
this.handleMouseDown
index =
0
/> <
Cell widths =
this.state.widths
onMouseDown =
this.handleMouseDown
index =
1
/> <
Cell widths =
this.state.widths
onMouseDown =
this.handleMouseDown
index =
2
/> <
Cell widths =
this.state.widths
onMouseDown =
this.handleMouseDown
index =
3
/> <
/div>
);
// Render it
ReactDOM.render( <
Test / > ,
document.body
);
.test-container
width: 100vw;
height: 100vh;
display: flex;
flex-direction: row;
background-color: cyan;
.cell-container
width: 100%;
height: 100px;
display: flex;
flex-direction: row;
background-color: grey;
border: 1px solid black;
overflow-y: hidden;
overflow-x: hidden;
/*to push the element so we can see the outline*/
.cell-container:before
content:"";
width:10px;
.cell-content
align-self: center;
flex-shrink: 1;
font-size: 12px;
overflow-y: hidden;
overflow-x: hidden;
background-color: white;
.cell-vertical-grip
flex-shrink: 0;
margin-left: auto;
width: 3px;
min-width: 3px;
cursor: ew-resize;
background-color: blue;
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
【讨论】:
谢谢。position: sticky
拯救了我的一天。
@Mendes 添加了另一种方式 ;)【参考方案2】:
一个简单的解决方案可能是稍微修改您的 CSS,以便您的抓取器元素使用 absolute
定位,对齐并调整大小到父 .cell-container
的右边缘和高度:
.cell-vertical-grip
/* Add this */
position:absolute;
top:0;
height:100%;
right:0;
您还可以明确设置 .cell-container
的 min-width
以匹配夹具宽度,以便在容器完全折叠时仍然可见:
.cell-container
/* Add this */
min-width:3px;
position:relative;
我已使用以下 sn-p 中的这些更改更新了您的代码:
class Cell extends React.Component
handleMouseDown = event =>
this.props.onMouseDown(this.props.index, event);
;
render()
let verticalGrip = ( <
div onMouseDown =
this.handleMouseDown
className = "cell-vertical-grip" / >
);
return ( <
div className = "cell-container"
style =
width: this.props.widths[this.props.index]
>
<
div className = "cell-content"
style =
border: "10px solid transparent"
>
"WIDTH " + this.props.widths[this.props.index]
<
/div>
verticalGrip
<
/div>
);
class Test extends React.Component
state =
widths: [100, 100, 100, 100],
baseWidths: [100, 100, 100, 100],
xBase: 0,
resizeIndex: null
;
handleMouseDown = (index, event) =>
console.log("MouseDown: index: " + index + ", pageX: " + event.pageX);
this.setState(
xBase: event.pageX,
resizing: true,
resizeIndex: index
);
;
handleMouseMove = event =>
if (this.state.resizing)
let delta = this.state.xBase - event.pageX;
console.log("MouseMove " + delta);
let widths = this.state.widths.slice();
widths[this.state.resizeIndex] = this.state.baseWidths[this.state.resizeIndex] - delta;
this.setState(
widths: widths
);
;
handleMouseUp = event =>
console.log("MouseUp");
this.setState(
resizing: false,
resizeIndex: null
);
;
render()
return ( <
div className = "test-container"
onMouseMove =
this.handleMouseMove
onMouseUp =
this.handleMouseUp
>
<
Cell widths =
this.state.widths
onMouseDown =
this.handleMouseDown
index =
0
/> <
Cell widths =
this.state.widths
onMouseDown =
this.handleMouseDown
index =
1
/> <
Cell widths =
this.state.widths
onMouseDown =
this.handleMouseDown
index =
2
/> <
Cell widths =
this.state.widths
onMouseDown =
this.handleMouseDown
index =
3
/> <
/div>
);
// Render it
ReactDOM.render( <
Test / > ,
document.body
);
.test-container
width: 100vw;
height: 100vh;
display: flex;
flex-direction: row;
background-color: cyan;
.cell-container
width: 100%;
height: 100px;
display: flex;
flex-direction: row;
background-color: grey;
border: 1px solid black;
overflow-y: hidden;
overflow-x: hidden;
/* Add this */
min-width:3px;
position:relative;
.cell-content
align-self: center;
flex-shrink: 1;
font-size: 12px;
overflow-y: hidden;
overflow-x: hidden;
background-color: white;
.cell-vertical-grip
flex-shrink: 0;
margin-left: auto;
width: 3px;
min-width: 3px;
cursor: ew-resize;
background-color: blue;
/* Add this */
position:absolute;
top:0;
height:100%;
right:0;
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
【讨论】:
以上是关于Flex 子项在非常小的宽度上消失的主要内容,如果未能解决你的问题,请参考以下文章
Flex-grow 没有按预期工作(弹性项目没有我期望的宽度)