如何使一个flex-grow元素占据一个隐藏的flex项的空间?

huangapple go评论66阅读模式
英文:

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(&quot;hint&quot;).style.height=&quot;0%&quot; 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(&quot;hint&quot;).style.display==&quot;block&quot;){ document.getElementById(&quot;hint&quot;).style.display=&quot;none&quot;;
}
else if (document.getElementById(&quot;hint&quot;).style.display==&quot;none&quot;){
document.getElementById(&quot;hint&quot;).style.display=&quot;block&quot;;
}
else{   document.getElementById(&quot;hint&quot;).style.display=&quot;block&quot;;
}
}

<!-- 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 -->

&lt;body&gt;
&lt;main&gt;
&lt;div class=&quot;maingrid-wrapper&quot;&gt;
&lt;div class=&quot;image maingrid-content&quot;&gt;A&lt;/div&gt;
&lt;div class=&quot;sidehint maingrid-content&quot;
id=&quot;hint&quot; style=&quot;display:none&quot;&gt;B&lt;/div&gt;
&lt;div class=&quot;footer-wrapper 
maingrid-content&quot;&gt;
&lt;input class=&quot;bulb-input&quot; id=&quot;hint-toggle&quot;
type=&quot;checkbox&quot;
onchange=&quot;visCheck()&quot;&gt;C&lt;/div&gt;
&lt;/div&gt;
&lt;/main&gt;
&lt;/body&gt;

<!-- 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(&quot;hint&quot;).style.display==&quot;block&quot;) {
document.getElementById(&quot;hint&quot;).style.display=&quot;none&quot;;
}
else if (document.getElementById(&quot;hint&quot;).style.display==&quot;none&quot;) {
document.getElementById(&quot;hint&quot;).style.display=&quot;block&quot;;
}
else {
document.getElementById(&quot;hint&quot;).style.display=&quot;block&quot;;
}
}

<!-- 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 -->

&lt;body&gt;
&lt;main&gt;
&lt;div class=&quot;maingrid-wrapper&quot;&gt;
&lt;div class=&quot;image maingrid-content&quot;&gt;A&lt;/div&gt;
&lt;div class=&quot;sidehint maingrid-content&quot; id=&quot;hint&quot; style=&quot;display:none&quot;&gt;B&lt;/div&gt;
&lt;div class=&quot;footer-wrapper maingrid-content&quot;&gt;
&lt;input class=&quot;bulb-input&quot; id=&quot;hint-toggle&quot; type=&quot;checkbox&quot; onchange=&quot;visCheck()&quot;&gt;C&lt;/div&gt;
&lt;/div&gt;
&lt;/main&gt;
&lt;/body&gt;

<!-- end snippet -->

huangapple
  • 本文由 发表于 2023年5月29日 07:51:25
  • 转载请务必保留本文链接:https://go.coder-hub.com/76354013.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定