内联块元素换行时的CSS,父包装器不适合新宽度

Posted

技术标签:

【中文标题】内联块元素换行时的CSS,父包装器不适合新宽度【英文标题】:CSS when inline-block elements line-break, parent wrapper does not fit new width 【发布时间】:2016-05-01 22:44:42 【问题描述】:

如果内容因屏幕宽度而换行,如何让inline-block 元素适应其内容宽度?

<!-- parent inline-block -->
<div style='display: inline-block;'>
    <div style='display: inline-block; width:200px;'></div>
    <!--
        If this child line breaks, 
        two 200px wide blocks are stacked vertically.
        That should make the parent width 200px,
        but the parent stays much wider than that
    -->
    <div style='display: inline-block; width:200px;'></div>
</div>

我想不出如何表达这个问题,所以听起来很简单,但我整理了一个简单的 JSFiddle 说明。

#wide 
  position: relative;
  width: 100%;
  border: 1px solid black;
  padding: 5px;

#narrow 
  position: relative;
  width: 175px;
  border: 1px solid black;
  padding: 5px;

.wrap 
  display: inline-block;
  border: 1px solid green;
  margin: auto;

.inlineblock 
  display: inline-block;
  vertical-align: top;
  background: red;
  min-width: 100px;
  min-height: 100px;
  border: 1px solid black;
<section id='wide'>
  <div class='wrap'>
    <div class='inlineblock'></div>
    <div class='inlineblock'></div>
  </div>
</section>
<p>
  When the red inline-blocks are forced to line break, how do you make a parent with display:inline-block (the green border) snap to fit? How do you get rid of all the extra horiztonal space in the lower green bordered div?
</p>
<section id='narrow'>
  <div class='wrap'>
    <div class='inlineblock'></div>
    <div class='inlineblock'></div>
  </div>
</section>

【问题讨论】:

你不能……这不是线盒模型的工作原理。 您可能还想将父 div 宽度设置为 200px? 使用 white-space:preline 我可以摆脱额外的宽度空间,但它会强制 inline-block 元素从一开始就换行。没有办法只在换行时做前置空白吗? 我认为你应该搜索 CSS Flex 它可能是你需要的...... @miguelmpn 不……连 flexbox 都做不到。 【参考方案1】:

你不能。默认情况下,inline-block 元素有一个shrink-to-fit width:

收缩到适合的宽度是:min(max(preferred minimum width, available width), preferred width)

那么,

preferred minimum width &lt;= preferred width &lt;= available width 时,宽度将是 preferred width,如您所愿。 available width &lt;= preferred minimum width &lt;= preferred width 时,宽度将是 preferred minimum width,如您所愿。 preferred minimum width &lt;= available width &lt;= preferred width 时,宽度为available width,即使你不喜欢。

如果你真的不想这样,我想你可以用JS添加一个resize事件监听器,并手动设置所需的宽度。

【讨论】:

@Paulie_D 是的,浮动也使用缩小以适应宽度(实际上它是为它们定义的)。基本上所有的原子内联级盒子都做同样的事情。 谢谢...这也是我的理解。奇怪的是这还没有解决...似乎是一个常见的设计要求。 @Paulie_D 也许是有意的,以避免突然改变宽度和可能的圆形定义。但在没有问题的情况下最好有这个。 @Paulie_D BTW,flex 项目使用 max-content 而不是 fit-content/shrink-to-fit。我已经自我回答了Should flex item overflow the flex container instead of breaking lines? 来解释这一点。【参考方案2】:

inline-block 元素无法实现这种布局——正如@Oriol 所展示的那样——但是,

CSS Grid 可以实现这种布局。

body 
  margin: 0;


ul 
  display: inline-grid;
  grid-template-columns: repeat(auto-fit, 100px);
  min-width: 50vw;
  
  /* decorative properties */
  grid-gap: 10px;
  padding: 0;
  list-style: none;
  border: 5px solid salmon;
  box-sizing: border-box;
  
  /* center the grid */ 
  position: relative;
  left: 50vw;
  transform: translateX(-50%);

li 
  background-color: lightblue;
  height: 100px;
<ul>
  <li>1</li>
  <li>2</li>
  <li>3</li>
  <li>4</li>
  <li>5</li>
  <li>6</li>
  <li>7</li>
  <li>8</li>
  <li>9</li>
  <li>10</li>
  <li>11</li>
  <li>12</li>
  <li>13</li>
  <li>14</li>
  <li>15</li>
  <li>16</li>
  <li>17</li>
  <li>18</li>
  <li>19</li>
  <li>20</li>
  <li>21</li>
  <li>22</li>
</ul>

Codepen demo(一定要调整大小)

基本上相关代码归结为:

ul 
  display: inline-grid; /* (1) */
  grid-template-columns: repeat(auto-fit, 100px); /* 100px = column width - (2) */
  min-width: 50vw; /* or any user-defined min-width (3) */

1) 使容器元素成为内联网格容器。这将导致网格“收缩包装”其内容 - 以便网格宽度永远不会比其内容更宽。

2) 使用响应式布局设置网格(auto-fill / auto-fit 值用于响应式布局)。如果一行中没有空间容纳下一个项目 - 它会换到下一行。

当响应式布局与内联网格一起使用时 - 网格宽度将等于网格中一项的宽度。 (当没有明确设置宽度/最小宽度时 - like this)

3) 将容器设置为最小宽度,该最小宽度表示(最多 - 小于一个部分项)容器所需的最大宽度

因此,如果给定的最小宽度恰好适合一定数量的项目 - 这意味着这也将是网格的 最大 宽度,因为下一个项目将换行。

但是,如果最小宽度不完全对应于“n”个项目的宽度,因为它也适合第 n+1 个项目的一部分 - 在这种情况下,网格将略微扩展以完全适合 n+第 1 项 - 第 n+2 项环绕到下一行。

【讨论】:

如果我们想在父容器中容纳尽可能多的100px 列,我们可以使用min-width: calc(100% - 100px); 对我来说不幸的是,这似乎不适用于容器内具有动态宽度的项目,例如文本,以及动态最大宽度。想如果我将每个单词都包装在一个跨度中,可能会有某种使用方式。 是的,我想这不适用于动态大小(宽度方向)的内容,因为 A)你有一个网格结构和 B)你需要以某种方式指定网格列宽度。 当我尝试使用 max-width:870px;min-width:320px 修改它时(目的是尝试显示尽可能多的列,最多 8 个(8 * 100px + 7 * 10px 间隙),它没有t 缩小。我可以将窗口设置为 600px 宽,它仍然是 870px 宽。我做错了什么?

以上是关于内联块元素换行时的CSS,父包装器不适合新宽度的主要内容,如果未能解决你的问题,请参考以下文章

换行时如何使父元素缩小?

当文本换行到两行时,块元素采用全宽

在 CSS 中以动态宽度居中内联块

关于CSS的内联和块元素

详解HTML块级元素内联元素和内联块元素

在内联元素中的块元素会自动换行..求解答~谢谢~