使元素在容器中免费使用 space

Make element consume free space in a container

我有一个页面应该是这样的:

这里的 header 就是我遇到问题的原因。它包含:

  1. 一个图标,位于最左端,具有固定大小

  2. 一个标题,就在图标的右边,它占用的空间与space一样多,足以将标题文本排成一行

  3. 有时,在标题下方安排一个副标题

  4. 有时,标题右侧会出现一个带有一些辅助内容的框,用完任何 left-over space

出于各种原因(包括但不限于完美主义),我不想嵌套这些元素,而且我几乎...除了我可以'得到最后一个框,"auxiliary stuff",来填充剩余的space。

我将其构建为列,图标高度为 100%,标题和副标题高度 <50%,辅助框高度为 100%。给辅助框一个固定的宽度效果很好,但是当我试图让它水平增长 width: 100% 时,100% 似乎意味着“周围框的 100%”(在我的例子中,<heading> ) 而不是“剩余 space 的 100%”,这会使其溢出。

html, body { padding: 0; margin: 0; height: 100%; width: 100%; font: 10px sans-serif }

/* Colors to please the eyes */
article { border: 5em solid limegreen; }
header { border: 1px solid tomato; }
.icon { background-color: cyan; }
h1 { background-color: magenta; }
h2 { background-color: yellow; }
.aux { background-color: lavender; }

/* Arrange them boxes */
article {
    display: flex;
    flex-flow: column nowrap;
}
header {
    display: flex;
    flex-flow: column wrap;
    align-content: flex-start;
    height: 5em;
}
.icon { width: 5em; height: 100% }
h1 { font-size: 200%; margin: 0 }
h2 { font-size: 150%; margin: 0  }
.aux { height: 100%; width: 100%; }
<article>
  <header>
    <div class=icon>ICON</div>
    <h1>Main header</h1>
    <h2>Subheading here</h2>
    <div class=aux>MOAR STUFF</div>
  </header>
  <section>
    Lorem ipsum dolor sit amet...
  </section>
</article>

我可以让最后一个盒子水平增长,而不改变标记吗?

我不知道有什么简单的方法可以在不更改标记的情况下解决这个问题。问题是你同时进行了包裹和拉伸。如果您删除了包裹的部分,您可以更改弯曲方向并拉伸最终元素。

下面是一个对标记几乎没有改动的解决方案。我将标题和副标题放在一个容器中。

html, body { padding: 0; margin: 0; height: 100%; width: 100%; font: 10px sans-serif }

/* Colors to please the eyes */
article { border: 5em solid limegreen; }
header { border: 1px solid tomato; }
.icon { background-color: cyan; }
h1 { background-color: magenta; }
h2 { background-color: yellow; }
.aux { background-color: lavender; }

/* Arrange them boxes */
article {
    display: flex;
    flex-flow: column nowrap;
}

header {
    display: flex;
    flex-flow: row wrap;
    align-content: flex-start;
    height: 5em;
}

.icon, h1, h2 {
  flex-shrink: noshrink;
}

.icon { width: 5em; height: 100% }
h1 { font-size: 200%; margin: 0 }
h2 { font-size: 150%; margin: 0  }

.aux { height: 100%; flex-grow: 1; }
<!DOCTYPE html>
<html>
    <head>
        <title>Flexicols</title>
    </head>
    <body>
        <article>
            <header>
                <div class=icon>ICON</div>
                <div class='subtitled-heading'>
                  <h1>Main header</h1>
                  <h2>Subheading here</h2>
                </div>
                <div class=aux>MOAR STUFF</div>
            </header>
            <section>
                Lorem ipsum dolor sit amet...
            </section>
        </article>
    </body>
</html>

更新的解决方案(现在 CSS 网格可用)

随着CSS网格的出现,布局相对简单。无需更改加价。

一条关键规则是:

grid-template-columns: 5em auto 1fr;

它建立了一个三列的网格。每列的宽度都是指定的,并且符合题目的要求。

fr 单元在概念上类似于 flex-grow 属性。它旨在免费消费 space.

header {
  display: grid;
  grid-template-columns: 5em auto 1fr; /* set 3 columns at specified widths */
  grid-template-rows: 50% 50%;         /* set 2 rows at specified heights */
  height: 5em;  
}

.icon {
  grid-row: span 2;                    /* span two rows (full height) */
}

h1 {}                                 /* placed automatically based on source order */

h2 {
  grid-column: 2;                      /* placed in column 2 */
}

.aux {
  grid-column: 3;
  grid-row: 1 / span 2;
}

