英文:
How to make a flex-grow element take up the space of a hidden flex item?
问题
我希望整个窗口分成两个或三个区域 - 取决于复选框的状态。如果未选中复选框,我希望第二个区域被隐藏,同时我希望第一个区域扩展到这个额外的窗口空间。
对于较大的屏幕(>640px),设置完美正常运行:
选中复选框大屏幕 和 未选中复选框大屏幕
然而,对于较小的屏幕,我遇到了问题。在这里,第二个区域位于区域1和3之间:
选中复选框小屏幕
但是一旦取消选中复选框,区域1保持不变,不会扩展到隐藏区域2的空间。相反,区域3向上移动并在现在可用的空间中居中(灰色背景):
未选中复选框小屏幕
我认为我知道为什么会发生这种情况,但尚未能提出解决方案。
由于我为包装器使用了 flex-direction: column
,所以 flex-grow: 1
仅在水平方向上对子元素起作用。
因此,我首先尝试使用 flex-direction: row
,但这会使元素水平排列在一起。即使我尝试将包装器限制在视口宽度范围内并使用 flex-wrap: wrap
,仍然会出现这种情况。
区域3上下的灰色空间似乎是隐藏区域2的 height:20%
的结果。虽然我认为使用 display:none
应该完全阻止考虑这个高度,但似乎并非如此。
因此,我其次尝试使用Javascript,只有在未选中复选框且屏幕大小低于阈值时,才将隐藏区域2的 height:20%
更改为0%。但是在开发工具中,看起来 document.getElementById("hint").style.height="0%"
没有改变任何东西。但即使它改变了,直接在css中将高度设置为0%似乎不会解决我的问题,因为灰色包装器区域仍然存在。
这是我尝试创建的一个可复制的示例,但我不确定它是否足够简化并且有帮助:
<!-- begin snippet: js hide: true console: true babel: false -->
<!-- language: lang-js -->
function visCheck() {
if (document.getElementById("hint").style.display == "block") {
document.getElementById("hint").style.display = "none";
} else if (document.getElementById("hint").style.display == "none") {
document.getElementById("hint").style.display = "block";
} else {
document.getElementById("hint").style.display = "block";
}
}
<!-- language: lang-css -->
* {
box-sizing: border-box;
}
body {
margin: 0;
height: 100vh;
width: 100%;
}
main {
height: 100%;
box-sizing: border-box;
}
.maingrid-wrapper {
box-sizing: border-box;
display: flex;
flex-direction: row;
flex-wrap: wrap;
position: relative;
display: flex;
width: 100%;
height: 100%;
}
.maingrid-content {
/* border: red solid; */
}
.image {
flex: 2 1 60%;
flex-grow: 2;
height: 90%;
background-color: lightblue;
}
.sidehint {
background-color: lightgreen;
flex: 1 1 40%;
height: 90%;
}
.footer-wrapper {
background-color: lightpink;
height: 10%;
width: 100%;
display: flex;
flex-direction: row;
}
@media all and (max-width: 640px) {
.maingrid-wrapper {
box-sizing: border-box;
display: flex;
flex-direction: row;
flex-wrap: wrap;
position: relative;
display: flex;
width: 100%;
height: 100%;
background-color: lightgrey;
}
.maingrid-content {
/* border: red solid; */
box-sizing: border-box;
}
.image {
height: 70%;
flex: 1 1 100%;
flex-grow: 2;
background-color: lightblue;
}
.sidehint {
height: 20%;
background-color: lightgreen;
}
.footer-wrapper {
height: 10%;
width: 100%;
display: flex;
background-color: lightpink;
}
}
<!-- language: lang-html -->
<body>
<main>
<div class="maingrid-wrapper">
<div class="image maingrid-content">A</div>
<div class="sidehint maingrid-content" id="hint" style="display:none">B</div>
<div class="footer-wrapper maingrid-content">
<input class="bulb-input" id="hint-toggle" type="checkbox" onchange="visCheck()">C
</div>
</div>
</main>
</body>
<!-- end snippet -->
英文:
I want the entire window divided into two or three areas - depending on the state of a checkbox. If the box is not checked I want the second area to be hidden while I want the first area to grow into this additional window space.
The way I set it up for larger screens (>640px) works perfectly fine:
checked box large screens and unchecked box lange screens
For smaller screens, however, I run into trouble. Here the second area is placed in between area 1 and 3:
checked box small screens
But once I uncheck the box, area 1 remains the same and does not grow into the space of the hidden area 2. Instead area 3 moves up and centers itself in the now available space (grey background):
unchecked box small screens
I think I know why this happens but have not been able to come up with a solution yet.
As I used flex-direction: column
for the wrapper the flex-grow:1
only works horizontally for the children.
Therefore I at first tried to use flex-direction: row
but that put the elements next to each other horizontally. Even if I tried to use flex-wrap:wrap
while restricting the wrapper to the viewport width.
The grey space above and below area 3 seems to be the result of the height:20%
of the hidden area 2. While I thought that using display:none
would completely stop this height from being considered this seemed not to be the case.
Therefore I secondly tried to use Javascript to change the height:20%
of the hidden area 2 to 0% only if the box is unchecked and the screen-size is below the threshhold. But in the dev tools it looked like document.getElementById("hint").style.height="0%"
did not change anything at all. But even if it did it seems like setting the height to 0% directly in the css wont solve my issue as the grey wrapper area still remains.
Here is my attemot of a reproducible example but I am not sure if it is minimal and of any help:
<!-- begin snippet: js hide: true console: true babel: false -->
<!-- language: lang-js -->
function visCheck (){
if (document.getElementById("hint").style.display=="block"){ document.getElementById("hint").style.display="none";
}
else if (document.getElementById("hint").style.display=="none"){
document.getElementById("hint").style.display="block";
}
else{ document.getElementById("hint").style.display="block";
}
}
<!-- language: lang-css -->
*{
box-sizing: border-box;
}
body{
margin: 0;
height: 100vh;
width: 100%;
}
main{
height: 100%;
box-sizing: border-box;
}
.maingrid-wrapper{
box-sizing: border-box;
display: flex;
flex-direction: row;
flex-wrap: wrap;
position: relative;
display: flex;
width: 100%;
height: 100%;
}
.maingrid-content{
/* border: red solid; */
}
.image{
flex:2 1 60%;
flex-grow:2;
height: 90%;
background-color: lightblue;
}
.sidehint{
background-color: lightgreen;
flex:1 1 40%;
height: 90%;
}
.footer-wrapper{
background-color: lightpink;
height:10%;
width: 100%;
display: flex;
flex-direction: row;
}
@media all and (max-width: 640px){
.maingrid-wrapper{
box-sizing: border-box;
display: flex;
flex-direction: row;
flex-wrap: wrap;
position: relative;
display: flex;
width: 100%;
height: 100%;
background-color: lightgrey;
}
.maingrid-content{
/* border: red solid; */
box-sizing: border-box;
}
.image{
height: 70%;
flex:1 1 100%;
flex-grow: 2;
background-color:lightblue;
}
.sidehint{
height: 20%;
background-color: lightgreen;
}
.footer-wrapper{
height:10%;
width: 100%;
display: flex;
background-color: lightpink;
}
}
<!-- language: lang-html -->
<body>
<main>
<div class="maingrid-wrapper">
<div class="image maingrid-content">A</div>
<div class="sidehint maingrid-content"
id="hint" style="display:none">B</div>
<div class="footer-wrapper
maingrid-content">
<input class="bulb-input" id="hint-toggle"
type="checkbox"
onchange="visCheck()">C</div>
</div>
</main>
</body>
<!-- end snippet -->
答案1
得分: 0
我整理了您的CSS,其中包含了冗余、默认值和不必要的声明。
您的CSS将受益于“移动优先”的方法,其中媒体查询用于在视口扩展时添加样式,而不是使用媒体查询来覆盖较窄视口的声明。
* {
box-sizing: border-box;
}
body {
margin: 0;
height: 100vh;
}
main {
height: 100%;
}
.maingrid-wrapper {
display: flex;
flex-wrap: wrap;
height: 100%;
}
.maingrid-content {
/* border: red solid; */
}
.image {
flex: 2;
height: 90%;
background-color: lightblue;
}
.sidehint {
flex: 1;
background-color: lightgreen;
}
.footer-wrapper {
background-color: lightpink;
height: 10%;
width: 100%;
}
@media all and (max-width: 640px) {
.maingrid-wrapper {
flex-direction: column;
background-color: lightgrey;
}
}
请注意,我只提供了CSS部分的翻译。如果您需要其他部分的翻译,请告诉我。
英文:
I cleaned up your CSS, which was bloated with redundancy, default values, and extraneous declarations.
Your CSS would benefit from a "mobile first" approach where media queries are used to add styling as the viewport widens, instead of using media queries to overwrite the declarations for narrower viewports.
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
function visCheck() {
if (document.getElementById("hint").style.display=="block") {
document.getElementById("hint").style.display="none";
}
else if (document.getElementById("hint").style.display=="none") {
document.getElementById("hint").style.display="block";
}
else {
document.getElementById("hint").style.display="block";
}
}
<!-- language: lang-css -->
* {
box-sizing: border-box;
}
body {
margin: 0;
height: 100vh;
}
main{
height: 100%;
}
.maingrid-wrapper{
display: flex;
flex-wrap: wrap;
height: 100%;
}
.maingrid-content{
/* border: red solid; */
}
.image{
flex: 2;
height: 90%;
background-color: lightblue;
}
.sidehint{
flex: 1;
background-color: lightgreen;
}
.footer-wrapper{
background-color: lightpink;
height: 10%;
width: 100%;
}
@media all and (max-width: 640px){
.maingrid-wrapper{
flex-direction: column;
background-color: lightgrey;
}
}
<!-- language: lang-html -->
<body>
<main>
<div class="maingrid-wrapper">
<div class="image maingrid-content">A</div>
<div class="sidehint maingrid-content" id="hint" style="display:none">B</div>
<div class="footer-wrapper maingrid-content">
<input class="bulb-input" id="hint-toggle" type="checkbox" onchange="visCheck()">C</div>
</div>
</main>
</body>
<!-- end snippet -->
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论