首页 > 解决方案 > Flexbox 难题 - 如何将 flex box 嵌套在自定义元素的层中并通过媒体查询获得所需的结果

问题描述

这是一个关于在列方向使用时与 flexbox 对齐的问题。我发现的问题是所有文档都使用行中的示例,并且在更改轴时某些内容似乎没有翻译。

我正在构建一个 Web 单页 Web 应用程序,该应用程序由多层自定义元素构成。为简单起见,我排除了页面之间的选择,因此此视图是一个页面内容的摘要,其他页面基本上被换出(使用litHtmlcache由动态对象选择控制的指令)。我的层次结构是这样的(除了<app-page>元素之外,所有其他元素的内容都只在 shadowroot 中,所以不像这里显示的子元素。 <app-page>更像是一个实用项目,因此它在 shadow root 中定义了插槽及其真实孩子们被吊起来了。我用一些线条来表示它的影子根和它真正的孩子之间的区别。<app-error>大部分时间都没有内容 - 当出现错误时它会获取内容,并且此时<app-session>不显示任何内容。

<main-app>
  <header>My App Header Bar with menu button and App-logo etc</header>
  <section>
    <app-error></app-error>
    <app-session>
      <app-verify-email>
        <app-page>
          <--
            <header>Different sort of Logo </header>
            <slot></slot>
            <div id="wedge"></div>
            <slot name="action></slot>
          -->
          <h1>Verify Email Header</h1>
          <p>Some text about Verifying Email</p>
          <input type="email" value="${this.email}"/.
          <button slot="action">Send</button>
          <button slot="action>Cancel</button>
        </app-page>
      </app-verify-email>`,
    </app-session>
  </section>
</main-app>`  

我的目标如下正常情况下,我假设我们有一部手机,主应用程序的标题栏将位于屏幕底部,以使其上的菜单按钮关闭用户的拇指。我通过给 main-app 一种风格来实现这一点

:host {
  height: 100vh;
  display: flex;
  flex-direction: column-reverse;
}
@media (min-width: 500px) {
  :host {
    flex-direction: column;
  }
}

为了支撑链中的其他元素,使它们都被完全拉伸,我决定尝试使用它们

:host {
  display: flex;
  flex-direction: row;
  align-items: stretch;
}

这允许他们填写完整的内容,但是(我希望)允许在有要显示的内容<app-session>时折叠下来<app-error>(并且不会因为将选择错误阶段。

另一个考虑因素是,我希望其余内容位于顶部,除了“操作”插槽内的按钮。首先,在正常情况下,按钮应位于标题栏上方的底部,但在更宽的屏幕情况下,它们应位于内容下方的顶部。我正在尝试通过主机样式来实现:-

:host {
  display: flex;
  flex-direction: column;
}
#wedge {
  display: block;
  flex:1;
}
@media-query (min-width: 500px) {
  #wedge {
     display: none;
     flex:0;
  }
}

但它不工作,我不知道为什么?

我尝试了其他选项,比如不使用楔形而是放在align-item: flex end;按钮槽上,但这也不起作用。

正如我上面所说,我正在努力寻找基于列布局的弹性框示例,因此我可以帮助研究如何实现我的目标。

标签: cssflexbox

解决方案


我做了一个测试用例,并一直在努力解决这个问题。我认为诀窍是在某些东西是 flex-box 时有所保留,但也要利用 height=100% 来强制非 flexbox 项目填充空间,以便其内部的 flexbox 项目可以在整个空间。

真正的关键是使用 margin:auto 作为将按钮块推到底部的一种方式,即使内容是合理的 flex-start。这似乎是将弹性容器中的项目分开的“标准”方式;

<!DOCTYPE html>
<html lang="en">
  <head>
    <style>
      html {
        background: #ffffff;
      }

      body {
        margin: 0;
        min-height: 100vh;
        font-family: sans-serif;
        line-height: 1.5;
        letter-spacing: 0.1em;
        background-color: #fafafa;
        color: #333;
      }
      .main-app {
        height: 100vh;
        display: flex;
        flex-direction: column-reverse;
        justify-content:flex-start;
      }
      .main-app>header {

          height: 64px;
          color:  white;
          background-color: #adcabd;
          display: flex;
          flex-direction: row;
          justify-content: space-between;
          align-items:center;
      }
      .main-app>section {
        height: calc(100vh - 64px);
        display: flex;
        flex-direction: column;
      }

      .app-session {
        display:block;
        flex:1;
      }
      .app-verify-email {
        height: 100%;
        display:flex;
        flex-direction:column;
        align-items: center;
      }

      .app-page{
        height:100%;
        display: flex;
        flex-direction:column;
        max-width: 600px;
        justify-content: start;
        padding:10px;
      }
      .app-page header {
        height: 64px;
        margin: 0 auto;
        padding: 0;
      }


      .action {
        display: flex;
        width:100%;
        flex-direction:row;
        flex-wrap: wrap;
        justify-content: space-evenly;
        margin-top:auto;
      }

      @media (min-width: 500px) {
        .main-app {
          flex-direction: column;
        }
        .action {
          margin-top: 10px;
        }
        .app-page {
          min-width:600px;
          height: auto;
        }
      }
      @media (min-width: 501px) {
        .app-page {

          border-radius: 10px;
          box-shadow: 0px 0px 38px -2px rgba(0, 0, 0, 0.5);

        }
      }



    </style>

  </head>
  <body>
    <div class="main-app">
      <header><img src="/appimages/site_logo.png"/><div>v1.0.0</div></header>
      <section>
        <div class="app-error"><!--Error in progress--></div>
        <div class="app-session">
          <div class="app-verify-email">
            <div class="app-page">
              <header>Different sort of Logo </header>
              <section class="container">
                <h1>Verify Email Header</h1>
                <p>Some text about Verifying Email</p>
                <input type="email" value="alan@chandlerfamily.org.uk"/>
              </section>

              <div class="action">
                <button>Send</button>
                <button cancel>Cancel</button>
              </div>
            </app-page>
          </div> 
        </div>
      </section>
    </div>  
  </body>
</html>


推荐阅读