/* non-essential decorative styles */
body    { margin: 0; font: 10px sans-serif }
article { border: 5em solid limegreen; }
header  { border: 1px solid tomato;    }
.icon   { background-color: cyan;      }
h1      { background-color: magenta; font-size: 200%; margin: 0; }
h2      { background-color: yellow;; font-size: 150%; margin: 0; }
.aux    { background-color: lavender;  }
<article>
  <header>
    <div class=icon>ICON</div>
    <h1>Main header</h1>
    <h2>Subheading here</h2>
    <div class=aux>MOAR STUFF</div>
  </header>
  <section>
    Lorem ipsum dolor sit amet...
  </section>
</article>

jsFiddle demo


旧(电网前)解决方案

如果您为包含h1h2的列定义宽度,那么让辅助框("moar stuff")拉伸其父框的剩余宽度不是问题。

试试这个:

HTML(无变化)

CSS

h1 {
   font-size: 200%;
   margin: 0;
   width: 10em; /* new */
}

.aux {
   height: 100%;
   width: calc(100% - 10em - 5em - 10em); /* width less header column less icon 
                                             less green border */
}

jsFiddle demo

本质上需要更改的内容(根据您离开 HTML as-is 的规则)是:

  • 使header填充其parent
  • header 背景到薰衣草色到假 aux 填充 100%(aux 将 根据需要增长)
  • min/max height/width of aux 所以它留在 parent
  • 里面
  • h1h2 的高度设置为 50%,以便它们环绕。
  • h1h2 需要填满他们的盒子,所以 flex 会增长。

小更新

  • 使header截断溢出
  • 添加 box-sizing 规则以使所有内容正确对齐

html,
body {
  box-sizing: border-box;
  padding: 0;
  margin: 0;
  height: 100%;
  width: 100%;
}
*,
*:before,
*:after {
  box-sizing: inherit
}
/* Colors to please the eyes */

article {
  border: 5em solid limegreen;
}
header {
  border: 1px solid tomato;
}
.icon {
  background-color: cyan;
}
h1 {
  background-color: magenta;
}
h2 {
  background-color: yellow;
}
.aux {
  background-color: lavender;
}
/* Arrange them boxes */

article {
  display: flex;
  flex-flow: column nowrap;
}
header {
  background-color: lavender;
  display: flex;
  overflow: hidden;
  width: 100%;
  flex-flow: column wrap;
  align-content: flex-start;
  height: 5em;
}
.icon {
  width: 5em;
  height: 100%
}
h1 {
  font-size: 200%;
  margin: 0;
  height: 50%;
}
h2 {
  font-size: 150%;
  margin: 0;
  height: 50%;
}
.aux {
  min-height: 100%;
  max-width: 100%
}
<article>
  <header>
    <div class=icon>ICON</div>
    <h1>Main header</h1>
    <h2>Subheading here</h2>
    <div class=aux>MOAR STUFF</div>
  </header>
  <section>
    Lorem ipsum dolor sit amet...
  </section>
</article>

我的回答

html,
body {
  padding: 0;
  margin: 0;
  height: 100%;
  width: 100%;
  font: 10px sans-serif
}
/* Colors to please the eyes */

article {
  border: 5em solid limegreen;
}
header {
  border: 1px solid tomato;
}
.icon {
  background-color: cyan;
}
h1 {
  background-color: magenta;
}
h2 {
  background-color: yellow;
}
.aux {
  background-color: lavender;
}
header {
  height: 5em;
  position: relative;
}
.icon {
  width: 5em;
  height: 100%;
  position: absolute;
}
h1 {
  font-size: 200%;
  margin: 0 0 0 calc(5em / 2); /* adjust for the font size */
  float: left;
  height: 1px;
}
h2 {
  font-size: 150%;
  margin: calc(1em * 200 / 150) 0 0 calc(5em / 1.5); /* adjust for the font size */
  float: left;
  clear: left;
}
.aux {
  overflow: hidden;
  height: 100%;
  text-align: center;
}
<article>
  <header>
    <div class=icon>ICON</div>
    <h1>Main header</h1>
    <h2>Subheader here</h2>
    <div class=aux>
      MOAR STUFF MOAR STUFF
    </div>
  </header>
  <section>
    Lorem ipsum dolor sit amet...
  </section>
</article>

优点是 .aux 具有正确的大小,因此您可以在其中放置一些东西。缺点是你失去了主要 header 的背景,所以你必须在另一个元素上伪造它。但这是可以做到的。